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 | |
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
-rw-r--r-- | chrome_frame/bho.cc | 125 | ||||
-rw-r--r-- | chrome_frame/bho.h | 5 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_activex.cc | 1 | ||||
-rw-r--r-- | chrome_frame/extra_system_apis.h | 2 | ||||
-rw-r--r-- | chrome_frame/http_negotiate.cc | 58 | ||||
-rw-r--r-- | chrome_frame/urlmon_url_request.cc | 84 | ||||
-rw-r--r-- | chrome_frame/utils.cc | 123 | ||||
-rw-r--r-- | chrome_frame/utils.h | 16 |
8 files changed, 210 insertions, 204 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() { diff --git a/chrome_frame/bho.h b/chrome_frame/bho.h index 2838fec..d30ae49 100644 --- a/chrome_frame/bho.h +++ b/chrome_frame/bho.h @@ -100,10 +100,7 @@ END_SINK_MAP() protected: bool PatchProtocolHandler(const CLSID& handler_clsid); - static bool HasSubFrames(IWebBrowser2* web_browser2); - static HRESULT SwitchRenderer(IWebBrowser2* web_browser2, - IBrowserService* browser, IShellView* shell_view, - const wchar_t* meta_tag); + std::string referrer_; static base::LazyInstance<base::ThreadLocalPointer<Bho> > diff --git a/chrome_frame/chrome_frame_activex.cc b/chrome_frame/chrome_frame_activex.cc index 297b5ad..e8fa70a 100644 --- a/chrome_frame/chrome_frame_activex.cc +++ b/chrome_frame/chrome_frame_activex.cc @@ -4,7 +4,6 @@ #include "chrome_frame/chrome_frame_activex.h" -#include <shdeprecated.h> // for IBrowserService2 #include <wininet.h> #include <algorithm> diff --git a/chrome_frame/extra_system_apis.h b/chrome_frame/extra_system_apis.h index 2258298..724b0c8f 100644 --- a/chrome_frame/extra_system_apis.h +++ b/chrome_frame/extra_system_apis.h @@ -8,6 +8,8 @@ #ifndef CHROME_FRAME_EXTRA_SYSTEM_APIS_H_ #define CHROME_FRAME_EXTRA_SYSTEM_APIS_H_ +#include <mshtml.h> + // This is an interface provided by the WebBrowser object. It allows us to // notify the browser of navigation events. MSDN documents this interface // (see http://msdn2.microsoft.com/en-us/library/aa752109(VS.85).aspx) diff --git a/chrome_frame/http_negotiate.cc b/chrome_frame/http_negotiate.cc index ef996e5..b938cae 100644 --- a/chrome_frame/http_negotiate.cc +++ b/chrome_frame/http_negotiate.cc @@ -234,28 +234,38 @@ HRESULT HttpNegotiatePatch::ReportProgress( if (status_code == BINDSTATUS_MIMETYPEAVAILABLE || status_code == BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE || status_code == LOCAL_BINDSTATUS_SERVER_MIMETYPEAVAILABLE) { - bool is_top_level_request = !IsSubFrameRequest(me); - - if (is_top_level_request) { - // Check to see if we need to alter the mime type that gets reported - // by inspecting the raw header information: - ScopedComPtr<IWinInetHttpInfo> win_inet_http_info; - HRESULT hr = win_inet_http_info.QueryFrom(me); - - // Try slightly harder if we couldn't QI directly. - if (!win_inet_http_info || FAILED(hr)) { - hr = DoQueryService(IID_IWinInetHttpInfo, me, - win_inet_http_info.Receive()); - } + bool render_in_chrome_frame = false; + + // Check if this is a top level browser request that should be + // rendered in CF. + ScopedComPtr<IBrowserService> browser; + DoQueryService(IID_IShellBrowser, me, browser.Receive()); + if (browser) { + render_in_chrome_frame = CheckForCFNavigation(browser, true); + } + + if (!render_in_chrome_frame) { + bool is_top_level_request = !IsSubFrameRequest(me); + + if (is_top_level_request) { + // Check to see if we need to alter the mime type that gets reported + // by inspecting the raw header information: + ScopedComPtr<IWinInetHttpInfo> win_inet_http_info; + HRESULT hr = win_inet_http_info.QueryFrom(me); - // Note that it has been observed that getting an IWinInetHttpInfo will - // fail if we are loading a page like about:blank that isn't loaded via - // wininet. - if (win_inet_http_info) { - // We have headers: check to see if the server is requesting CF via - // the X-UA-Compatible: chrome=1 HTTP header. - std::string headers(GetRawHttpHeaders(win_inet_http_info)); - if (net::HttpUtil::HasHeader(headers, kUACompatibleHttpHeader)) { + // Try slightly harder if we couldn't QI directly. + if (!win_inet_http_info || FAILED(hr)) { + hr = DoQueryService(IID_IWinInetHttpInfo, me, + win_inet_http_info.Receive()); + } + + // Note that it has been observed that getting an IWinInetHttpInfo will + // fail if we are loading a page like about:blank that isn't loaded via + // wininet. + if (win_inet_http_info) { + // We have headers: check to see if the server is requesting CF via + // the X-UA-Compatible: chrome=1 HTTP header. + std::string headers(GetRawHttpHeaders(win_inet_http_info)); net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); while (it.GetNext()) { @@ -263,7 +273,7 @@ HRESULT HttpNegotiatePatch::ReportProgress( kUACompatibleHttpHeader)) { std::string ua_value(StringToLowerASCII(it.values())); if (ua_value.find("chrome=1") != std::string::npos) { - status_text = kChromeMimeType; + render_in_chrome_frame = true; break; } } @@ -271,6 +281,10 @@ HRESULT HttpNegotiatePatch::ReportProgress( } } } + + if (render_in_chrome_frame) { + status_text = kChromeMimeType; + } } return original(me, status_code, status_text); diff --git a/chrome_frame/urlmon_url_request.cc b/chrome_frame/urlmon_url_request.cc index 5bb78c2..2e39bea 100644 --- a/chrome_frame/urlmon_url_request.cc +++ b/chrome_frame/urlmon_url_request.cc @@ -136,85 +136,13 @@ bool UrlmonUrlRequest::Read(int bytes_to_read) { void UrlmonUrlRequest::TransferToHost(IUnknown* host) { DCHECK_EQ(PlatformThread::CurrentId(), thread_); DCHECK(host); - DCHECK(moniker_); - if (!moniker_) - return; - - ScopedComPtr<IMoniker> moniker; - moniker.Attach(moniker_.Detach()); - - // 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. - ScopedComPtr<IBindCtx> bind_context; - CreateBindCtx(0, bind_context.Receive()); - DCHECK(bind_context); - - LPOLESTR url = NULL; - if (SUCCEEDED(moniker->GetDisplayName(bind_context, NULL, &url))) { - DLOG(INFO) << __FUNCTION__ << " " << url; - - // 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<IWebBrowser2> wb2; - HRESULT hr = DoQueryService(SID_SWebBrowserApp, host, wb2.Receive()); - DCHECK(wb2); - DLOG_IF(WARNING, FAILED(hr)) << StringPrintf(L"SWebBrowserApp 0x%08X", hr); - - ScopedComPtr<IWebBrowserPriv> wbp; - ScopedComPtr<IWebBrowserPriv2IE7> wbp2_ie7; - ScopedComPtr<IWebBrowserPriv2IE8> wbp2_ie8; - if (SUCCEEDED(hr = wbp.QueryFrom(wb2))) { - ScopedVariant var_url(url); - hr = wbp->NavigateWithBindCtx(var_url.AsInput(), NULL, NULL, NULL, NULL, - bind_context, NULL); - DLOG_IF(WARNING, FAILED(hr)) - << StringPrintf(L"NavigateWithBindCtx 0x%08X", hr); - } else { - DLOG(WARNING) << StringPrintf(L"IWebBrowserPriv 0x%08X", hr); - IWebBrowserPriv2IE7* common_wbp2 = NULL; - if (SUCCEEDED(hr = wbp2_ie7.QueryFrom(wb2))) { - common_wbp2 = wbp2_ie7; - } else if (SUCCEEDED(hr = wbp2_ie8.QueryFrom(wb2))) { - common_wbp2 = reinterpret_cast<IWebBrowserPriv2IE7*>(wbp2_ie8.get()); - } - - if (common_wbp2) { - typedef HRESULT (WINAPI* CreateUriFn)(LPCWSTR uri, DWORD flags, - DWORD_PTR reserved, IUri** ret); - - CreateUriFn create_uri = reinterpret_cast<CreateUriFn>( - ::GetProcAddress(::GetModuleHandleA("urlmon"), "CreateUri")); - DCHECK(create_uri); - if (create_uri) { - ScopedComPtr<IUri> uri_obj; - hr = create_uri(url, 0, 0, uri_obj.Receive()); - DLOG_IF(WARNING, FAILED(hr)) - << StringPrintf(L"create_uri 0x%08X", hr); - hr = common_wbp2->NavigateWithBindCtx2(uri_obj, NULL, NULL, NULL, - NULL, bind_context, NULL); - DLOG_IF(WARNING, FAILED(hr)) - << StringPrintf(L"NavigateWithBindCtx2 0x%08X", hr); - } - } else { - DLOG(WARNING) << StringPrintf(L"IWebBrowserPriv2 0x%08X", hr); - NOTREACHED(); - } - } - - DCHECK(wbp || wbp2_ie7 || wbp2_ie8); - - ::CoTaskMemFree(url); + if (moniker_) { + ScopedComPtr<IBindCtx> bind_context; + CreateBindCtx(0, bind_context.Receive()); + DCHECK(bind_context); + NavigateBrowserToMoniker(host, moniker_, bind_context); + moniker_.Release(); } } 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; diff --git a/chrome_frame/utils.h b/chrome_frame/utils.h index f71bb7d..8750794 100644 --- a/chrome_frame/utils.h +++ b/chrome_frame/utils.h @@ -7,7 +7,8 @@ #include <atlbase.h> #include <string> -#include <UrlMon.h> +#include <shdeprecated.h> +#include <urlmon.h> #include "base/basictypes.h" #include "base/logging.h" @@ -215,6 +216,19 @@ HRESULT DoQueryService(const IID& service_id, IUnknown* unk, T** service) { HRESULT GetUrlFromMoniker(IMoniker* moniker, IBindCtx* bind_context, std::wstring* url); +// Navigates an IWebBrowser2 object to a moniker. +HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, + IBindCtx* bind_ctx); + +// Raises a flag on the current thread (using TLS) to indicate that an +// in-progress navigation should be rendered in chrome frame. +void MarkBrowserOnThreadForCFNavigation(IBrowserService* browser); + +// Checks if this browser instance has been marked as currently navigating +// to a CF document. If clear_flag is set to true, the tls flag is cleared but +// only if the browser has been marked. +bool CheckForCFNavigation(IBrowserService* browser, bool clear_flag); + // Returns true if the URL passed in is something which can be handled by // Chrome. If this function returns false then we should fail the navigation. // When is_privileged is true, chrome extension URLs will be considered valid. |