summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/webui/help/version_updater_win.cc
blob: 1c869667d3f821aa2e5f93b0374f6fb6e4639aee (plain)
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
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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_win.h"

#include "base/memory/weak_ptr.h"
#include "base/task_runner_util.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/upgrade_util.h"
#include "chrome/browser/lifetime/application_lifetime.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"

VersionUpdaterWin::VersionUpdaterWin(gfx::AcceleratedWidget owner_widget)
    : owner_widget_(owner_widget), weak_factory_(this) {
}

VersionUpdaterWin::~VersionUpdaterWin() {
}

void VersionUpdaterWin::CheckForUpdate(const StatusCallback& callback,
                                       const PromoteCallback&) {
  // There is no supported integration with Google Update for Chromium.
  callback_ = callback;

  // On-demand updates for Chrome don't work in Vista RTM when UAC is turned
  // off. So, in this case, the version updater must not mention
  // on-demand updates. Silent updates (in the background) should still
  // work as before - enabling UAC or installing the latest service pack
  // for Vista is another option.
  if (!(base::win::GetVersion() == base::win::VERSION_VISTA &&
        (base::win::OSInfo::GetInstance()->service_pack().major == 0) &&
        !base::win::UserAccountControlIsEnabled())) {
    callback_.Run(CHECKING, 0, base::string16());
    BeginUpdateCheckOnFileThread(false /* !install_update_if_possible */);
  }
}

void VersionUpdaterWin::RelaunchBrowser() const {
  chrome::AttemptRestart();
}

void VersionUpdaterWin::OnUpdateCheckComplete(
    const base::string16& new_version) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  Status status = CHECKING;
  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.
    if (base::PostTaskAndReplyWithResult(
            content::BrowserThread::GetBlockingPool(),
            FROM_HERE,
            base::Bind(&upgrade_util::IsUpdatePendingRestart),
            base::Bind(&VersionUpdaterWin::OnPendingRestartCheck,
                       weak_factory_.GetWeakPtr()))) {
      // Early exit since callback_ will be Run in OnPendingRestartCheck.
      return;
    }
    // Failure to post the task means that Chrome is shutting down. A pending
    // update (if there is one) will be applied as Chrome exits, so tell the
    // caller that it is up to date in either case.
    status = UPDATED;
  } else {
    // Notify the caller that the update is now beginning and initiate it.
    status = UPDATING;
    BeginUpdateCheckOnFileThread(true /* install_update_if_possible */);
  }
  callback_.Run(status, 0, base::string16());
}

void VersionUpdaterWin::OnUpgradeProgress(int progress,
                                          const base::string16& new_version) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  callback_.Run(UPDATING, progress, base::string16());
}

void VersionUpdaterWin::OnUpgradeComplete(const base::string16& new_version) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  callback_.Run(NEARLY_UPDATED, 0, base::string16());
}

void VersionUpdaterWin::OnError(GoogleUpdateErrorCode error_code,
                                const base::string16& html_error_message,
                                const base::string16& new_version) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  base::string16 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, message);
}

void VersionUpdaterWin::BeginUpdateCheckOnFileThread(
    bool install_update_if_possible) {
  BeginUpdateCheck(content::BrowserThread::GetMessageLoopProxyForThread(
                       content::BrowserThread::FILE),
                   g_browser_process->GetApplicationLocale(),
                   install_update_if_possible, owner_widget_,
                   weak_factory_.GetWeakPtr());
}

void VersionUpdaterWin::OnPendingRestartCheck(bool is_update_pending_restart) {
  callback_.Run(is_update_pending_restart ? NEARLY_UPDATED : UPDATED, 0,
                base::string16());
}

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 new VersionUpdaterWin(
      window_tree_host ? window_tree_host->GetAcceleratedWidget() : nullptr);
}