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/utils.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/utils.cc')
-rw-r--r-- | chrome_frame/utils.cc | 123 |
1 files changed, 104 insertions, 19 deletions
diff --git a/chrome_frame/utils.cc b/chrome_frame/utils.cc index 32524cd..c18cb93 100644 --- a/chrome_frame/utils.cc +++ b/chrome_frame/utils.cc @@ -7,21 +7,23 @@ #include <shlobj.h> #include <wininet.h> -#include "chrome_frame/html_utils.h" -#include "chrome_frame/utils.h" - #include "base/file_util.h" #include "base/file_version_info.h" +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/path_service.h" #include "base/registry.h" #include "base/scoped_comptr_win.h" +#include "base/scoped_variant_win.h" #include "base/string_util.h" +#include "base/thread_local.h" #include "chrome/common/url_constants.h" #include "chrome/installer/util/chrome_frame_distribution.h" +#include "chrome_frame/extra_system_apis.h" +#include "chrome_frame/html_utils.h" +#include "chrome_frame/utils.h" #include "googleurl/src/gurl.h" #include "grit/chrome_frame_resources.h" -#include "chrome_frame/resource.h" // Note that these values are all lower case and are compared to // lower-case-transformed values. @@ -51,6 +53,17 @@ const wchar_t kChromeAttachExternalTabPrefix[] = L"attach_external_tab"; // are handled by the chrome test crash server. const wchar_t kChromeFrameHeadlessMode[] = L"ChromeFrameHeadlessMode"; +namespace { + +// A flag used to signal when an active browser instance on the current thread +// is loading a Chrome Frame document. There's no reference stored with the +// pointer so it should not be dereferenced and used for comparison against a +// living instance only. +base::LazyInstance<base::ThreadLocalPointer<IBrowserService> > + g_tls_browser_for_cf_navigation(base::LINKER_INITIALIZED); + +} // end anonymous namespace + HRESULT UtilRegisterTypeLib(HINSTANCE tlb_instance, LPCOLESTR index, bool for_current_user_only) { @@ -591,27 +604,99 @@ bool IsOptInUrl(const wchar_t* url) { return false; } -HRESULT GetUrlFromMoniker(IMoniker* moniker, IBindCtx* bind_context, - std::wstring* url) { - if (!moniker || !url) { - NOTREACHED(); - return E_INVALIDARG; - } +HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, + IBindCtx* bind_ctx) { + DCHECK(browser); + DCHECK(moniker); + DCHECK(bind_ctx); + + ScopedComPtr<IWebBrowser2> web_browser2; + HRESULT hr = DoQueryService(SID_SWebBrowserApp, browser, + web_browser2.Receive()); + DCHECK(web_browser2); + DLOG_IF(WARNING, FAILED(hr)) << StringPrintf(L"SWebBrowserApp 0x%08X", hr); + if (FAILED(hr)) + return hr; + + // Create a new bind context that's not associated with our callback. + // Calling RevokeBindStatusCallback doesn't disassociate the callback with + // the bind context in IE7. The returned bind context has the same + // implementation of GetRunningObjectTable as the bind context we held which + // basically delegates to ole32's GetRunningObjectTable. The object table + // is then used to determine if the moniker is already running and via + // that mechanism is associated with the same internet request as has already + // been issued. + + // TODO(tommi): See if we can get HlinkSimpleNavigateToMoniker to work + // instead. Looks like we'll need to support IHTMLDocument2 (get_URL in + // particular), access to IWebBrowser2 etc. + // HlinkSimpleNavigateToMoniker(moniker, url, NULL, host, bind_context, + // NULL, 0, 0); + + ScopedComPtr<IUriContainer> uri_container; + hr = uri_container.QueryFrom(moniker); + + if (uri_container) { + // IE7 and IE8. + ScopedComPtr<IWebBrowserPriv2IE7> browser_priv2_ie7; + ScopedComPtr<IWebBrowserPriv2IE8> browser_priv2_ie8; + IWebBrowserPriv2IE7* common_browser_priv2 = NULL; + if (SUCCEEDED(hr = browser_priv2_ie7.QueryFrom(web_browser2))) { + common_browser_priv2 = browser_priv2_ie7; + } else if (SUCCEEDED(hr = browser_priv2_ie8.QueryFrom(web_browser2))) { + common_browser_priv2 = + reinterpret_cast<IWebBrowserPriv2IE7*>(browser_priv2_ie8.get()); + } - ScopedComPtr<IBindCtx> temp_bind_context; - if (!bind_context) { - CreateBindCtx(0, temp_bind_context.Receive()); - bind_context = temp_bind_context; - } + DCHECK(common_browser_priv2); - CComHeapPtr<WCHAR> display_name; - HRESULT hr = moniker->GetDisplayName(bind_context, NULL, &display_name); - if (display_name) - *url = display_name; + if (common_browser_priv2) { + ScopedComPtr<IUri> uri_obj; + uri_container->GetIUri(uri_obj.Receive()); + DCHECK(uri_obj); + hr = common_browser_priv2->NavigateWithBindCtx2(uri_obj, NULL, NULL, NULL, + NULL, bind_ctx, NULL); + DLOG_IF(WARNING, FAILED(hr)) + << StringPrintf(L"NavigateWithBindCtx2 0x%08X", hr); + } + } else { + // IE6 + LPOLESTR url = NULL; + if (SUCCEEDED(hr = moniker->GetDisplayName(bind_ctx, NULL, &url))) { + DLOG(INFO) << __FUNCTION__ << " " << url; + ScopedComPtr<IWebBrowserPriv> browser_priv; + if (SUCCEEDED(hr = browser_priv.QueryFrom(web_browser2))) { + ScopedVariant var_url(url); + hr = browser_priv->NavigateWithBindCtx(var_url.AsInput(), NULL, NULL, + NULL, NULL, bind_ctx, NULL); + DLOG_IF(WARNING, FAILED(hr)) + << StringPrintf(L"NavigateWithBindCtx 0x%08X", hr); + } else { + NOTREACHED(); + } + ::CoTaskMemFree(url); + } else { + DLOG(ERROR) << StringPrintf("GetDisplayName: 0x%08X", hr); + } + } return hr; } +void MarkBrowserOnThreadForCFNavigation(IBrowserService* browser) { + DCHECK(browser != NULL); + DCHECK(g_tls_browser_for_cf_navigation.Pointer()->Get() == NULL); + g_tls_browser_for_cf_navigation.Pointer()->Set(browser); +} + +bool CheckForCFNavigation(IBrowserService* browser, bool clear_flag) { + DCHECK(browser); + bool ret = (g_tls_browser_for_cf_navigation.Pointer()->Get() == browser); + if (ret && clear_flag) + g_tls_browser_for_cf_navigation.Pointer()->Set(NULL); + return ret; +} + bool IsValidUrlScheme(const std::wstring& url, bool is_privileged) { if (url.empty()) return false; |