diff options
-rw-r--r-- | chrome_frame/bho.cc | 2 | ||||
-rw-r--r-- | chrome_frame/chrome_active_document.cc | 32 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_activex_base.h | 11 | ||||
-rw-r--r-- | chrome_frame/test/navigation_test.cc | 77 | ||||
-rw-r--r-- | chrome_frame/urlmon_moniker.h | 30 |
5 files changed, 143 insertions, 9 deletions
diff --git a/chrome_frame/bho.cc b/chrome_frame/bho.cc index 5e74881..35623b3 100644 --- a/chrome_frame/bho.cc +++ b/chrome_frame/bho.cc @@ -132,6 +132,8 @@ STDMETHODIMP Bho::BeforeNavigate2(IDispatch* dispatch, VARIANT* url, if (is_top_level) { set_url(url->bstrVal); set_referrer(""); + set_post_data(post_data); + set_headers(headers); } return S_OK; } diff --git a/chrome_frame/chrome_active_document.cc b/chrome_frame/chrome_active_document.cc index 6000505..deee511 100644 --- a/chrome_frame/chrome_active_document.cc +++ b/chrome_frame/chrome_active_document.cc @@ -74,6 +74,7 @@ HRESULT ChromeActiveDocument::FinalConstruct() { // optimization to get Chrome active documents to load faster. ChromeActiveDocument* cached_document = g_active_doc_cache.Get(); if (cached_document && cached_document->IsValid()) { + SetResourceModule(); DCHECK(automation_client_.get() == NULL); automation_client_.swap(cached_document->automation_client_); DVLOG(1) << "Reusing automation client instance from " << cached_document; @@ -1070,6 +1071,37 @@ HRESULT ChromeActiveDocument::OnRefreshPage(const GUID* cmd_group_guid, 0x80000000 | OLECMDIDF_WINDOWSTATE_USERVISIBLE_VALID, NULL, NULL); } + NavigationManager* mgr = NavigationManager::GetThreadInstance(); + DLOG_IF(ERROR, !mgr) << "Couldn't get instance of NavigationManager"; + + // If ChromeFrame was activated on this page as a result of a document + // received in response to a top level post, then we ask the user for + // permission to repost and issue a navigation with the saved post data + // which reinitates the whole sequence, i.e. the server receives the top + // level post and chrome frame will be reactivated in response. + if (mgr && mgr->post_data().type() != VT_EMPTY) { + if (MessageBox( + SimpleResourceLoader::Get(IDS_HTTP_POST_WARNING).c_str(), + SimpleResourceLoader::Get(IDS_HTTP_POST_WARNING_TITLE).c_str(), + MB_YESNO | MB_ICONEXCLAMATION) == IDYES) { + base::win::ScopedComPtr<IWebBrowser2> web_browser2; + DoQueryService(SID_SWebBrowserApp, m_spClientSite, + web_browser2.Receive()); + DCHECK(web_browser2); + VARIANT empty = base::win::ScopedVariant::kEmptyVariant; + VARIANT flags = { VT_I4 }; + V_I4(&flags) = navNoHistory; + + return web_browser2->Navigate2(base::win::ScopedVariant(url_).AsInput(), + &flags, + &empty, + const_cast<VARIANT*>(&mgr->post_data()), + const_cast<VARIANT*>(&mgr->headers())); + } else { + return S_OK; + } + } + TabProxy* tab_proxy = GetTabProxy(); if (tab_proxy) { tab_proxy->ReloadAsync(); diff --git a/chrome_frame/chrome_frame_activex_base.h b/chrome_frame/chrome_frame_activex_base.h index 1dd2755..c7dd5cf 100644 --- a/chrome_frame/chrome_frame_activex_base.h +++ b/chrome_frame/chrome_frame_activex_base.h @@ -251,17 +251,12 @@ END_MSG_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() - virtual void SetResourceModule() { + void SetResourceModule() { DCHECK(NULL == prev_resource_instance_); SimpleResourceLoader* loader_instance = SimpleResourceLoader::instance(); DCHECK(loader_instance); HMODULE res_dll = loader_instance->GetResourceModuleHandle(); - prev_resource_instance_ = _AtlBaseModule.SetResourceInstance(res_dll); - } - - virtual void ClearResourceModule() { - _AtlBaseModule.SetResourceInstance(prev_resource_instance_); - prev_resource_instance_ = NULL; + _AtlBaseModule.SetResourceInstance(res_dll); } HRESULT FinalConstruct() { @@ -286,8 +281,6 @@ END_MSG_MAP() void FinalRelease() { Uninitialize(); - - ClearResourceModule(); } void ResetUrlRequestManager() { diff --git a/chrome_frame/test/navigation_test.cc b/chrome_frame/test/navigation_test.cc index 0918037..457793d 100644 --- a/chrome_frame/test/navigation_test.cc +++ b/chrome_frame/test/navigation_test.cc @@ -1026,5 +1026,82 @@ TEST_F(FullTabSeleniumTest, Core) { LaunchIENavigateAndLoop(url, kSeleniumTestTimeout); } +// See bug http://code.google.com/p/chromium/issues/detail?id=64901 +// This test does the following:- +// Navigates IE to a non ChromeFrame URL. +// Performs a top level form post in the document +// In response to the POST send over a html document containing a meta tag +// This would cause IE to switch to ChromeFrame. +// Refresh the page in ChromeFrame. +// This should bring up a confirmation dialog which we hit yes on. This should +// reissue the top level post request in response to which the html content +// containing the meta tag is sent again. +TEST_F(FullTabDownloadTest, TopLevelPostReissueFromChromeFramePage) { + chrome_frame_test::MockWindowObserver post_reissue_watcher; + post_reissue_watcher.WatchWindow("Confirm Form Resubmission", ""); + + EXPECT_CALL(server_mock_, Get(_, StrEq(L"/post_source.html"), _)) + .WillOnce(SendFast( + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html\r\n", + "<html>" + "<head>" + " <script type=\"text/javascript\">" + " function onLoad() {" + " document.getElementById(\"myform\").submit();}</script></head>" + " <body onload=\"setTimeout(onLoad, 2000);\">" + " <form id=\"myform\" action=\"post_target.html\" method=\"POST\">" + "</form></body></html>")); + + EXPECT_CALL(server_mock_, Post(_, StrEq(L"/post_target.html"), _)) + .Times(2) + .WillRepeatedly( + SendFast( + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html\r\n", + "<html>" + "<head><meta http-equiv=\"x-ua-compatible\" content=\"chrome=1\" />" + "</head>" + "<body> Target page in ChromeFrame </body>" + "</html>")); + + EXPECT_CALL(post_reissue_watcher, OnWindowOpen(_)) + .WillOnce(DelayAccDoDefaultAction( + AccObjectMatcher(L"Yes", L"push button"), + 1000)); + + EXPECT_CALL(post_reissue_watcher, OnWindowClose(_)); + + std::wstring src_url = server_mock_.Resolve(L"/post_source.html"); + std::wstring tgt_url = server_mock_.Resolve(L"/post_target.html"); + + EXPECT_CALL(ie_mock_, OnFileDownload(_, _)).Times(testing::AnyNumber()); + + EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_, + testing::Field(&VARIANT::bstrVal, + StrEq(src_url)), _, _, _, _, _)); + EXPECT_CALL(ie_mock_, OnNavigateComplete2(_, + testing::Field(&VARIANT::bstrVal, + StrEq(src_url)))); + EXPECT_CALL(ie_mock_, OnLoad(false, StrEq(src_url))); + + EXPECT_CALL(ie_mock_, OnLoad(true, StrEq(tgt_url))) + .Times(2); + + EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_, + testing::Field(&VARIANT::bstrVal, + StrEq(tgt_url)), _, _, _, _, _)) + .Times(2); + + EXPECT_CALL(ie_mock_, OnNavigateComplete2(_, + testing::Field(&VARIANT::bstrVal, + StrEq(tgt_url)))) + .Times(2) + .WillOnce(testing::DoAll(DelayRefresh(&ie_mock_, &loop_, 2000), + DelayCloseBrowserMock(&loop_, 4000, &ie_mock_))) + .WillOnce(testing::Return()); + + LaunchIENavigateAndLoop(src_url, kChromeFrameLongNavigationTimeoutInSeconds); +} } // namespace chrome_frame_test diff --git a/chrome_frame/urlmon_moniker.h b/chrome_frame/urlmon_moniker.h index a5b7fdf..dde70adb 100644 --- a/chrome_frame/urlmon_moniker.h +++ b/chrome_frame/urlmon_moniker.h @@ -13,6 +13,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/thread_local.h" +#include "base/win/scoped_variant.h" #include "googleurl/src/gurl.h" #include "chrome_frame/utils.h" @@ -122,9 +123,38 @@ class NavigationManager { // and need to switch over from mshtml to CF. virtual HRESULT NavigateToCurrentUrlInCF(IBrowserService* browser); + void set_post_data(VARIANT* post_data) { + post_data_.Reset(); + if (post_data) { + if (V_VT(post_data) == (VT_BYREF | VT_VARIANT)) { + post_data_.Set(*post_data->pvarVal); + } else { + NOTREACHED() << "unexpected type for post_data: " + << std::hex << post_data->vt; + } + } + } + + const base::win::ScopedVariant& post_data() const { + return post_data_; + } + + void set_headers(VARIANT* headers) { + headers_.Reset(); + if (headers) { + headers_ = *headers; + } + } + + const base::win::ScopedVariant& headers() const { + return headers_; + } + protected: std::string referrer_; std::wstring url_; + base::win::ScopedVariant post_data_; + base::win::ScopedVariant headers_; static base::LazyInstance<base::ThreadLocalPointer<NavigationManager> > thread_singleton_; |