summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--chrome_frame/bho.cc125
-rw-r--r--chrome_frame/bho.h5
-rw-r--r--chrome_frame/chrome_frame_activex.cc1
-rw-r--r--chrome_frame/extra_system_apis.h2
-rw-r--r--chrome_frame/http_negotiate.cc58
-rw-r--r--chrome_frame/urlmon_url_request.cc84
-rw-r--r--chrome_frame/utils.cc123
-rw-r--r--chrome_frame/utils.h16
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.