diff options
author | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-28 22:18:33 +0000 |
---|---|---|
committer | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-28 22:18:33 +0000 |
commit | f4fbae68a3fbdea8d14af164ddaa5986b4eefd6c (patch) | |
tree | f89c5ee0329d5ab17ad0281ff45589f4cb1e3940 /chrome_frame/utils.cc | |
parent | 1d9104aa2450fd4dd21cfb2e1a73ddc0e0613f50 (diff) | |
download | chromium_src-f4fbae68a3fbdea8d14af164ddaa5986b4eefd6c.zip chromium_src-f4fbae68a3fbdea8d14af164ddaa5986b4eefd6c.tar.gz chromium_src-f4fbae68a3fbdea8d14af164ddaa5986b4eefd6c.tar.bz2 |
Download requests in ChromeFrame which occur in response to a POST request need to pass
the post data as well while reissuing the navigation. This ensures that a POST request is
correctly sent out at all times instead of a GET request. While the assumption is that reusing
the bind context would achieve this behavior, it does not appear to be true at all times.
While fixing this I also found that reissuing a navigation via a NavigateWithBindCtx call
causes the current chrome frame document to receive an Unload call at times, leading to
the page being rendered useless after the request finishes. We should reissue the navigation
on a new window to work around this problem.
Fixes bug http://code.google.com/p/chromium/issues/detail?id=73985
BUG=73985
TEST=As described in the bug.
Review URL: http://codereview.chromium.org/6598016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76282 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/utils.cc')
-rw-r--r-- | chrome_frame/utils.cc | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/chrome_frame/utils.cc b/chrome_frame/utils.cc index 7182428..1db94dc 100644 --- a/chrome_frame/utils.cc +++ b/chrome_frame/utils.cc @@ -4,12 +4,12 @@ #include "chrome_frame/utils.h" +#include <atlsafe.h> +#include <atlsecurity.h> #include <htiframe.h> #include <mshtml.h> #include <shlobj.h> -#include <atlsecurity.h> - #include "base/file_util.h" #include "base/file_version_info.h" #include "base/lazy_instance.h" @@ -793,7 +793,7 @@ RendererType RendererTypeForUrl(const std::wstring& url) { HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, const wchar_t* headers, IBindCtx* bind_ctx, - const wchar_t* fragment) { + const wchar_t* fragment, IStream* post_data) { DCHECK(browser); DCHECK(moniker); DCHECK(bind_ctx); @@ -807,6 +807,46 @@ HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, if (FAILED(hr)) return hr; + // Always issue the download request in a new window to ensure that the + // currently loaded ChromeFrame document does not inadvarently see an unload + // request. This runs javascript unload handlers on the page which renders + // the page non functional. + VARIANT flags = { VT_I4 }; + V_I4(&flags) = navOpenInNewWindow | navNoHistory; + + // If the data to be downloaded was received in response to a post request + // then we need to reissue the post request. + base::win::ScopedVariant post_data_variant; + if (post_data) { + RewindStream(post_data); + + CComSafeArray<uint8> safe_array_post; + + STATSTG stat; + post_data->Stat(&stat, STATFLAG_NONAME); + + if (stat.cbSize.LowPart > 0) { + std::string data; + + HRESULT hr = E_FAIL; + while ((hr = ReadStream(post_data, 0xffff, &data)) == S_OK) { + safe_array_post.Add( + data.size(), + reinterpret_cast<unsigned char*>(const_cast<char*>(data.data()))); + data.clear(); + } + } else { + // If we get here it means that the navigation is being reissued for a + // POST request with no data. To ensure that the new window used as a + // target to handle the new navigation issues a POST request + // we need valid POST data. In this case we create a dummy 1 byte array. + // May not work as expected with some web sites. + DLOG(WARNING) << "Reissuing navigation with empty POST data. May not" + << " work as expected"; + safe_array_post.Create(1); + } + post_data_variant.Set(safe_array_post.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 @@ -854,14 +894,16 @@ HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, if (GetIEVersion() < IE_9) { hr = browser_priv2->NavigateWithBindCtx2( - uri_obj, NULL, NULL, NULL, headers_var.AsInput(), bind_ctx, - const_cast<wchar_t*>(fragment)); + uri_obj, &flags, NULL, post_data_variant.AsInput(), + headers_var.AsInput(), bind_ctx, + const_cast<wchar_t*>(fragment)); } else { IWebBrowserPriv2CommonIE9* browser_priv2_ie9 = reinterpret_cast<IWebBrowserPriv2CommonIE9*>(browser_priv2.get()); hr = browser_priv2_ie9->NavigateWithBindCtx2( - uri_obj, NULL, NULL, NULL, headers_var.AsInput(), bind_ctx, - const_cast<wchar_t*>(fragment), 0); + uri_obj, &flags, NULL, post_data_variant.AsInput(), + headers_var.AsInput(), bind_ctx, + const_cast<wchar_t*>(fragment), 0); } DLOG_IF(WARNING, FAILED(hr)) << base::StringPrintf(L"NavigateWithBindCtx2 0x%08X", hr); @@ -889,9 +931,9 @@ HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, } base::win::ScopedVariant var_url(UTF8ToWide(target_url.spec()).c_str()); - hr = browser_priv->NavigateWithBindCtx(var_url.AsInput(), NULL, NULL, - NULL, headers_var.AsInput(), - bind_ctx, + hr = browser_priv->NavigateWithBindCtx(var_url.AsInput(), &flags, NULL, + post_data_variant.AsInput(), + headers_var.AsInput(), bind_ctx, const_cast<wchar_t*>(fragment)); DLOG_IF(WARNING, FAILED(hr)) << base::StringPrintf(L"NavigateWithBindCtx 0x%08X", hr); |