diff options
Diffstat (limited to 'chrome_frame/test/chrome_frame_test_utils.cc')
-rw-r--r-- | chrome_frame/test/chrome_frame_test_utils.cc | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/chrome_frame/test/chrome_frame_test_utils.cc b/chrome_frame/test/chrome_frame_test_utils.cc index 8777651..9f2a6de 100644 --- a/chrome_frame/test/chrome_frame_test_utils.cc +++ b/chrome_frame/test/chrome_frame_test_utils.cc @@ -16,6 +16,7 @@ #include "base/string_util.h" #include "base/win_util.h" #include "chrome/common/chrome_switches.h" +#include "chrome_frame/utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace chrome_frame_test { @@ -623,4 +624,242 @@ bool LowIntegrityToken::IsImpersonated() { return false; } +HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser) { + if (!web_browser) + return E_INVALIDARG; + + HRESULT hr = S_OK; + DWORD cocreate_flags = CLSCTX_LOCAL_SERVER; + chrome_frame_test::LowIntegrityToken token; + // Vista has a bug which manifests itself when a medium integrity process + // launches a COM server like IE which runs in protected mode due to UAC. + // This causes the IWebBrowser2 interface which is returned to be useless, + // i.e it does not receive any events, etc. Our workaround for this is + // to impersonate a low integrity token and then launch IE. + if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) { + // Create medium integrity browser that will launch IE broker. + ScopedComPtr<IWebBrowser2> medium_integrity_browser; + hr = medium_integrity_browser.CreateInstance(CLSID_InternetExplorer, NULL, + CLSCTX_LOCAL_SERVER); + if (FAILED(hr)) + return hr; + medium_integrity_browser->Quit(); + // Broker remains alive. + if (!token.Impersonate()) { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + cocreate_flags |= CLSCTX_ENABLE_CLOAKING; + } + + hr = ::CoCreateInstance(CLSID_InternetExplorer, NULL, + cocreate_flags, IID_IWebBrowser2, + reinterpret_cast<void**>(web_browser)); + // ~LowIntegrityToken() will switch integrity back to medium. + return hr; +} + +_ATL_FUNC_INFO WebBrowserEventSink::kNavigateErrorInfo = { + CC_STDCALL, VT_EMPTY, 5, { + VT_DISPATCH, + VT_VARIANT | VT_BYREF, + VT_VARIANT | VT_BYREF, + VT_VARIANT | VT_BYREF, + VT_BOOL | VT_BYREF, + } +}; + +_ATL_FUNC_INFO WebBrowserEventSink::kNavigateComplete2Info = { + CC_STDCALL, VT_EMPTY, 2, { + VT_DISPATCH, + VT_VARIANT | VT_BYREF + } +}; + +_ATL_FUNC_INFO WebBrowserEventSink::kBeforeNavigate2Info = { + CC_STDCALL, VT_EMPTY, 7, { + VT_DISPATCH, + VT_VARIANT | VT_BYREF, + VT_VARIANT | VT_BYREF, + VT_VARIANT | VT_BYREF, + VT_VARIANT | VT_BYREF, + VT_VARIANT | VT_BYREF, + VT_BOOL | VT_BYREF + } +}; + +_ATL_FUNC_INFO WebBrowserEventSink::kNewWindow3Info = { + CC_STDCALL, VT_EMPTY, 5, { + VT_DISPATCH | VT_BYREF, + VT_BOOL | VT_BYREF, + VT_UINT, + VT_BSTR, + VT_BSTR + } +}; + +_ATL_FUNC_INFO WebBrowserEventSink::kVoidMethodInfo = { + CC_STDCALL, VT_EMPTY, 0, {NULL}}; + +_ATL_FUNC_INFO WebBrowserEventSink::kDocumentCompleteInfo = { + CC_STDCALL, VT_EMPTY, 2, { + VT_DISPATCH, + VT_VARIANT | VT_BYREF + } +}; + +// WebBrowserEventSink member defines +void WebBrowserEventSink::Uninitialize() { + DisconnectFromChromeFrame(); + if (web_browser2_.get()) { + DispEventUnadvise(web_browser2_); + web_browser2_->Quit(); + web_browser2_.Release(); + } +} + +STDMETHODIMP WebBrowserEventSink::OnBeforeNavigate2Internal( + IDispatch* dispatch, VARIANT* url, VARIANT* flags, + VARIANT* target_frame_name, VARIANT* post_data, VARIANT* headers, + VARIANT_BOOL* cancel) { + DLOG(INFO) << __FUNCTION__; + // Reset any existing reference to chrome frame since this is a new + // navigation. + chrome_frame_ = NULL; + return OnBeforeNavigate2(dispatch, url, flags, target_frame_name, + post_data, headers, cancel); +} + +STDMETHODIMP_(void) WebBrowserEventSink::OnNavigateComplete2Internal( + IDispatch* dispatch, VARIANT* url) { + DLOG(INFO) << __FUNCTION__; + ConnectToChromeFrame(); + OnNavigateComplete2(dispatch, url); +} + +STDMETHODIMP_(void) WebBrowserEventSink::OnDocumentCompleteInternal( + IDispatch* dispatch, VARIANT* url) { + DLOG(INFO) << __FUNCTION__; + OnDocumentComplete(dispatch, url); +} + +HRESULT WebBrowserEventSink::OnLoadInternal(const VARIANT* param) { + DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal; + OnLoad(param->bstrVal); + return S_OK; +} + +HRESULT WebBrowserEventSink::OnLoadErrorInternal(const VARIANT* param) { + DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal; + OnLoadError(param->bstrVal); + return S_OK; +} + +HRESULT WebBrowserEventSink::OnMessageInternal(const VARIANT* param) { + DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal; + OnMessage(param->bstrVal); + return S_OK; +} + +HRESULT WebBrowserEventSink::LaunchIEAndNavigate( + const std::wstring& navigate_url) { + HRESULT hr = LaunchIEAsComServer(web_browser2_.Receive()); + EXPECT_EQ(S_OK, hr); + if (hr == S_OK) { + web_browser2_->put_Visible(VARIANT_TRUE); + hr = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2); + EXPECT_TRUE(hr == S_OK); + hr = Navigate(navigate_url); + } + return hr; +} + +HRESULT WebBrowserEventSink::Navigate(const std::wstring& navigate_url) { + VARIANT empty = ScopedVariant::kEmptyVariant; + ScopedVariant url; + url.Set(navigate_url.c_str()); + + HRESULT hr = S_OK; + hr = web_browser2_->Navigate2(url.AsInput(), &empty, &empty, &empty, &empty); + EXPECT_TRUE(hr == S_OK); + return hr; +} + +void WebBrowserEventSink::SetFocusToChrome() { + chrome_frame_test::SetKeyboardFocusToWindow( + GetAttachedChromeRendererWindow(), 1, 1); +} + +void WebBrowserEventSink::SendInputToChrome( + const std::string& input_string) { + chrome_frame_test::SendInputToWindow( + GetAttachedChromeRendererWindow(), input_string); +} + +void WebBrowserEventSink::ConnectToChromeFrame() { + DCHECK(web_browser2_); + ScopedComPtr<IShellBrowser> shell_browser; + DoQueryService(SID_STopLevelBrowser, web_browser2_, + shell_browser.Receive()); + + if (shell_browser) { + ScopedComPtr<IShellView> shell_view; + shell_browser->QueryActiveShellView(shell_view.Receive()); + if (shell_view) { + shell_view->GetItemObject(SVGIO_BACKGROUND, __uuidof(IChromeFrame), + reinterpret_cast<void**>(chrome_frame_.Receive())); + } + + if (chrome_frame_) { + ScopedVariant onmessage(onmessage_.ToDispatch()); + ScopedVariant onloaderror(onloaderror_.ToDispatch()); + ScopedVariant onload(onload_.ToDispatch()); + EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onmessage(onmessage)); + EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onloaderror(onloaderror)); + EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onload(onload)); + } + } +} + +void WebBrowserEventSink::DisconnectFromChromeFrame() { + if (chrome_frame_) { + ScopedVariant dummy(static_cast<IDispatch*>(NULL)); + chrome_frame_->put_onmessage(dummy); + chrome_frame_->put_onload(dummy); + chrome_frame_->put_onloaderror(dummy); + chrome_frame_.Release(); + } +} + +HWND WebBrowserEventSink::GetAttachedChromeRendererWindow() { + DCHECK(chrome_frame_); + HWND renderer_window = NULL; + ScopedComPtr<IOleWindow> ole_window; + ole_window.QueryFrom(chrome_frame_); + EXPECT_TRUE(ole_window.get()); + + if (ole_window) { + HWND activex_window = NULL; + ole_window->GetWindow(&activex_window); + EXPECT_TRUE(IsWindow(activex_window)); + + // chrome tab window is the first (and the only) child of activex + HWND chrome_tab_window = GetWindow(activex_window, GW_CHILD); + EXPECT_TRUE(IsWindow(chrome_tab_window)); + renderer_window = GetWindow(chrome_tab_window, GW_CHILD); + } + + DCHECK(IsWindow(renderer_window)); + return renderer_window; +} + +HRESULT WebBrowserEventSink::SetWebBrowser(IWebBrowser2* web_browser2) { + DCHECK(web_browser2_.get() == NULL); + web_browser2_ = web_browser2; + web_browser2_->put_Visible(VARIANT_TRUE); + HRESULT hr = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2); + return hr; +} + } // namespace chrome_frame_test |