OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome_frame/bho.h" | 5 #include "chrome_frame/bho.h" |
6 | 6 |
7 #include <shlguid.h> | 7 #include <shlguid.h> |
8 | 8 |
9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 void ReadyModeDelegateImpl::DisableChromeFrame() { | 87 void ReadyModeDelegateImpl::DisableChromeFrame() { |
88 HttpNegotiatePatch::set_modify_user_agent(false); | 88 HttpNegotiatePatch::set_modify_user_agent(false); |
89 ProtocolSinkWrap::set_ignore_xua(true); | 89 ProtocolSinkWrap::set_ignore_xua(true); |
90 } | 90 } |
91 | 91 |
92 } // namespace | 92 } // namespace |
93 | 93 |
94 STDMETHODIMP Bho::SetSite(IUnknown* site) { | 94 STDMETHODIMP Bho::SetSite(IUnknown* site) { |
95 HRESULT hr = S_OK; | 95 HRESULT hr = S_OK; |
96 if (site) { | 96 if (site) { |
97 ScopedComPtr<IWebBrowser2> web_browser2; | 97 base::win::ScopedComPtr<IWebBrowser2> web_browser2; |
98 web_browser2.QueryFrom(site); | 98 web_browser2.QueryFrom(site); |
99 if (web_browser2) { | 99 if (web_browser2) { |
100 hr = DispEventAdvise(web_browser2, &DIID_DWebBrowserEvents2); | 100 hr = DispEventAdvise(web_browser2, &DIID_DWebBrowserEvents2); |
101 DCHECK(SUCCEEDED(hr)) << "DispEventAdvise failed. Error: " << hr; | 101 DCHECK(SUCCEEDED(hr)) << "DispEventAdvise failed. Error: " << hr; |
102 | 102 |
103 ready_mode::Configure(new ReadyModeDelegateImpl(), web_browser2); | 103 ready_mode::Configure(new ReadyModeDelegateImpl(), web_browser2); |
104 } | 104 } |
105 | 105 |
106 if (g_patch_helper.state() == PatchHelper::PATCH_IBROWSER) { | 106 if (g_patch_helper.state() == PatchHelper::PATCH_IBROWSER) { |
107 ScopedComPtr<IBrowserService> browser_service; | 107 base::win::ScopedComPtr<IBrowserService> browser_service; |
108 hr = DoQueryService(SID_SShellBrowser, site, browser_service.Receive()); | 108 hr = DoQueryService(SID_SShellBrowser, site, browser_service.Receive()); |
109 DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed." | 109 DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed." |
110 << " Site: " << site << " Error: " << hr; | 110 << " Site: " << site << " Error: " << hr; |
111 if (browser_service) { | 111 if (browser_service) { |
112 g_patch_helper.PatchBrowserService(browser_service); | 112 g_patch_helper.PatchBrowserService(browser_service); |
113 DCHECK(SUCCEEDED(hr)) << "vtable_patch::PatchInterfaceMethods failed." | 113 DCHECK(SUCCEEDED(hr)) << "vtable_patch::PatchInterfaceMethods failed." |
114 << " Site: " << site << " Error: " << hr; | 114 << " Site: " << site << " Error: " << hr; |
115 } | 115 } |
116 } | 116 } |
117 // Save away our BHO instance in TLS which enables it to be referenced by | 117 // Save away our BHO instance in TLS which enables it to be referenced by |
118 // our active document/activex instances to query referrer and other | 118 // our active document/activex instances to query referrer and other |
119 // information for a URL. | 119 // information for a URL. |
120 AddRef(); | 120 AddRef(); |
121 RegisterThreadInstance(); | 121 RegisterThreadInstance(); |
122 MetricsService::Start(); | 122 MetricsService::Start(); |
123 | 123 |
124 if (!IncreaseWinInetConnections(kMaxHttpConnections)) { | 124 if (!IncreaseWinInetConnections(kMaxHttpConnections)) { |
125 DLOG(WARNING) << "Failed to bump up HTTP connections. Error:" | 125 DLOG(WARNING) << "Failed to bump up HTTP connections. Error:" |
126 << ::GetLastError(); | 126 << ::GetLastError(); |
127 } | 127 } |
128 } else { | 128 } else { |
129 UnregisterThreadInstance(); | 129 UnregisterThreadInstance(); |
130 buggy_bho::BuggyBhoTls::DestroyInstance(); | 130 buggy_bho::BuggyBhoTls::DestroyInstance(); |
131 ScopedComPtr<IWebBrowser2> web_browser2; | 131 base::win::ScopedComPtr<IWebBrowser2> web_browser2; |
132 web_browser2.QueryFrom(m_spUnkSite); | 132 web_browser2.QueryFrom(m_spUnkSite); |
133 DispEventUnadvise(web_browser2, &DIID_DWebBrowserEvents2); | 133 DispEventUnadvise(web_browser2, &DIID_DWebBrowserEvents2); |
134 Release(); | 134 Release(); |
135 } | 135 } |
136 | 136 |
137 return IObjectWithSiteImpl<Bho>::SetSite(site); | 137 return IObjectWithSiteImpl<Bho>::SetSite(site); |
138 } | 138 } |
139 | 139 |
140 STDMETHODIMP Bho::BeforeNavigate2(IDispatch* dispatch, VARIANT* url, | 140 STDMETHODIMP Bho::BeforeNavigate2(IDispatch* dispatch, VARIANT* url, |
141 VARIANT* flags, VARIANT* target_frame_name, VARIANT* post_data, | 141 VARIANT* flags, VARIANT* target_frame_name, VARIANT* post_data, |
142 VARIANT* headers, VARIANT_BOOL* cancel) { | 142 VARIANT* headers, VARIANT_BOOL* cancel) { |
143 if (!url || url->vt != VT_BSTR || url->bstrVal == NULL) { | 143 if (!url || url->vt != VT_BSTR || url->bstrVal == NULL) { |
144 DLOG(WARNING) << "Invalid URL passed in"; | 144 DLOG(WARNING) << "Invalid URL passed in"; |
145 return S_OK; | 145 return S_OK; |
146 } | 146 } |
147 | 147 |
148 ScopedComPtr<IWebBrowser2> web_browser2; | 148 base::win::ScopedComPtr<IWebBrowser2> web_browser2; |
149 if (dispatch) | 149 if (dispatch) |
150 web_browser2.QueryFrom(dispatch); | 150 web_browser2.QueryFrom(dispatch); |
151 | 151 |
152 if (!web_browser2) { | 152 if (!web_browser2) { |
153 NOTREACHED() << "Can't find WebBrowser2 with given dispatch"; | 153 NOTREACHED() << "Can't find WebBrowser2 with given dispatch"; |
154 return S_OK; | 154 return S_OK; |
155 } | 155 } |
156 | 156 |
157 DVLOG(1) << "BeforeNavigate2: " << url->bstrVal; | 157 DVLOG(1) << "BeforeNavigate2: " << url->bstrVal; |
158 | 158 |
159 ScopedComPtr<IBrowserService> browser_service; | 159 base::win::ScopedComPtr<IBrowserService> browser_service; |
160 DoQueryService(SID_SShellBrowser, web_browser2, browser_service.Receive()); | 160 DoQueryService(SID_SShellBrowser, web_browser2, browser_service.Receive()); |
161 if (!browser_service || !CheckForCFNavigation(browser_service, false)) { | 161 if (!browser_service || !CheckForCFNavigation(browser_service, false)) { |
162 // TODO(tommi): Remove? Isn't this done below by calling set_referrer("")? | 162 // TODO(tommi): Remove? Isn't this done below by calling set_referrer("")? |
163 referrer_.clear(); | 163 referrer_.clear(); |
164 } | 164 } |
165 | 165 |
166 VARIANT_BOOL is_top_level = VARIANT_FALSE; | 166 VARIANT_BOOL is_top_level = VARIANT_FALSE; |
167 web_browser2->get_TopLevelContainer(&is_top_level); | 167 web_browser2->get_TopLevelContainer(&is_top_level); |
168 if (is_top_level) { | 168 if (is_top_level) { |
169 set_url(url->bstrVal); | 169 set_url(url->bstrVal); |
170 set_referrer(""); | 170 set_referrer(""); |
171 set_post_data(post_data); | 171 set_post_data(post_data); |
172 set_headers(headers); | 172 set_headers(headers); |
173 } | 173 } |
174 return S_OK; | 174 return S_OK; |
175 } | 175 } |
176 | 176 |
177 STDMETHODIMP_(void) Bho::NavigateComplete2(IDispatch* dispatch, VARIANT* url) { | 177 STDMETHODIMP_(void) Bho::NavigateComplete2(IDispatch* dispatch, VARIANT* url) { |
178 DVLOG(1) << __FUNCTION__; | 178 DVLOG(1) << __FUNCTION__; |
179 } | 179 } |
180 | 180 |
181 STDMETHODIMP_(void) Bho::DocumentComplete(IDispatch* dispatch, VARIANT* url) { | 181 STDMETHODIMP_(void) Bho::DocumentComplete(IDispatch* dispatch, VARIANT* url) { |
182 DVLOG(1) << __FUNCTION__; | 182 DVLOG(1) << __FUNCTION__; |
183 | 183 |
184 ScopedComPtr<IWebBrowser2> web_browser2; | 184 base::win::ScopedComPtr<IWebBrowser2> web_browser2; |
185 if (dispatch) | 185 if (dispatch) |
186 web_browser2.QueryFrom(dispatch); | 186 web_browser2.QueryFrom(dispatch); |
187 | 187 |
188 if (web_browser2) { | 188 if (web_browser2) { |
189 VARIANT_BOOL is_top_level = VARIANT_FALSE; | 189 VARIANT_BOOL is_top_level = VARIANT_FALSE; |
190 web_browser2->get_TopLevelContainer(&is_top_level); | 190 web_browser2->get_TopLevelContainer(&is_top_level); |
191 if (is_top_level) { | 191 if (is_top_level) { |
192 CrashMetricsReporter::GetInstance()->IncrementMetric( | 192 CrashMetricsReporter::GetInstance()->IncrementMetric( |
193 CrashMetricsReporter::NAVIGATION_COUNT); | 193 CrashMetricsReporter::NAVIGATION_COUNT); |
194 } | 194 } |
195 } | 195 } |
196 } | 196 } |
197 | 197 |
198 namespace { | 198 namespace { |
199 | 199 |
200 // See comments in Bho::OnHttpEquiv for details. | 200 // See comments in Bho::OnHttpEquiv for details. |
201 void ClearDocumentContents(IUnknown* browser) { | 201 void ClearDocumentContents(IUnknown* browser) { |
202 ScopedComPtr<IWebBrowser2> web_browser2; | 202 base::win::ScopedComPtr<IWebBrowser2> web_browser2; |
203 if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser, | 203 if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser, |
204 web_browser2.Receive()))) { | 204 web_browser2.Receive()))) { |
205 ScopedComPtr<IDispatch> doc_disp; | 205 base::win::ScopedComPtr<IDispatch> doc_disp; |
206 web_browser2->get_Document(doc_disp.Receive()); | 206 web_browser2->get_Document(doc_disp.Receive()); |
207 ScopedComPtr<IHTMLDocument2> doc; | 207 base::win::ScopedComPtr<IHTMLDocument2> doc; |
208 if (doc_disp && SUCCEEDED(doc.QueryFrom(doc_disp))) { | 208 if (doc_disp && SUCCEEDED(doc.QueryFrom(doc_disp))) { |
209 SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 0); | 209 SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 0); |
210 doc->write(sa); | 210 doc->write(sa); |
211 ::SafeArrayDestroy(sa); | 211 ::SafeArrayDestroy(sa); |
212 } | 212 } |
213 } | 213 } |
214 } | 214 } |
215 | 215 |
216 // Returns true if the currently loaded document in the browser has | 216 // Returns true if the currently loaded document in the browser has |
217 // any embedded items such as a frame or an iframe. | 217 // any embedded items such as a frame or an iframe. |
218 bool DocumentHasEmbeddedItems(IUnknown* browser) { | 218 bool DocumentHasEmbeddedItems(IUnknown* browser) { |
219 bool has_embedded_items = false; | 219 bool has_embedded_items = false; |
220 | 220 |
221 ScopedComPtr<IWebBrowser2> web_browser2; | 221 base::win::ScopedComPtr<IWebBrowser2> web_browser2; |
222 ScopedComPtr<IDispatch> document; | 222 base::win::ScopedComPtr<IDispatch> document; |
223 if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser, | 223 if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser, |
224 web_browser2.Receive())) && | 224 web_browser2.Receive())) && |
225 SUCCEEDED(web_browser2->get_Document(document.Receive()))) { | 225 SUCCEEDED(web_browser2->get_Document(document.Receive()))) { |
226 ScopedComPtr<IOleContainer> container; | 226 base::win::ScopedComPtr<IOleContainer> container; |
227 if (SUCCEEDED(container.QueryFrom(document))) { | 227 if (SUCCEEDED(container.QueryFrom(document))) { |
228 ScopedComPtr<IEnumUnknown> enumerator; | 228 base::win::ScopedComPtr<IEnumUnknown> enumerator; |
229 container->EnumObjects(OLECONTF_EMBEDDINGS, enumerator.Receive()); | 229 container->EnumObjects(OLECONTF_EMBEDDINGS, enumerator.Receive()); |
230 if (enumerator) { | 230 if (enumerator) { |
231 ScopedComPtr<IUnknown> unk; | 231 base::win::ScopedComPtr<IUnknown> unk; |
232 DWORD fetched = 0; | 232 DWORD fetched = 0; |
233 while (!has_embedded_items && | 233 while (!has_embedded_items && |
234 SUCCEEDED(enumerator->Next(1, unk.Receive(), &fetched)) | 234 SUCCEEDED(enumerator->Next(1, unk.Receive(), &fetched)) |
235 && fetched) { | 235 && fetched) { |
236 // If a top level document has embedded iframes then the theory is | 236 // If a top level document has embedded iframes then the theory is |
237 // that first the top level document finishes loading and then the | 237 // that first the top level document finishes loading and then the |
238 // iframes load. We should only treat an embedded element as an | 238 // iframes load. We should only treat an embedded element as an |
239 // iframe if it supports the IWebBrowser interface. | 239 // iframe if it supports the IWebBrowser interface. |
240 ScopedComPtr<IWebBrowser2> embedded_web_browser2; | 240 base::win::ScopedComPtr<IWebBrowser2> embedded_web_browser2; |
241 if (SUCCEEDED(embedded_web_browser2.QueryFrom(unk))) { | 241 if (SUCCEEDED(embedded_web_browser2.QueryFrom(unk))) { |
242 // If we initiate a top level navigation then at times MSHTML | 242 // If we initiate a top level navigation then at times MSHTML |
243 // creates a temporary IWebBrowser2 interface which basically shows | 243 // creates a temporary IWebBrowser2 interface which basically shows |
244 // up as a temporary iframe in the parent document. It is not clear | 244 // up as a temporary iframe in the parent document. It is not clear |
245 // as to how we can detect this. I tried the usual stuff like | 245 // as to how we can detect this. I tried the usual stuff like |
246 // getting to the parent IHTMLWindow2 interface. They all end up | 246 // getting to the parent IHTMLWindow2 interface. They all end up |
247 // pointing to dummy tear off interfaces owned by MSHTML. | 247 // pointing to dummy tear off interfaces owned by MSHTML. |
248 // As a temporary workaround, we found that the location url in | 248 // As a temporary workaround, we found that the location url in |
249 // this case is about:blank. We now check for the same and don't | 249 // this case is about:blank. We now check for the same and don't |
250 // treat it as an iframe. This should be fine in most cases as we | 250 // treat it as an iframe. This should be fine in most cases as we |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 VARIANT_BOOL is_top_level = VARIANT_FALSE; | 333 VARIANT_BOOL is_top_level = VARIANT_FALSE; |
334 browser->get_TopLevelContainer(&is_top_level); | 334 browser->get_TopLevelContainer(&is_top_level); |
335 DCHECK(is_top_level); | 335 DCHECK(is_top_level); |
336 #endif | 336 #endif |
337 | 337 |
338 std::wstring current_url(url, SysStringLen(url)); | 338 std::wstring current_url(url, SysStringLen(url)); |
339 if (IsValidUrlScheme(GURL(current_url), false)) { | 339 if (IsValidUrlScheme(GURL(current_url), false)) { |
340 bool cf_protocol = StartsWith(current_url, kChromeProtocolPrefix, false); | 340 bool cf_protocol = StartsWith(current_url, kChromeProtocolPrefix, false); |
341 if (!cf_protocol && IsChrome(RendererTypeForUrl(current_url))) { | 341 if (!cf_protocol && IsChrome(RendererTypeForUrl(current_url))) { |
342 DVLOG(1) << "Opt-in URL. Switching to cf."; | 342 DVLOG(1) << "Opt-in URL. Switching to cf."; |
343 ScopedComPtr<IBrowserService> browser_service; | 343 base::win::ScopedComPtr<IBrowserService> browser_service; |
344 DoQueryService(SID_SShellBrowser, browser, browser_service.Receive()); | 344 DoQueryService(SID_SShellBrowser, browser, browser_service.Receive()); |
345 DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed."; | 345 DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed."; |
346 MarkBrowserOnThreadForCFNavigation(browser_service); | 346 MarkBrowserOnThreadForCFNavigation(browser_service); |
347 } | 347 } |
348 } | 348 } |
349 } | 349 } |
350 | 350 |
351 bool PatchHelper::InitializeAndPatchProtocolsIfNeeded() { | 351 bool PatchHelper::InitializeAndPatchProtocolsIfNeeded() { |
352 bool ret = false; | 352 bool ret = false; |
353 | 353 |
(...skipping 19 matching lines...) Expand all Loading... |
373 } | 373 } |
374 } | 374 } |
375 | 375 |
376 void PatchHelper::UnpatchIfNeeded() { | 376 void PatchHelper::UnpatchIfNeeded() { |
377 if (state_ == PATCH_PROTOCOL) { | 377 if (state_ == PATCH_PROTOCOL) { |
378 g_trans_hooks.RevertHooks(); | 378 g_trans_hooks.RevertHooks(); |
379 HttpNegotiatePatch::Uninitialize(); | 379 HttpNegotiatePatch::Uninitialize(); |
380 } | 380 } |
381 state_ = UNKNOWN; | 381 state_ = UNKNOWN; |
382 } | 382 } |
OLD | NEW |