summaryrefslogtreecommitdiffstats
path: root/chrome_frame/bho.cc
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-11 19:31:56 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-11 19:31:56 +0000
commitb22ef28f215f7475f1c0401f89e353a8aacf8def (patch)
tree045041d0534fb9aa8b6b009e3a7499809b42e7ed /chrome_frame/bho.cc
parent2f7aff273b0a1357e79d99e2f31ede1f702d8783 (diff)
downloadchromium_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.cc125
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() {