Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: chrome_frame/turndown_prompt/turndown_prompt.cc

Issue 17153006: Chrome Frame turndown prompt. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase to r208076 Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome_frame/turndown_prompt/turndown_prompt.h"
6
7 #include <atlbase.h>
8 #include <shlguid.h>
9
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/path_service.h"
15 #include "base/process_util.h"
16 #include "base/win/scoped_bstr.h"
17 #include "base/win/scoped_comptr.h"
18 #include "base/win/win_util.h"
19 #include "chrome/installer/util/browser_distribution.h"
20 #include "chrome/installer/util/google_update_settings.h"
21 #include "chrome/installer/util/install_util.h"
22 #include "chrome/installer/util/installation_state.h"
23 #include "chrome/installer/util/util_constants.h"
24 #include "chrome_frame/infobars/infobar_manager.h"
25 #include "chrome_frame/policy_settings.h"
26 #include "chrome_frame/ready_mode/internal/ready_mode_web_browser_adapter.h"
27 #include "chrome_frame/ready_mode/internal/url_launcher.h"
28 #include "chrome_frame/simple_resource_loader.h"
29 #include "chrome_frame/turndown_prompt/reshow_state.h"
30 #include "chrome_frame/turndown_prompt/turndown_prompt_content.h"
31 #include "chrome_frame/utils.h"
32 #include "grit/chromium_strings.h"
33 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
34
35 namespace {
36
37 // Time between showings of the turndown prompt.
38 const int kTurndownPromptReshowDeltaMinutes = 60 * 24 * 7;
39
40 void OnUninstallClicked(UrlLauncher* url_launcher);
41
42 // Manages the Turndown UI in response to browsing ChromeFrame-rendered
43 // pages.
44 class BrowserObserver : public ReadyModeWebBrowserAdapter::Observer {
45 public:
46 BrowserObserver(IWebBrowser2* web_browser,
47 ReadyModeWebBrowserAdapter* adapter);
48
49 // ReadyModeWebBrowserAdapter::Observer implementation
50 virtual void OnNavigateTo(const string16& url);
51 virtual void OnRenderInChromeFrame(const string16& url);
52 virtual void OnRenderInHost(const string16& url);
53
54 private:
55 // Shows the turndown prompt if it hasn't been seen since
56 // kTurndownPromptReshowDeltaMinutes.
57 void ShowPrompt();
58 void Hide();
59 // Returns a self-managed pointer that is not guaranteed to survive handling
60 // of Windows events. For safety's sake, retrieve this pointer for each use
61 // and do not store it for use outside of scope.
62 InfobarManager* GetInfobarManager();
63
64 GURL rendered_url_;
65 base::win::ScopedComPtr<IWebBrowser2> web_browser_;
66 ReadyModeWebBrowserAdapter* adapter_;
67
68 DISALLOW_COPY_AND_ASSIGN(BrowserObserver);
69 };
70
71 // Implements launching of a URL in an instance of IWebBrowser2.
72 class UrlLauncherImpl : public UrlLauncher {
73 public:
74 explicit UrlLauncherImpl(IWebBrowser2* web_browser);
75
76 // UrlLauncher implementation
77 void LaunchUrl(const string16& url);
78
79 private:
80 base::win::ScopedComPtr<IWebBrowser2> web_browser_;
81 };
82
83 UrlLauncherImpl::UrlLauncherImpl(IWebBrowser2* web_browser) {
84 DCHECK(web_browser);
85 web_browser_ = web_browser;
86 }
87
88 void UrlLauncherImpl::LaunchUrl(const string16& url) {
89 VARIANT flags = { VT_I4 };
90 V_I4(&flags) = navOpenInNewWindow;
91 base::win::ScopedBstr location(url.c_str());
92
93 HRESULT hr = web_browser_->Navigate(location, &flags, NULL, NULL, NULL);
94 DLOG_IF(ERROR, FAILED(hr)) << "Failed to invoke Navigate on IWebBrowser2. "
95 << "Error: " << hr;
96 }
97
98 BrowserObserver::BrowserObserver(IWebBrowser2* web_browser,
99 ReadyModeWebBrowserAdapter* adapter)
100 : web_browser_(web_browser),
101 adapter_(adapter) {
102 }
103
104 void BrowserObserver::OnNavigateTo(const string16& url) {
105 if (!net::registry_controlled_domains::SameDomainOrHost(
106 GURL(url),
107 rendered_url_,
108 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)) {
109 rendered_url_ = GURL();
110 Hide();
111 }
112 }
113
114 void BrowserObserver::OnRenderInChromeFrame(const string16& url) {
115 ShowPrompt();
116 rendered_url_ = GURL(url);
117 }
118
119 void BrowserObserver::OnRenderInHost(const string16& url) {
120 Hide();
121 rendered_url_ = GURL(url);
122 }
123
124 void BrowserObserver::ShowPrompt() {
125 turndown_prompt::ReshowState reshow_state(
126 base::TimeDelta::FromMinutes(kTurndownPromptReshowDeltaMinutes));
127
128 // Short-circuit if the prompt shouldn't be shown again yet.
129 if (!reshow_state.HasReshowDeltaExpired(base::Time::Now()))
130 return;
131
132 // This pointer is self-managed and not guaranteed to survive handling of
133 // Windows events. For safety's sake, retrieve this pointer for each use and
134 // do not store it for use outside of scope.
135 InfobarManager* infobar_manager = GetInfobarManager();
136
137 if (infobar_manager) {
138 // Owned by infobar_content
139 scoped_ptr<UrlLauncher> url_launcher(new UrlLauncherImpl(web_browser_));
140
141 // Owned by infobar_manager
142 scoped_ptr<InfobarContent> infobar_content(new TurndownPromptContent(
143 url_launcher.release(),
144 base::Bind(&OnUninstallClicked,
145 base::Owned(new UrlLauncherImpl(web_browser_)))));
146
147 if (infobar_manager->Show(infobar_content.release(), TOP_INFOBAR)) {
148 // Update state in the registry that the prompt was shown.
149 reshow_state.MarkShown(base::Time::Now());
150 }
151 }
152 }
153
154 void BrowserObserver::Hide() {
155 InfobarManager* infobar_manager = GetInfobarManager();
156 if (infobar_manager)
157 infobar_manager->HideAll();
158 }
159
160 InfobarManager* BrowserObserver::GetInfobarManager() {
161 HRESULT hr = NOERROR;
162
163 base::win::ScopedComPtr<IOleWindow> ole_window;
164 hr = DoQueryService(SID_SShellBrowser, web_browser_, ole_window.Receive());
165 if (FAILED(hr) || ole_window == NULL) {
166 DLOG(ERROR) << "Failed to query SID_SShellBrowser from IWebBrowser2. "
167 << "Error: " << hr;
168 return NULL;
169 }
170
171 HWND web_browser_hwnd = NULL;
172 hr = ole_window->GetWindow(&web_browser_hwnd);
173 if (FAILED(hr) || web_browser_hwnd == NULL) {
174 DLOG(ERROR) << "Failed to query HWND from IOleWindow. "
175 << "Error: " << hr;
176 return NULL;
177 }
178
179 return InfobarManager::Get(web_browser_hwnd);
180 }
181
182 // Returns true if the module into which this code is linked is installed at
183 // system-level.
184 bool IsCurrentModuleSystemLevel() {
185 base::FilePath dll_path;
186 if (PathService::Get(base::DIR_MODULE, &dll_path))
187 return !InstallUtil::IsPerUserInstall(dll_path.value().c_str());
188 return false;
189 }
190
191 // Attempts to create a ReadyModeWebBrowserAdapter instance.
192 bool CreateWebBrowserAdapter(ReadyModeWebBrowserAdapter** adapter) {
193 *adapter = NULL;
194
195 CComObject<ReadyModeWebBrowserAdapter>* com_object;
196 HRESULT hr =
197 CComObject<ReadyModeWebBrowserAdapter>::CreateInstance(&com_object);
198
199 if (FAILED(hr)) {
200 DLOG(ERROR) << "Failed to create instance of ReadyModeWebBrowserAdapter. "
201 << "Error: " << hr;
202 return false;
203 }
204
205 com_object->AddRef();
206 *adapter = com_object;
207 return true;
208 }
209
210 // Attempts to install Turndown prompts in the provided web browser.
211 bool InstallPrompts(IWebBrowser2* web_browser) {
212 base::win::ScopedComPtr<ReadyModeWebBrowserAdapter, NULL> adapter;
213
214 if (!CreateWebBrowserAdapter(adapter.Receive()))
215 return false;
216
217 // Pass ownership of our delegate to the BrowserObserver
218 scoped_ptr<ReadyModeWebBrowserAdapter::Observer> browser_observer(
219 new BrowserObserver(web_browser, adapter));
220
221 // Owns the BrowserObserver
222 return adapter->Initialize(web_browser, browser_observer.release());
223 }
224
225 // Launches the Chrome Frame uninstaller in response to user action. This
226 // implementation should not be used to uninstall MSI-based versions of GCF,
227 // since those must be removed by way of Windows Installer machinery.
228 void LaunchChromeFrameUninstaller() {
229 BrowserDistribution* dist =
230 BrowserDistribution::GetSpecificDistribution(
231 BrowserDistribution::CHROME_FRAME);
232 const bool system_level = IsCurrentModuleSystemLevel();
233 installer::ProductState product_state;
234 if (!product_state.Initialize(system_level, dist)) {
235 DLOG(ERROR) << "Chrome frame isn't installed at "
236 << (system_level ? "system" : "user") << " level.";
237 return;
238 }
239
240 CommandLine uninstall_command(product_state.uninstall_command());
241 if (uninstall_command.GetProgram().empty()) {
242 DLOG(ERROR) << "No uninstall command found in registry.";
243 return;
244 }
245
246 // Force Uninstall silences the prompt to reboot to complete uninstall.
247 uninstall_command.AppendSwitch(installer::switches::kForceUninstall);
248 VLOG(1) << "Uninstalling Chrome Frame with command: "
249 << uninstall_command.GetCommandLineString();
250 base::LaunchProcess(uninstall_command, base::LaunchOptions(), NULL);
251 }
252
253 void LaunchLearnMoreURL(UrlLauncher* url_launcher) {
254 url_launcher->LaunchUrl(SimpleResourceLoader::Get(
255 IDS_CHROME_FRAME_TURNDOWN_LEARN_MORE_URL));
256 }
257
258 void OnUninstallClicked(UrlLauncher* url_launcher) {
259 LaunchChromeFrameUninstaller();
260 LaunchLearnMoreURL(url_launcher);
261 }
262
263 } // namespace
264
265 namespace turndown_prompt {
266
267 bool IsPromptSuppressed() {
268 // See if this is an MSI install of GCF or if updates have been disabled.
269 BrowserDistribution* dist =
270 BrowserDistribution::GetSpecificDistribution(
271 BrowserDistribution::CHROME_FRAME);
272
273 const bool system_level = IsCurrentModuleSystemLevel();
274 bool multi_install = false;
275
276 installer::ProductState product_state;
277 if (product_state.Initialize(system_level, dist)) {
278 if (product_state.is_msi())
279 return true;
280 multi_install = product_state.is_multi_install();
281 }
282
283 if (multi_install) {
284 dist =
285 BrowserDistribution::GetSpecificDistribution(
286 BrowserDistribution::CHROME_BINARIES);
287 }
288 if (GoogleUpdateSettings::GetAppUpdatePolicy(dist->GetAppGuid(), NULL) ==
289 GoogleUpdateSettings::UPDATES_DISABLED) {
290 return true;
291 }
292
293 // See if the prompt is explicitly suppressed via GP.
294 return PolicySettings::GetInstance()->suppress_turndown_prompt();
295 }
296
297 void Configure(IWebBrowser2* web_browser) {
298 if (!IsPromptSuppressed())
299 InstallPrompts(web_browser);
300 }
301
302 } // namespace turndown_prompt
OLDNEW
« no previous file with comments | « chrome_frame/turndown_prompt/turndown_prompt.h ('k') | chrome_frame/turndown_prompt/turndown_prompt_content.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698