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

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 r207907 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 std::wstring& url);
51 virtual void OnRenderInChromeFrame(const std::wstring& url);
52 virtual void OnRenderInHost(const std::wstring& 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 std::wstring& 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 std::wstring& 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 std::wstring& 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 std::wstring& url) {
115 ShowPrompt();
116 rendered_url_ = GURL(url);
117 }
118
119 void BrowserObserver::OnRenderInHost(const std::wstring& url) {
120 Hide();
121 rendered_url_ = GURL(url);
122 }
123
124 void BrowserObserver::ShowPrompt() {
125 BrowserDistribution* dist =
126 BrowserDistribution::GetSpecificDistribution(
127 BrowserDistribution::CHROME_FRAME);
128 turndown_prompt::ReshowState reshow_state(
129 dist->GetStateKey(),
130 base::TimeDelta::FromMinutes(kTurndownPromptReshowDeltaMinutes));
131
132 // Short-circuit if the prompt shouldn't be shown again yet.
133 if (!reshow_state.HasReshowDeltaExpired(base::Time::Now()))
134 return;
135
136 // This pointer is self-managed and not guaranteed to survive handling of
137 // Windows events. For safety's sake, retrieve this pointer for each use and
138 // do not store it for use outside of scope.
139 InfobarManager* infobar_manager = GetInfobarManager();
140
141 if (infobar_manager) {
142 // Owned by infobar_content
143 scoped_ptr<UrlLauncher> url_launcher(new UrlLauncherImpl(web_browser_));
144
145 // Owned by infobar_manager
146 scoped_ptr<InfobarContent> infobar_content(new TurndownPromptContent(
147 url_launcher.release(),
148 base::Bind(&OnUninstallClicked,
149 base::Owned(new UrlLauncherImpl(web_browser_)))));
150
151 if (infobar_manager->Show(infobar_content.release(), TOP_INFOBAR)) {
152 // Update state in the registry that the prompt was shown.
153 reshow_state.MarkShown(base::Time::Now());
154 }
155 }
156 }
157
158 void BrowserObserver::Hide() {
159 InfobarManager* infobar_manager = GetInfobarManager();
160 if (infobar_manager)
161 infobar_manager->HideAll();
162 }
163
164 InfobarManager* BrowserObserver::GetInfobarManager() {
165 HRESULT hr = NOERROR;
166
167 base::win::ScopedComPtr<IOleWindow> ole_window;
168 hr = DoQueryService(SID_SShellBrowser, web_browser_, ole_window.Receive());
169 if (FAILED(hr) || ole_window == NULL) {
170 DLOG(ERROR) << "Failed to query SID_SShellBrowser from IWebBrowser2. "
171 << "Error: " << hr;
172 return NULL;
173 }
174
175 HWND web_browser_hwnd = NULL;
176 hr = ole_window->GetWindow(&web_browser_hwnd);
177 if (FAILED(hr) || web_browser_hwnd == NULL) {
178 DLOG(ERROR) << "Failed to query HWND from IOleWindow. "
179 << "Error: " << hr;
180 return NULL;
181 }
182
183 return InfobarManager::Get(web_browser_hwnd);
184 }
185
186 // Returns true if the module into which this code is linked is installed at
187 // system-level.
188 bool IsCurrentModuleSystemLevel() {
189 base::FilePath dll_path;
190 if (PathService::Get(base::DIR_MODULE, &dll_path))
191 return !InstallUtil::IsPerUserInstall(dll_path.value().c_str());
192 return false;
193 }
194
195 // Attempts to create a ReadyModeWebBrowserAdapter instance.
196 bool CreateWebBrowserAdapter(ReadyModeWebBrowserAdapter** adapter) {
197 *adapter = NULL;
198
199 CComObject<ReadyModeWebBrowserAdapter>* com_object;
200 HRESULT hr =
201 CComObject<ReadyModeWebBrowserAdapter>::CreateInstance(&com_object);
202
203 if (FAILED(hr)) {
204 DLOG(ERROR) << "Failed to create instance of ReadyModeWebBrowserAdapter. "
205 << "Error: " << hr;
206 return false;
207 }
208
209 com_object->AddRef();
210 *adapter = com_object;
211 return true;
212 }
213
214 // Attempts to install Turnown prompts in the provided web browser.
robertshield 2013/06/21 20:06:45 Turndown
grt (UTC plus 2) 2013/06/21 20:10:40 Done.
215 bool InstallPrompts(IWebBrowser2* web_browser) {
216 base::win::ScopedComPtr<ReadyModeWebBrowserAdapter, NULL> adapter;
217
218 if (!CreateWebBrowserAdapter(adapter.Receive()))
219 return false;
220
221 // Pass ownership of our delegate to the BrowserObserver
222 scoped_ptr<ReadyModeWebBrowserAdapter::Observer> browser_observer(
223 new BrowserObserver(web_browser, adapter));
224
225 // Owns the BrowserObserver
226 return adapter->Initialize(web_browser, browser_observer.release());
227 }
228
229 // Launches the Chrome Frame uninstaller in response to user action. This
230 // implementation should not be used to uninstall MSI-based versions of GCF,
231 // since those must be removed by way of Windows Installer machinery.
232 void LaunchChromeFrameUninstaller() {
233 BrowserDistribution* dist =
234 BrowserDistribution::GetSpecificDistribution(
235 BrowserDistribution::CHROME_FRAME);
236 const bool system_level = IsCurrentModuleSystemLevel();
237 installer::ProductState product_state;
238 if (!product_state.Initialize(system_level, dist)) {
239 DLOG(ERROR) << "Chrome frame isn't installed at "
240 << (system_level ? "system" : "user") << " level.";
241 return;
242 }
243
244 CommandLine uninstall_command(product_state.uninstall_command());
245 if (uninstall_command.GetProgram().empty()) {
246 DLOG(ERROR) << "No uninstall command found in registry.";
247 return;
248 }
249
250 // Force Uninstall silences the prompt to reboot to complete uninstall.
251 uninstall_command.AppendSwitch(installer::switches::kForceUninstall);
252 VLOG(1) << "Uninstalling Chrome Frame with command: "
253 << uninstall_command.GetCommandLineString();
254 base::LaunchProcess(uninstall_command, base::LaunchOptions(), NULL);
255 }
256
257 void LaunchLearnMoreURL(UrlLauncher* url_launcher) {
258 url_launcher->LaunchUrl(SimpleResourceLoader::Get(
259 IDS_CHROME_FRAME_TURNDOWN_LEARN_MORE_URL));
260 }
261
262 void OnUninstallClicked(UrlLauncher* url_launcher) {
263 LaunchChromeFrameUninstaller();
264 LaunchLearnMoreURL(url_launcher);
265 }
266
267 } // namespace
268
269 namespace turndown_prompt {
270
271 bool IsPromptSuppressed() {
272 // See if this is an MSI install of GCF or if updates have been disabled.
273 BrowserDistribution* dist =
274 BrowserDistribution::GetSpecificDistribution(
275 BrowserDistribution::CHROME_FRAME);
276
277 const bool system_level = IsCurrentModuleSystemLevel();
278 bool multi_install = false;
279
280 installer::ProductState product_state;
281 if (product_state.Initialize(system_level, dist)) {
282 if (product_state.is_msi())
283 return true;
284 multi_install = product_state.is_multi_install();
285 }
286
287 if (multi_install) {
288 dist =
289 BrowserDistribution::GetSpecificDistribution(
290 BrowserDistribution::CHROME_BINARIES);
291 }
292 if (GoogleUpdateSettings::GetAppUpdatePolicy(dist->GetAppGuid(), NULL) ==
293 GoogleUpdateSettings::UPDATES_DISABLED) {
294 return true;
295 }
296
297 // See if the prompt is explicitly suppressed via GP.
298 return PolicySettings::GetInstance()->suppress_turndown_prompt();
299 }
300
301 void Configure(IWebBrowser2* web_browser) {
302 if (!IsPromptSuppressed())
303 InstallPrompts(web_browser);
304 }
305
306 } // 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