File: version_updater_win.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (164 lines) | stat: -rw-r--r-- 6,825 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/help/version_updater.h"

#include <memory>
#include <string>

#include "base/functional/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/task/thread_pool.h"
#include "base/win/win_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/upgrade_util.h"
#include "chrome/browser/google/google_update_win.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/native_widget_types.h"

namespace {

// Windows implementation of version update functionality, used by the WebUI
// About/Help page.
class VersionUpdaterWin : public VersionUpdater, public UpdateCheckDelegate {
 public:
  // |owner_widget| is the parent widget hosting the update check UI. Any UI
  // needed to install an update (e.g., a UAC prompt for a system-level install)
  // will be parented to this widget. |owner_widget| may be given a value of
  // nullptr in which case the UAC prompt will be parented to the desktop.
  explicit VersionUpdaterWin(gfx::AcceleratedWidget owner_widget)
      : owner_widget_(owner_widget), weak_factory_(this) {}

  VersionUpdaterWin(const VersionUpdaterWin&) = delete;
  VersionUpdaterWin& operator=(const VersionUpdaterWin&) = delete;

  ~VersionUpdaterWin() override = default;

  // VersionUpdater:
  void CheckForUpdate(StatusCallback callback, PromoteCallback) override {
    // There is no supported integration with Google Update for Chromium.
    callback_ = std::move(callback);

    callback_.Run(CHECKING, 0, false, false, std::string(), 0,
                  std::u16string());
    DoBeginUpdateCheck(false /* !install_update_if_possible */);
  }

  // UpdateCheckDelegate:
  void OnUpdateCheckComplete(const std::u16string& new_version) override {
    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    if (new_version.empty()) {
      // Google Update says that no new version is available. Check to see if a
      // restart is needed for a previously-applied update to take effect.
      base::ThreadPool::PostTaskAndReplyWithResult(
          FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
          base::BindOnce(&upgrade_util::IsUpdatePendingRestart),
          base::BindOnce(&VersionUpdaterWin::OnPendingRestartCheck,
                         weak_factory_.GetWeakPtr()));
      // Early exit since callback_ will be Run in OnPendingRestartCheck.
      return;
    }

    // Notify the caller that the update is now beginning and initiate it.
    DoBeginUpdateCheck(true /* install_update_if_possible */);
    callback_.Run(UPDATING, 0, false, false, std::string(), 0,
                  std::u16string());
  }

  void OnUpgradeProgress(int progress,
                         const std::u16string& new_version) override {
    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    callback_.Run(UPDATING, progress, false, false, std::string(), 0,
                  std::u16string());
  }

  void OnUpgradeComplete(const std::u16string& new_version) override {
    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    callback_.Run(NEARLY_UPDATED, 0, false, false, std::string(), 0,
                  std::u16string());
  }

  void OnError(GoogleUpdateErrorCode error_code,
               const std::u16string& html_error_message,
               const std::u16string& new_version) override {
    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    std::u16string message;
    Status status = FAILED;

    switch (error_code) {
      case GOOGLE_UPDATE_DISABLED_BY_POLICY:
        status = DISABLED_BY_ADMIN;
        message = l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY);
        break;
      case GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY:
        status = DISABLED_BY_ADMIN;
        message =
            l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY_MANUAL);
        break;
      default:
        // html_error_message mentions error_code so don't combine messages.
        if (html_error_message.empty()) {
          message =
              l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR, error_code);
        } else {
          message = l10n_util::GetStringFUTF16(
              IDS_ABOUT_BOX_ERROR_DURING_UPDATE_CHECK, html_error_message);
        }
        break;
    }
    callback_.Run(status, 0, false, false, std::string(), 0, message);
  }

 private:
  void DoBeginUpdateCheck(bool install_update_if_possible) {
    // Disconnect from any previous attempts to avoid redundant callbacks.
    weak_factory_.InvalidateWeakPtrs();
    BeginUpdateCheck(g_browser_process->GetApplicationLocale(),
                     install_update_if_possible, owner_widget_,
                     weak_factory_.GetWeakPtr());
  }

  // A task run on the UI thread with the result of checking for a pending
  // restart.
  void OnPendingRestartCheck(bool is_update_pending_restart) {
    callback_.Run(is_update_pending_restart ? NEARLY_UPDATED : UPDATED, 0,
                  false, false, std::string(), 0, std::u16string());
  }

  // The widget owning the UI for the update check.
  gfx::AcceleratedWidget owner_widget_;

  // Callback used to communicate update status to the client.
  StatusCallback callback_;

  // Used for callbacks.
  base::WeakPtrFactory<VersionUpdaterWin> weak_factory_;
};

}  // namespace

std::unique_ptr<VersionUpdater> VersionUpdater::Create(
    content::WebContents* web_contents) {
  // Retrieve the HWND for the browser window that is hosting the update check.
  // This will be used as the parent for a UAC prompt, if needed. It's possible
  // this this window will no longer have focus by the time UAC is needed. In
  // that case, the UAC prompt will appear in the taskbar and will require a
  // user click. This is the least surprising thing we can do for the user, and
  // is the intended behavior for Windows applications.
  // It's also possible that the browser window hosting the update check will
  // have been closed by the time the UAC prompt is needed. In this case, the
  // web contents may no longer be hosted in a window, leading either
  // GetTopLevelNativeWindow or GetHost to return null. Passing nullptr to
  // VersionUpdaterWin will then also cause the UAC prompt to appear in the task
  // bar.
  gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
  aura::WindowTreeHost* window_tree_host = window ? window->GetHost() : nullptr;
  return std::make_unique<VersionUpdaterWin>(
      window_tree_host ? window_tree_host->GetAcceleratedWidget() : nullptr);
}