diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-11 19:31:56 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-11 19:31:56 +0000 |
commit | b22ef28f215f7475f1c0401f89e353a8aacf8def (patch) | |
tree | 045041d0534fb9aa8b6b009e3a7499809b42e7ed /chrome_frame/bho.cc | |
parent | 2f7aff273b0a1357e79d99e2f31ede1f702d8783 (diff) | |
download | chromium_src-b22ef28f215f7475f1c0401f89e353a8aacf8def.zip chromium_src-b22ef28f215f7475f1c0401f89e353a8aacf8def.tar.gz chromium_src-b22ef28f215f7475f1c0401f89e353a8aacf8def.tar.bz2 |
Use the OnHttpEquiv notification to switch to CF when the http-equiv meta tag is detected. This implementation is still behind the registry switch (set PatchProtocols to 0 in the registry). I will switch over to it wholesale in a separate patch.
We use the same mechanism for re-initiating the navigation we use to transfer downloads over to the host, so I moved the common code to utils.cc and added NavigateBrowserToMoniker.
When we see a browser instance attempting to load a CF document, we raise a TLS flag that we catch in HttpNegotiatePatch::ReportProgress when the mime type is being reported. This is the same place where we examine http headers and report the mime type.
BUG=n/a
TEST=Set PatchProtocols (REG_DWORD) to 0 in the CF HKCU config key and make sure we detect and handle the meta tag as well or better than before.
Review URL: http://codereview.chromium.org/489004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34366 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/bho.cc')
-rw-r--r-- | chrome_frame/bho.cc | 125 |
1 files changed, 46 insertions, 79 deletions
diff --git a/chrome_frame/bho.cc b/chrome_frame/bho.cc index 8e95afb..4cb41af 100644 --- a/chrome_frame/bho.cc +++ b/chrome_frame/bho.cc @@ -156,92 +156,59 @@ HRESULT Bho::FinalConstruct() { void Bho::FinalRelease() { } -HRESULT STDMETHODCALLTYPE Bho::OnHttpEquiv( - IBrowserService_OnHttpEquiv_Fn original_httpequiv, +HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv, IBrowserService* browser, IShellView* shell_view, BOOL done, VARIANT* in_arg, VARIANT* out_arg) { - if (!done && in_arg && (VT_BSTR == V_VT(in_arg))) { - if (StrStrI(V_BSTR(in_arg), kChromeContentPrefix)) { - // OnHttpEquiv is invoked for meta tags within sub frames as well. - // We want to switch renderers only for the top level frame. Since - // the same |browser| and |shell_view| are passed in to OnHttpEquiv - // even for sub iframes, we determine if this is the top one by - // checking if there are any sub frames created or not. - ScopedComPtr<IWebBrowser2> web_browser2; - DoQueryService(SID_SWebBrowserApp, browser, web_browser2.Receive()); - if (web_browser2 && !HasSubFrames(web_browser2)) - SwitchRenderer(web_browser2, browser, shell_view, V_BSTR(in_arg)); - } - } - - return original_httpequiv(browser, shell_view, done, in_arg, out_arg); -} + // OnHttpEquiv is invoked for meta tags within sub frames as well. + // We want to switch renderers only for the top level frame. + bool is_top_level = (browser->GetBrowserIndex() == -1); + + // OnHttpEquiv with 'done' set to TRUE is called for all pages. + // 0 or more calls with done set to FALSE are made. + // When done is FALSE, the current moniker may not represent the page + // being navigated to so we always have to wait for done to be TRUE + // before re-initiating the navigation. + + if (done) { + if (CheckForCFNavigation(browser, false)) { + ScopedComPtr<IOleObject> mshtml_ole_object; + HRESULT hr = shell_view->GetItemObject(SVGIO_BACKGROUND, IID_IOleObject, + reinterpret_cast<void**>(mshtml_ole_object.Receive())); + DCHECK(FAILED(hr) || mshtml_ole_object != NULL); + if (mshtml_ole_object) { + ScopedComPtr<IMoniker> moniker; + hr = mshtml_ole_object->GetMoniker(OLEGETMONIKER_ONLYIFTHERE, + OLEWHICHMK_OBJFULL, moniker.Receive()); + DCHECK(FAILED(hr) || moniker != NULL); + if (moniker) { + DLOG(INFO) << "Navigating in CF"; + ScopedComPtr<IBindCtx> bind_context; + // This bind context will be discarded by IE and a new one + // constructed, so it's OK to create a sync bind context. + ::CreateBindCtx(0, bind_context.Receive()); + DCHECK(bind_context); + hr = NavigateBrowserToMoniker(browser, moniker, bind_context); + } else { + DLOG(ERROR) << "Couldn't get the current moniker"; + } + } -bool Bho::HasSubFrames(IWebBrowser2* web_browser2) { - bool has_sub_frames = false; - ScopedComPtr<IDispatch> doc_dispatch; - if (web_browser2) { - HRESULT hr = web_browser2->get_Document(doc_dispatch.Receive()); - DCHECK(SUCCEEDED(hr) && doc_dispatch) << - "web_browser2->get_Document failed. Error: " << hr; - ScopedComPtr<IOleContainer> container; - if (SUCCEEDED(hr) && doc_dispatch) { - container.QueryFrom(doc_dispatch); - ScopedComPtr<IEnumUnknown> enumerator; - if (container) { - container->EnumObjects(OLECONTF_EMBEDDINGS, enumerator.Receive()); - ScopedComPtr<IUnknown> unk; - ULONG items_retrieved = 0; - if (enumerator) - enumerator->Next(1, unk.Receive(), &items_retrieved); - has_sub_frames = (items_retrieved != 0); + if (FAILED(hr)) { + NOTREACHED(); + // Lower the flag. + CheckForCFNavigation(browser, true); + } else { + // The navigate-in-gcf flag will be cleared in + // HttpNegotiatePatch::ReportProgress when the mime type is reported. } } + } else if (is_top_level && in_arg && VT_BSTR == V_VT(in_arg)) { + if (StrStrI(V_BSTR(in_arg), kChromeContentPrefix)) { + MarkBrowserOnThreadForCFNavigation(browser); + } } - return has_sub_frames; -} - -HRESULT Bho::SwitchRenderer(IWebBrowser2* web_browser2, - IBrowserService* browser, IShellView* shell_view, - const wchar_t* meta_tag) { - DCHECK(web_browser2 && browser && shell_view && meta_tag); - - // Get access to the mshtml instance and the moniker - ScopedComPtr<IOleObject> mshtml_ole_object; - HRESULT hr = shell_view->GetItemObject(SVGIO_BACKGROUND, IID_IOleObject, - reinterpret_cast<void**>(mshtml_ole_object.Receive())); - if (!mshtml_ole_object) { - NOTREACHED() << "shell_view->GetItemObject failed. Error: " << hr; - return hr; - } - - std::wstring url; - ScopedComPtr<IMoniker> moniker; - hr = mshtml_ole_object->GetMoniker(OLEGETMONIKER_ONLYIFTHERE, - OLEWHICHMK_OBJFULL, moniker.Receive()); - DCHECK(moniker) << "mshtml_ole_object->GetMoniker failed. Error: " << hr; - - if (moniker) - hr = GetUrlFromMoniker(moniker, NULL, &url); - - DCHECK(!url.empty()) << "GetUrlFromMoniker failed. Error: " << hr; - DCHECK(!StartsWith(url, kChromeProtocolPrefix, false)); - - if (!url.empty()) { - url.insert(0, kChromeProtocolPrefix); - // Navigate to new url - VARIANT empty = ScopedVariant::kEmptyVariant; - VARIANT flags = { VT_I4 }; - V_I4(&flags) = 0; - ScopedVariant url_var(url.c_str()); - hr = web_browser2->Navigate2(url_var.AsInput(), &flags, &empty, &empty, - &empty); - DCHECK(SUCCEEDED(hr)) << "web_browser2->Navigate2 failed. Error: " << hr - << std::endl << "Url: " << url; - } - - return S_OK; + return original_httpequiv(browser, shell_view, done, in_arg, out_arg); } Bho* Bho::GetCurrentThreadBhoInstance() { |