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

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: robert comments 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/win/scoped_bstr.h"
16 #include "base/win/scoped_comptr.h"
17 #include "base/win/win_util.h"
18 #include "chrome/installer/util/browser_distribution.h"
19 #include "chrome/installer/util/google_update_settings.h"
20 #include "chrome/installer/util/install_util.h"
21 #include "chrome/installer/util/installation_state.h"
22 #include "chrome_frame/infobars/infobar_manager.h"
23 #include "chrome_frame/policy_settings.h"
24 #include "chrome_frame/ready_mode/internal/ready_mode_web_browser_adapter.h"
25 #include "chrome_frame/ready_mode/internal/url_launcher.h"
26 #include "chrome_frame/turndown_prompt/reshow_state.h"
27 #include "chrome_frame/turndown_prompt/turndown_prompt_content.h"
28 #include "chrome_frame/utils.h"
29 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
30
31 namespace {
32
33 // Time between showings of the turndown prompt.
34 const int kTurndownPromptReshowDeltaMinutes = 60 * 24 * 7;
35
36 void UninstallChromeFrame();
37
38 // Manages the Turndown UI in response to browsing ChromeFrame-rendered
39 // pages.
40 class BrowserObserver : public ReadyModeWebBrowserAdapter::Observer {
41 public:
42 BrowserObserver(IWebBrowser2* web_browser,
43 ReadyModeWebBrowserAdapter* adapter);
44
45 // ReadyModeWebBrowserAdapter::Observer implementation
46 virtual void OnNavigateTo(const std::wstring& url);
47 virtual void OnRenderInChromeFrame(const std::wstring& url);
48 virtual void OnRenderInHost(const std::wstring& url);
49
50 private:
51 // Shows the turndown prompt if it hasn't been seen since
52 // kTurndownPromptReshowDeltaMinutes.
53 void ShowPrompt();
54 void Hide();
55 // Returns a self-managed pointer that is not guaranteed to survive handling
56 // of Windows events. For safety's sake, retrieve this pointer for each use
57 // and do not store it for use outside of scope.
58 InfobarManager* GetInfobarManager();
59
60 GURL rendered_url_;
61 base::win::ScopedComPtr<IWebBrowser2> web_browser_;
62 ReadyModeWebBrowserAdapter* adapter_;
63
64 DISALLOW_COPY_AND_ASSIGN(BrowserObserver);
65 };
66
67 // Implements launching of a URL in an instance of IWebBrowser2.
68 class UrlLauncherImpl : public UrlLauncher {
69 public:
70 explicit UrlLauncherImpl(IWebBrowser2* web_browser);
71
72 // UrlLauncher implementation
73 void LaunchUrl(const std::wstring& url);
74
75 private:
76 base::win::ScopedComPtr<IWebBrowser2> web_browser_;
77 };
78
79 UrlLauncherImpl::UrlLauncherImpl(IWebBrowser2* web_browser) {
80 DCHECK(web_browser);
81 web_browser_ = web_browser;
82 }
83
84 void UrlLauncherImpl::LaunchUrl(const std::wstring& url) {
85 VARIANT flags = { VT_I4 };
86 V_I4(&flags) = navOpenInNewWindow;
87 base::win::ScopedBstr location(url.c_str());
88
89 HRESULT hr = web_browser_->Navigate(location, &flags, NULL, NULL, NULL);
90 DLOG_IF(ERROR, FAILED(hr)) << "Failed to invoke Navigate on IWebBrowser2. "
91 << "Error: " << hr;
92 }
93
94 BrowserObserver::BrowserObserver(IWebBrowser2* web_browser,
95 ReadyModeWebBrowserAdapter* adapter)
96 : web_browser_(web_browser),
97 adapter_(adapter) {
98 }
99
100 void BrowserObserver::OnNavigateTo(const std::wstring& url) {
101 if (!net::registry_controlled_domains::SameDomainOrHost(
102 GURL(url),
103 rendered_url_,
104 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)) {
105 rendered_url_ = GURL();
106 Hide();
107 }
108 }
109
110 void BrowserObserver::OnRenderInChromeFrame(const std::wstring& url) {
111 ShowPrompt();
112 rendered_url_ = GURL(url);
113 }
114
115 void BrowserObserver::OnRenderInHost(const std::wstring& url) {
116 Hide();
117 rendered_url_ = GURL(url);
118 }
119
120 void BrowserObserver::ShowPrompt() {
121 BrowserDistribution* dist =
122 BrowserDistribution::GetSpecificDistribution(
123 BrowserDistribution::CHROME_FRAME);
124 turndown_prompt::ReshowState reshow_state(
125 dist->GetStateKey(),
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(&UninstallChromeFrame)));
145
146 if (infobar_manager->Show(infobar_content.release(), TOP_INFOBAR)) {
147 // Update state in the registry that the prompt was shown.
148 reshow_state.MarkShown(base::Time::Now());
149 }
150 }
151 }
152
153 void BrowserObserver::Hide() {
154 InfobarManager* infobar_manager = GetInfobarManager();
155 if (infobar_manager)
156 infobar_manager->HideAll();
157 }
158
159 InfobarManager* BrowserObserver::GetInfobarManager() {
160 HRESULT hr = NOERROR;
161
162 base::win::ScopedComPtr<IOleWindow> ole_window;
163 hr = DoQueryService(SID_SShellBrowser, web_browser_, ole_window.Receive());
164 if (FAILED(hr) || ole_window == NULL) {
165 DLOG(ERROR) << "Failed to query SID_SShellBrowser from IWebBrowser2. "
166 << "Error: " << hr;
167 return NULL;
168 }
169
170 HWND web_browser_hwnd = NULL;
171 hr = ole_window->GetWindow(&web_browser_hwnd);
172 if (FAILED(hr) || web_browser_hwnd == NULL) {
173 DLOG(ERROR) << "Failed to query HWND from IOleWindow. "
174 << "Error: " << hr;
175 return NULL;
176 }
177
178 return InfobarManager::Get(web_browser_hwnd);
179 }
180
181 // Attempts to create a ReadyModeWebBrowserAdapter instance.
182 bool CreateWebBrowserAdapter(ReadyModeWebBrowserAdapter** adapter) {
183 *adapter = NULL;
184
185 CComObject<ReadyModeWebBrowserAdapter>* com_object;
186 HRESULT hr =
187 CComObject<ReadyModeWebBrowserAdapter>::CreateInstance(&com_object);
188
189 if (FAILED(hr)) {
190 DLOG(ERROR) << "Failed to create instance of ReadyModeWebBrowserAdapter. "
191 << "Error: " << hr;
192 return false;
193 }
194
195 com_object->AddRef();
196 *adapter = com_object;
197 return true;
198 }
199
200 // Attempts to install Turnown prompts in the provided web browser.
201 bool InstallPrompts(IWebBrowser2* web_browser) {
202 base::win::ScopedComPtr<ReadyModeWebBrowserAdapter, NULL> adapter;
203
204 if (!CreateWebBrowserAdapter(adapter.Receive()))
205 return false;
206
207 // Pass ownership of our delegate to the BrowserObserver
208 scoped_ptr<ReadyModeWebBrowserAdapter::Observer> browser_observer(
209 new BrowserObserver(web_browser, adapter));
210
211 // Owns the BrowserObserver
212 return adapter->Initialize(web_browser, browser_observer.release());
213 }
214
215 // Uninstalls Chrome Frame in response to user action.
216 void UninstallChromeFrame() {
217 // TODO(grt) Find and run the uninstaller.
218 }
219
220 } // namespace
221
222 namespace turndown_prompt {
223
224 bool IsPromptSuppressed() {
225 // See if this is an MSI install of GCF or if updates have been disabled.
226 BrowserDistribution* dist =
227 BrowserDistribution::GetSpecificDistribution(
228 BrowserDistribution::CHROME_FRAME);
229
230 base::FilePath dll_path;
231 if (PathService::Get(base::DIR_MODULE, &dll_path)) {
232 bool system_level =
233 !InstallUtil::IsPerUserInstall(dll_path.value().c_str());
234 bool multi_install = false;
235
236 installer::ProductState product_state;
237 if (product_state.Initialize(system_level, dist)) {
238 if (product_state.is_msi())
239 return true;
240 multi_install = product_state.is_multi_install();
241 }
242
243 if (multi_install) {
244 dist =
245 BrowserDistribution::GetSpecificDistribution(
246 BrowserDistribution::CHROME_BINARIES);
247 }
248 if (GoogleUpdateSettings::GetAppUpdatePolicy(dist->GetAppGuid(), NULL) ==
249 GoogleUpdateSettings::UPDATES_DISABLED) {
250 return true;
251 }
252 }
253
254 // See if the prompt is explicitly suppressed via GP.
255 return PolicySettings::GetInstance()->suppress_turndown_prompt();
256 }
257
258 void Configure(IWebBrowser2* web_browser) {
259 if (!IsPromptSuppressed())
260 InstallPrompts(web_browser);
261 }
262
263 } // namespace turndown_prompt
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698