diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-16 00:30:04 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-16 00:30:04 +0000 |
commit | a542e8259fe093c11a55c2656f1fdd3f76c1a1ee (patch) | |
tree | 27c37c019533c9125c52da4ab2f58d7ab01202c5 /chrome_frame | |
parent | b917bd60404fb8f76860e6db5db95396166f45d9 (diff) | |
download | chromium_src-a542e8259fe093c11a55c2656f1fdd3f76c1a1ee.zip chromium_src-a542e8259fe093c11a55c2656f1fdd3f76c1a1ee.tar.gz chromium_src-a542e8259fe093c11a55c2656f1fdd3f76c1a1ee.tar.bz2 |
Updates for onhttpequiv. Preserving the referrer header, zapping the currently loading document to prevent small documents from executing code.
I'm not enabling httpequiv just yet as there are a couple of things I'm working on related to tests that will break once I make the switch.
TEST=There should be no change since the code isn't still active but run all tests just to be safe.
BUG=none
Review URL: http://codereview.chromium.org/545096
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36436 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r-- | chrome_frame/bho.cc | 86 | ||||
-rw-r--r-- | chrome_frame/http_negotiate.cc | 6 | ||||
-rw-r--r-- | chrome_frame/urlmon_url_request.cc | 8 | ||||
-rw-r--r-- | chrome_frame/utils.cc | 15 | ||||
-rw-r--r-- | chrome_frame/utils.h | 3 |
5 files changed, 102 insertions, 16 deletions
diff --git a/chrome_frame/bho.cc b/chrome_frame/bho.cc index 4cb41af..15f1964 100644 --- a/chrome_frame/bho.cc +++ b/chrome_frame/bho.cc @@ -146,6 +146,7 @@ STDMETHODIMP Bho::BeforeNavigate2(IDispatch* dispatch, VARIANT* url, } } } + return S_OK; } @@ -156,12 +157,56 @@ HRESULT Bho::FinalConstruct() { void Bho::FinalRelease() { } +namespace { + +// See comments in Bho::OnHttpEquiv for details. +void ClearDocumentContents(IUnknown* browser) { + ScopedComPtr<IWebBrowser2> web_browser2; + if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser, + web_browser2.Receive()))) { + ScopedComPtr<IDispatch> doc_disp; + web_browser2->get_Document(doc_disp.Receive()); + ScopedComPtr<IHTMLDocument2> doc; + if (doc_disp && SUCCEEDED(doc.QueryFrom(doc_disp))) { + SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 0); + doc->write(sa); + ::SafeArrayDestroy(sa); + } + } +} + +// Returns true if the currently loaded document in the browser has +// any embedded items such as a frame or an iframe. +bool DocumentHasEmbeddedItems(IUnknown* browser) { + bool has_embedded_items = false; + + ScopedComPtr<IWebBrowser2> web_browser2; + ScopedComPtr<IDispatch> document; + if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser, + web_browser2.Receive())) && + SUCCEEDED(web_browser2->get_Document(document.Receive()))) { + ScopedComPtr<IOleContainer> container; + if (SUCCEEDED(container.QueryFrom(document))) { + ScopedComPtr<IEnumUnknown> enumerator; + container->EnumObjects(OLECONTF_EMBEDDINGS, enumerator.Receive()); + if (enumerator) { + ScopedComPtr<IUnknown> unk; + DWORD fetched = 0; + enumerator->Next(1, unk.Receive(), &fetched); + has_embedded_items = (fetched != 0); + } + } + } + + return has_embedded_items; +} + +} // end namespace + HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv, IBrowserService* browser, IShellView* shell_view, BOOL done, VARIANT* in_arg, VARIANT* 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); + DLOG(INFO) << __FUNCTION__ << " done:" << done; // OnHttpEquiv with 'done' set to TRUE is called for all pages. // 0 or more calls with done set to FALSE are made. @@ -171,6 +216,16 @@ HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv, if (done) { if (CheckForCFNavigation(browser, false)) { + // TODO(tommi): See if we can't figure out a cleaner way to avoid this. + // For small documents we can hit a problem here. When we attempt to + // navigate the document again in CF, mshtml can "complete" the current + // navigation (if all data is available) and fire off script events such + // as onload and even render the page. This will happen inside + // NavigateBrowserToMoniker below. + // To work around this, we clear the contents of the document before + // opening it up in CF. + ClearDocumentContents(browser); + ScopedComPtr<IOleObject> mshtml_ole_object; HRESULT hr = shell_view->GetItemObject(SVGIO_BACKGROUND, IID_IOleObject, reinterpret_cast<void**>(mshtml_ole_object.Receive())); @@ -186,8 +241,19 @@ HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv, // 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); + + // If there's a referrer, preserve it. + std::wstring headers; + Bho* chrome_frame_bho = Bho::GetCurrentThreadBhoInstance(); + if (chrome_frame_bho && !chrome_frame_bho->referrer().empty()) { + headers = StringPrintf(L"Referer: %ls\r\n\r\n", + ASCIIToWide(chrome_frame_bho->referrer()).c_str()); + } + + hr = NavigateBrowserToMoniker(browser, moniker, headers.c_str(), + bind_context); } else { DLOG(ERROR) << "Couldn't get the current moniker"; } @@ -202,9 +268,17 @@ HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv, // HttpNegotiatePatch::ReportProgress when the mime type is reported. } } - } else if (is_top_level && in_arg && VT_BSTR == V_VT(in_arg)) { + } else if (in_arg && VT_BSTR == V_VT(in_arg)) { if (StrStrI(V_BSTR(in_arg), kChromeContentPrefix)) { - MarkBrowserOnThreadForCFNavigation(browser); + // OnHttpEquiv is invoked for meta tags within sub frames as well. + // We want to switch renderers only for the top level frame. + // The theory here is that if there are any existing embedded items + // (frames or iframes) in the current document, then the http-equiv + // notification is coming from those and not the top level document. + // The embedded items should only be created once the top level + // doc has been created. + if (!DocumentHasEmbeddedItems(browser)) + MarkBrowserOnThreadForCFNavigation(browser); } } diff --git a/chrome_frame/http_negotiate.cc b/chrome_frame/http_negotiate.cc index b938cae..f118baf 100644 --- a/chrome_frame/http_negotiate.cc +++ b/chrome_frame/http_negotiate.cc @@ -131,7 +131,7 @@ HRESULT HttpNegotiatePatch::PatchHttpNegotiate(IUnknown* to_patch) { HRESULT HttpNegotiatePatch::BeginningTransaction( IHttpNegotiate_BeginningTransaction_Fn original, IHttpNegotiate* me, LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR* additional_headers) { - DLOG(INFO) << __FUNCTION__ << " " << url; + DLOG(INFO) << __FUNCTION__ << " " << url << " headers:\n" << headers; HRESULT hr = original(me, url, headers, reserved, additional_headers); @@ -145,8 +145,10 @@ HRESULT HttpNegotiatePatch::BeginningTransaction( using net::HttpUtil; std::string ascii_headers; - if (*additional_headers) + if (*additional_headers) { ascii_headers = WideToASCII(*additional_headers); + DLOG(INFO) << __FUNCTION__ << " additional headers: " << ascii_headers; + } HttpUtil::HeadersIterator headers_iterator(ascii_headers.begin(), ascii_headers.end(), "\r\n"); diff --git a/chrome_frame/urlmon_url_request.cc b/chrome_frame/urlmon_url_request.cc index 8831447..5a946ce 100644 --- a/chrome_frame/urlmon_url_request.cc +++ b/chrome_frame/urlmon_url_request.cc @@ -150,7 +150,8 @@ class WrappedBindContext : public IBindCtx, } STDMETHOD(RegisterObjectParam)(LPOLESTR key, IUnknown* object) { - DLOG(INFO) << "In " << __FUNCTION__ << " for object: " << this; + DLOG(INFO) << "In " << __FUNCTION__ << " for object: " << this << " key: " + << key; ScopedComPtr<IBindCtx> bind_context; HRESULT hr = GetMarshalledBindContext(bind_context.Receive()); @@ -161,7 +162,8 @@ class WrappedBindContext : public IBindCtx, } STDMETHOD(GetObjectParam)(LPOLESTR key, IUnknown** object) { - DLOG(INFO) << "In " << __FUNCTION__ << " for object: " << this; + DLOG(INFO) << "In " << __FUNCTION__ << " for object: " << this << " key: " + << key; ScopedComPtr<IBindCtx> bind_context; HRESULT hr = GetMarshalledBindContext(bind_context.Receive()); @@ -339,7 +341,7 @@ void UrlmonUrlRequest::TransferToHost(IUnknown* host) { ScopedComPtr<IBindCtx> bind_context; CreateBindCtx(0, bind_context.Receive()); DCHECK(bind_context); - NavigateBrowserToMoniker(host, moniker_, bind_context); + NavigateBrowserToMoniker(host, moniker_, NULL, bind_context); moniker_.Release(); } } diff --git a/chrome_frame/utils.cc b/chrome_frame/utils.cc index af85cb4..67b1217 100644 --- a/chrome_frame/utils.cc +++ b/chrome_frame/utils.cc @@ -636,7 +636,7 @@ bool IsOptInUrl(const wchar_t* url) { } HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, - IBindCtx* bind_ctx) { + const wchar_t* headers, IBindCtx* bind_ctx) { DCHECK(browser); DCHECK(moniker); DCHECK(bind_ctx); @@ -667,6 +667,10 @@ HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, ScopedComPtr<IUriContainer> uri_container; hr = uri_container.QueryFrom(moniker); + ScopedVariant headers_var; + if (headers && headers[0]) + headers_var.Set(headers); + if (uri_container) { // IE7 and IE8. const IID* interface_ids[] = { @@ -688,8 +692,10 @@ HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, ScopedComPtr<IUri> uri_obj; uri_container->GetIUri(uri_obj.Receive()); DCHECK(uri_obj); - hr = browser_priv2->NavigateWithBindCtx2(uri_obj, NULL, NULL, NULL, NULL, - bind_ctx, NULL); + + hr = browser_priv2->NavigateWithBindCtx2(uri_obj, NULL, NULL, NULL, + headers_var.AsInput(), bind_ctx, + NULL); DLOG_IF(WARNING, FAILED(hr)) << StringPrintf(L"NavigateWithBindCtx2 0x%08X", hr); } @@ -702,7 +708,8 @@ HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, 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); + NULL, headers_var.AsInput(), + bind_ctx, NULL); DLOG_IF(WARNING, FAILED(hr)) << StringPrintf(L"NavigateWithBindCtx 0x%08X", hr); } else { diff --git a/chrome_frame/utils.h b/chrome_frame/utils.h index ab25cf2..8048beb 100644 --- a/chrome_frame/utils.h +++ b/chrome_frame/utils.h @@ -223,8 +223,9 @@ HRESULT GetUrlFromMoniker(IMoniker* moniker, IBindCtx* bind_context, std::wstring* url); // Navigates an IWebBrowser2 object to a moniker. +// |headers| can be NULL. HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, - IBindCtx* bind_ctx); + const wchar_t* headers, 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. |