OLD | NEW |
---|---|
(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_frame/infobars/infobar_manager.h" | |
22 #include "chrome_frame/policy_settings.h" | |
23 #include "chrome_frame/ready_mode/internal/ready_mode_web_browser_adapter.h" | |
24 #include "chrome_frame/ready_mode/internal/url_launcher.h" | |
25 #include "chrome_frame/turndown_prompt/reshow_state.h" | |
26 #include "chrome_frame/turndown_prompt/turndown_prompt_content.h" | |
27 #include "chrome_frame/utils.h" | |
28 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | |
29 | |
30 namespace { | |
31 | |
32 // Time between showingings of the turndown prompt. | |
robertshield
2013/06/19 23:36:33
Too many ings
grt (UTC plus 2)
2013/06/20 19:55:29
Done.
| |
33 const int kTurndownPromptReshowDeltaMinutes = 60 * 24 * 7; | |
34 | |
35 void UninstallChromeFrame(); | |
36 | |
37 // Manages the Turndown UI in response to browsing ChromeFrame-rendered | |
38 // pages. | |
39 class BrowserObserver : public ReadyModeWebBrowserAdapter::Observer { | |
40 public: | |
41 BrowserObserver(IWebBrowser2* web_browser, | |
42 ReadyModeWebBrowserAdapter* adapter); | |
43 | |
44 // ReadyModeWebBrowserAdapter::Observer implementation | |
45 virtual void OnNavigateTo(const std::wstring& url); | |
46 virtual void OnRenderInChromeFrame(const std::wstring& url); | |
47 virtual void OnRenderInHost(const std::wstring& url); | |
48 | |
49 private: | |
50 // Shows the turndown prompt if it hasn't been seen since the reshow delta. | |
robertshield
2013/06/19 23:36:33
reshow delta -> kTurndownPromptReshowDeltaMinutes
grt (UTC plus 2)
2013/06/20 19:55:29
Done.
| |
51 void ShowPrompt(); | |
52 void Hide(); | |
53 InfobarManager* GetInfobarManager(); | |
robertshield
2013/06/19 23:36:33
The pointer this returns has a non-obvious life-cy
grt (UTC plus 2)
2013/06/20 19:55:29
Done.
| |
54 | |
55 GURL rendered_url_; | |
56 base::win::ScopedComPtr<IWebBrowser2> web_browser_; | |
57 ReadyModeWebBrowserAdapter* adapter_; | |
58 | |
59 DISALLOW_COPY_AND_ASSIGN(BrowserObserver); | |
60 }; | |
61 | |
62 // Implements launching of a URL in an instance of IWebBrowser2. | |
63 class UrlLauncherImpl : public UrlLauncher { | |
64 public: | |
65 explicit UrlLauncherImpl(IWebBrowser2* web_browser); | |
66 | |
67 // UrlLauncher implementation | |
68 void LaunchUrl(const std::wstring& url); | |
69 | |
70 private: | |
71 base::win::ScopedComPtr<IWebBrowser2> web_browser_; | |
72 }; | |
73 | |
74 UrlLauncherImpl::UrlLauncherImpl(IWebBrowser2* web_browser) { | |
75 DCHECK(web_browser); | |
76 web_browser_ = web_browser; | |
77 } | |
78 | |
79 void UrlLauncherImpl::LaunchUrl(const std::wstring& url) { | |
80 VARIANT flags = { VT_I4 }; | |
81 V_I4(&flags) = navOpenInNewWindow; | |
82 base::win::ScopedBstr location(url.c_str()); | |
83 | |
84 HRESULT hr = web_browser_->Navigate(location, &flags, NULL, NULL, NULL); | |
85 DLOG_IF(ERROR, FAILED(hr)) << "Failed to invoke Navigate on IWebBrowser2. " | |
86 << "Error: " << hr; | |
87 } | |
88 | |
89 BrowserObserver::BrowserObserver(IWebBrowser2* web_browser, | |
90 ReadyModeWebBrowserAdapter* adapter) | |
91 : web_browser_(web_browser), | |
92 adapter_(adapter) { | |
93 } | |
94 | |
95 void BrowserObserver::OnNavigateTo(const std::wstring& url) { | |
96 if (!net::registry_controlled_domains::SameDomainOrHost( | |
97 GURL(url), | |
98 rendered_url_, | |
99 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)) { | |
100 rendered_url_ = GURL(); | |
101 Hide(); | |
102 } | |
103 } | |
104 | |
105 void BrowserObserver::OnRenderInChromeFrame(const std::wstring& url) { | |
106 ShowPrompt(); | |
107 rendered_url_ = GURL(url); | |
108 } | |
109 | |
110 void BrowserObserver::OnRenderInHost(const std::wstring& url) { | |
111 Hide(); | |
112 rendered_url_ = GURL(url); | |
113 } | |
114 | |
115 void BrowserObserver::ShowPrompt() { | |
116 BrowserDistribution* dist = | |
117 BrowserDistribution::GetSpecificDistribution( | |
118 BrowserDistribution::CHROME_FRAME); | |
119 turndown_prompt::ReshowState reshow_state( | |
120 dist->GetStateKey(), | |
121 base::TimeDelta::FromMinutes(kTurndownPromptReshowDeltaMinutes)); | |
122 | |
123 // Short-circuit if the prompt shouldn't be shown again yet. | |
124 if (!reshow_state.HasReshowDeltaExpired(base::Time::Now())) | |
125 return; | |
126 | |
127 // This pointer is self-managed and not guaranteed to survive handling of | |
128 // Windows events. | |
robertshield
2013/06/19 23:36:33
As an unfamiliar reader, I don't know how to parse
grt (UTC plus 2)
2013/06/20 19:55:29
Done.
| |
129 InfobarManager* infobar_manager = GetInfobarManager(); | |
130 | |
131 if (infobar_manager) { | |
132 // Owned by infobar_content | |
133 scoped_ptr<UrlLauncher> url_launcher(new UrlLauncherImpl(web_browser_)); | |
134 | |
135 // Owned by infobar_manager | |
136 scoped_ptr<InfobarContent> infobar_content(new TurndownPromptContent( | |
137 url_launcher.release(), | |
138 base::Bind(&UninstallChromeFrame))); | |
139 | |
140 if (infobar_manager->Show(infobar_content.release(), TOP_INFOBAR)) { | |
141 // Update state in the registry that the prompt was shown. | |
142 reshow_state.MarkShown(base::Time::Now()); | |
robertshield
2013/06/19 23:36:33
Random thought: if I open two tabs both rendering
grt (UTC plus 2)
2013/06/20 19:55:29
I think this is possible.
robertshield
2013/06/20 21:45:10
Yeah, was simply musing. I don't have an immediate
| |
143 } | |
144 } | |
145 } | |
146 | |
147 void BrowserObserver::Hide() { | |
148 InfobarManager* infobar_manager = GetInfobarManager(); | |
149 if (infobar_manager) | |
150 infobar_manager->HideAll(); | |
151 } | |
152 | |
153 InfobarManager* BrowserObserver::GetInfobarManager() { | |
154 HRESULT hr = NOERROR; | |
155 | |
156 base::win::ScopedComPtr<IOleWindow> ole_window; | |
157 hr = DoQueryService(SID_SShellBrowser, web_browser_, ole_window.Receive()); | |
158 if (FAILED(hr) || ole_window == NULL) { | |
159 DLOG(ERROR) << "Failed to query SID_SShellBrowser from IWebBrowser2. " | |
160 << "Error: " << hr; | |
161 return NULL; | |
162 } | |
163 | |
164 HWND web_browserhwnd = NULL; | |
robertshield
2013/06/19 23:36:33
nit: web_browser_hwnd
grt (UTC plus 2)
2013/06/20 19:55:29
Done.
| |
165 hr = ole_window->GetWindow(&web_browserhwnd); | |
166 if (FAILED(hr) || web_browserhwnd == NULL) { | |
167 DLOG(ERROR) << "Failed to query HWND from IOleWindow. " | |
168 << "Error: " << hr; | |
169 return NULL; | |
170 } | |
171 | |
172 return InfobarManager::Get(web_browserhwnd); | |
173 } | |
174 | |
175 // Attempts to create a ReadyModeWebBrowserAdapter instance. | |
176 bool CreateWebBrowserAdapter(ReadyModeWebBrowserAdapter** pointer) { | |
robertshield
2013/06/19 23:36:33
nit: pointer -> adapter
grt (UTC plus 2)
2013/06/20 19:55:29
Done.
| |
177 *pointer = NULL; | |
178 | |
179 CComObject<ReadyModeWebBrowserAdapter>* com_object; | |
180 HRESULT hr = | |
181 CComObject<ReadyModeWebBrowserAdapter>::CreateInstance(&com_object); | |
182 | |
183 if (FAILED(hr)) { | |
184 DLOG(ERROR) << "Failed to create instance of ReadyModeWebBrowserAdapter. " | |
185 << "Error: " << hr; | |
186 return false; | |
187 } | |
188 | |
189 com_object->AddRef(); | |
190 *pointer = com_object; | |
191 return true; | |
192 } | |
193 | |
194 // Attempts to install Turnown prompts in the provided web browser. | |
195 bool InstallPrompts(IWebBrowser2* web_browser) { | |
196 base::win::ScopedComPtr<ReadyModeWebBrowserAdapter, NULL> adapter; | |
197 | |
198 if (!CreateWebBrowserAdapter(adapter.Receive())) | |
199 return false; | |
200 | |
201 // Pass ownership of our delegate to the BrowserObserver | |
202 scoped_ptr<ReadyModeWebBrowserAdapter::Observer> browser_observer( | |
203 new BrowserObserver(web_browser, adapter)); | |
204 | |
205 // Owns the BrowserObserver | |
206 return adapter->Initialize(web_browser, browser_observer.release()); | |
207 } | |
208 | |
209 // Uninstalls Chrome Frame in response to user action. | |
210 void UninstallChromeFrame() { | |
211 // TODO(grt) Find and run the uninstaller. | |
212 } | |
213 | |
214 } // namespace | |
215 | |
216 namespace turndown_prompt { | |
217 | |
218 bool IsPromptSuppressed() { | |
219 // See if updates are disabled for Chrome Frame (check the binaries if | |
220 // multi-install). | |
robertshield
2013/06/19 23:36:33
I wonder if we should check the MSI bit as well?
grt (UTC plus 2)
2013/06/20 19:55:29
Done.
| |
221 BrowserDistribution* dist = | |
222 BrowserDistribution::GetSpecificDistribution( | |
223 BrowserDistribution::CHROME_FRAME); | |
224 | |
225 base::FilePath dll_path; | |
226 if (PathService::Get(base::DIR_MODULE, &dll_path)) { | |
227 bool system_level = | |
228 !InstallUtil::IsPerUserInstall(dll_path.value().c_str()); | |
229 bool multi_install = InstallUtil::IsMultiInstall(dist, system_level); | |
230 if (multi_install) { | |
231 dist = | |
232 BrowserDistribution::GetSpecificDistribution( | |
233 BrowserDistribution::CHROME_BINARIES); | |
234 } | |
235 if (GoogleUpdateSettings::GetAppUpdatePolicy(dist->GetAppGuid(), NULL) == | |
236 GoogleUpdateSettings::UPDATES_DISABLED) { | |
237 return true; | |
238 } | |
239 } | |
240 | |
241 // See if the prompt is explicitly suppressed via GP. | |
242 return PolicySettings::GetInstance()->suppress_turndown_prompt(); | |
243 } | |
244 | |
245 void Configure(IWebBrowser2* web_browser) { | |
246 if (!IsPromptSuppressed()) | |
247 InstallPrompts(web_browser); | |
248 } | |
249 | |
250 } // namespace turndown_prompt | |
OLD | NEW |