Index: chrome_frame/chrome_frame_activex.cc |
diff --git a/chrome_frame/chrome_frame_activex.cc b/chrome_frame/chrome_frame_activex.cc |
deleted file mode 100644 |
index 037ab7119eb84d9319b1d01393d79be6cc584ac0..0000000000000000000000000000000000000000 |
--- a/chrome_frame/chrome_frame_activex.cc |
+++ /dev/null |
@@ -1,542 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome_frame/chrome_frame_activex.h" |
- |
-#include <wininet.h> |
- |
-#include <algorithm> |
-#include <map> |
- |
-#include "base/basictypes.h" |
-#include "base/command_line.h" |
-#include "base/debug/trace_event.h" |
-#include "base/logging.h" |
-#include "base/memory/singleton.h" |
-#include "base/path_service.h" |
-#include "base/strings/string_split.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/win/scoped_bstr.h" |
-#include "base/win/scoped_variant.h" |
-#include "chrome/common/automation_messages.h" |
-#include "chrome/common/chrome_constants.h" |
-#include "chrome/common/chrome_switches.h" |
-#include "chrome/test/automation/tab_proxy.h" |
-#include "chrome_frame/utils.h" |
-#include "url/gurl.h" |
- |
-namespace { |
- |
-// Class used to maintain a mapping from top-level windows to ChromeFrameActivex |
-// instances. |
-class TopLevelWindowMapping { |
- public: |
- typedef std::vector<HWND> WindowList; |
- |
- static TopLevelWindowMapping* GetInstance() { |
- return Singleton<TopLevelWindowMapping>::get(); |
- } |
- |
- // Add |cf_window| to the set of windows registered under |top_window|. |
- void AddMapping(HWND top_window, HWND cf_window) { |
- top_window_map_lock_.Lock(); |
- top_window_map_[top_window].push_back(cf_window); |
- top_window_map_lock_.Unlock(); |
- } |
- |
- // Return the set of Chrome-Frame instances under |window|. |
- WindowList GetInstances(HWND window) { |
- top_window_map_lock_.Lock(); |
- WindowList list = top_window_map_[window]; |
- top_window_map_lock_.Unlock(); |
- return list; |
- } |
- |
- private: |
- // Constructor is private as this class it to be used as a singleton. |
- // See static method instance(). |
- TopLevelWindowMapping() {} |
- |
- friend struct DefaultSingletonTraits<TopLevelWindowMapping>; |
- |
- typedef std::map<HWND, WindowList> TopWindowMap; |
- TopWindowMap top_window_map_; |
- |
- CComAutoCriticalSection top_window_map_lock_; |
- |
- DISALLOW_COPY_AND_ASSIGN(TopLevelWindowMapping); |
-}; |
- |
-} // unnamed namespace |
- |
-ChromeFrameActivex::ChromeFrameActivex() |
- : chrome_wndproc_hook_(NULL), |
- attaching_to_existing_cf_tab_(false) { |
- TRACE_EVENT_BEGIN_ETW("chromeframe.createactivex", this, ""); |
-} |
- |
-HRESULT ChromeFrameActivex::FinalConstruct() { |
- HRESULT hr = Base::FinalConstruct(); |
- if (FAILED(hr)) |
- return hr; |
- |
- // No need to call FireOnChanged at this point since nobody will be listening. |
- ready_state_ = READYSTATE_LOADING; |
- return S_OK; |
-} |
- |
-ChromeFrameActivex::~ChromeFrameActivex() { |
- // We expect these to be released during a call to SetClientSite(NULL). |
- DCHECK_EQ(0u, onmessage_.size()); |
- DCHECK_EQ(0u, onloaderror_.size()); |
- DCHECK_EQ(0u, onload_.size()); |
- DCHECK_EQ(0u, onreadystatechanged_.size()); |
- DCHECK_EQ(0u, onextensionready_.size()); |
- |
- if (chrome_wndproc_hook_) { |
- BOOL unhook_success = ::UnhookWindowsHookEx(chrome_wndproc_hook_); |
- DCHECK(unhook_success); |
- } |
- |
- // ChromeFramePlugin::Uninitialize() |
- Base::Uninitialize(); |
- |
- TRACE_EVENT_END_ETW("chromeframe.createactivex", this, ""); |
-} |
- |
-LRESULT ChromeFrameActivex::OnCreate(UINT message, WPARAM wparam, LPARAM lparam, |
- BOOL& handled) { |
- Base::OnCreate(message, wparam, lparam, handled); |
- // Install the notification hook on the top-level window, so that we can |
- // be notified on move events. Note that the return value is not checked. |
- // This hook is installed here, as opposed to during IOleObject_SetClientSite |
- // because m_hWnd has not yet been assigned during the SetSite call. |
- InstallTopLevelHook(m_spClientSite); |
- return 0; |
-} |
- |
-HRESULT ChromeFrameActivex::GetContainingDocument(IHTMLDocument2** doc) { |
- base::win::ScopedComPtr<IOleContainer> container; |
- HRESULT hr = m_spClientSite->GetContainer(container.Receive()); |
- if (container) |
- hr = container.QueryInterface(doc); |
- return hr; |
-} |
- |
-HRESULT ChromeFrameActivex::GetDocumentWindow(IHTMLWindow2** window) { |
- base::win::ScopedComPtr<IHTMLDocument2> document; |
- HRESULT hr = GetContainingDocument(document.Receive()); |
- if (document) |
- hr = document->get_parentWindow(window); |
- return hr; |
-} |
- |
-void ChromeFrameActivex::OnLoadFailed(int error_code, const std::string& url) { |
- base::win::ScopedComPtr<IDispatch> event; |
- if (SUCCEEDED(CreateDomEvent("event", url, "", event.Receive()))) |
- Fire_onloaderror(event); |
- |
- FireEvent(onloaderror_, url); |
- Base::OnLoadFailed(error_code, url); |
-} |
- |
-bool ChromeFrameActivex::ShouldShowVersionMismatchDialog( |
- bool is_privileged, |
- IOleClientSite* client_site) { |
- if (!is_privileged) { |
- return true; |
- } |
- |
- if (client_site) { |
- base::win::ScopedComPtr<IChromeFramePrivileged> service; |
- HRESULT hr = DoQueryService(SID_ChromeFramePrivileged, |
- client_site, |
- service.Receive()); |
- if (SUCCEEDED(hr) && service) { |
- return (S_FALSE != service->ShouldShowVersionMismatchDialog()); |
- } |
- } |
- |
- NOTREACHED(); |
- return true; |
-} |
- |
-void ChromeFrameActivex::OnAutomationServerLaunchFailed( |
- AutomationLaunchResult reason, const std::string& server_version) { |
- Base::OnAutomationServerLaunchFailed(reason, server_version); |
- |
- if (reason == AUTOMATION_VERSION_MISMATCH && |
- ShouldShowVersionMismatchDialog(is_privileged(), m_spClientSite)) { |
- UMA_HISTOGRAM_COUNTS("ChromeFrame.VersionMismatchDisplayed", 1); |
- DisplayVersionMismatchWarning(m_hWnd, server_version); |
- } |
-} |
- |
-void ChromeFrameActivex::OnChannelError() { |
- Fire_onchannelerror(); |
-} |
- |
-HRESULT ChromeFrameActivex::OnDraw(ATL_DRAWINFO& draw_info) { // NOLINT |
- HRESULT hr = S_OK; |
- int dc_type = ::GetObjectType(draw_info.hicTargetDev); |
- if (dc_type == OBJ_ENHMETADC) { |
- RECT print_bounds = {0}; |
- print_bounds.left = draw_info.prcBounds->left; |
- print_bounds.right = draw_info.prcBounds->right; |
- print_bounds.top = draw_info.prcBounds->top; |
- print_bounds.bottom = draw_info.prcBounds->bottom; |
- |
- automation_client_->Print(draw_info.hdcDraw, print_bounds); |
- } else { |
- hr = Base::OnDraw(draw_info); |
- } |
- |
- return hr; |
-} |
- |
-STDMETHODIMP ChromeFrameActivex::Load(IPropertyBag* bag, IErrorLog* error_log) { |
- DCHECK(bag); |
- |
- const wchar_t* event_props[] = { |
- (L"onload"), |
- (L"onloaderror"), |
- (L"onmessage"), |
- (L"onreadystatechanged"), |
- }; |
- |
- base::win::ScopedComPtr<IHTMLObjectElement> obj_element; |
- GetObjectElement(obj_element.Receive()); |
- |
- base::win::ScopedBstr object_id; |
- GetObjectScriptId(obj_element, object_id.Receive()); |
- |
- base::win::ScopedComPtr<IHTMLElement2> element; |
- element.QueryFrom(obj_element); |
- HRESULT hr = S_OK; |
- |
- for (int i = 0; SUCCEEDED(hr) && i < arraysize(event_props); ++i) { |
- base::win::ScopedBstr prop(event_props[i]); |
- base::win::ScopedVariant value; |
- if (SUCCEEDED(bag->Read(prop, value.Receive(), error_log))) { |
- if (value.type() != VT_BSTR || |
- FAILED(hr = CreateScriptBlockForEvent(element, object_id, |
- V_BSTR(&value), prop))) { |
- DLOG(ERROR) << "Failed to create script block for " << prop |
- << base::StringPrintf(L"hr=0x%08X, vt=%i", hr, |
- value.type()); |
- } else { |
- DVLOG(1) << "script block created for event " << prop |
- << base::StringPrintf(" (0x%08X)", hr) << " connections: " << |
- ProxyDIChromeFrameEvents<ChromeFrameActivex>::m_vec.GetSize(); |
- } |
- } else { |
- DVLOG(1) << "event property " << prop << " not in property bag"; |
- } |
- } |
- |
- base::win::ScopedVariant src; |
- if (SUCCEEDED(bag->Read(base::win::ScopedBstr(L"src"), src.Receive(), |
- error_log))) { |
- if (src.type() == VT_BSTR) { |
- hr = put_src(V_BSTR(&src)); |
- DCHECK(hr != E_UNEXPECTED); |
- } |
- } |
- |
- base::win::ScopedVariant use_chrome_network; |
- if (SUCCEEDED(bag->Read(base::win::ScopedBstr(L"useChromeNetwork"), |
- use_chrome_network.Receive(), error_log))) { |
- VariantChangeType(use_chrome_network.AsInput(), |
- use_chrome_network.AsInput(), |
- 0, VT_BOOL); |
- if (use_chrome_network.type() == VT_BOOL) { |
- hr = put_useChromeNetwork(V_BOOL(&use_chrome_network)); |
- DCHECK(hr != E_UNEXPECTED); |
- } |
- } |
- |
- DLOG_IF(ERROR, FAILED(hr)) |
- << base::StringPrintf("Failed to load property bag: 0x%08X", hr); |
- |
- return hr; |
-} |
- |
-const wchar_t g_activex_insecure_content_error[] = { |
- L"data:text/html,<html><body><b>ChromeFrame Security Error<br><br>" |
- L"Cannot navigate to HTTP url when document URL is HTTPS</body></html>"}; |
- |
-STDMETHODIMP ChromeFrameActivex::put_src(BSTR src) { |
- GURL document_url(GetDocumentUrl()); |
- if (document_url.SchemeIsSecure()) { |
- GURL source_url(src); |
- if (!source_url.SchemeIsSecure()) { |
- Base::put_src(base::win::ScopedBstr(g_activex_insecure_content_error)); |
- return E_ACCESSDENIED; |
- } |
- } |
- HRESULT hr = S_OK; |
- // If we are connecting to an existing ExternalTabContainer instance in |
- // Chrome then we should wait for Chrome to initiate the navigation. |
- if (!attaching_to_existing_cf_tab_) { |
- hr = Base::put_src(src); |
- } else { |
- url_.Reset(::SysAllocString(src)); |
- attaching_to_existing_cf_tab_ = false; |
- } |
- return S_OK; |
-} |
- |
-HRESULT ChromeFrameActivex::IOleObject_SetClientSite( |
- IOleClientSite* client_site) { |
- HRESULT hr = Base::IOleObject_SetClientSite(client_site); |
- if (FAILED(hr) || !client_site) { |
- EventHandlers* handlers[] = { |
- &onmessage_, |
- &onloaderror_, |
- &onload_, |
- &onreadystatechanged_, |
- &onextensionready_, |
- }; |
- |
- for (int i = 0; i < arraysize(handlers); ++i) |
- handlers[i]->clear(); |
- |
- // Drop privileged mode on uninitialization. |
- set_is_privileged(false); |
- } else { |
- base::win::ScopedComPtr<IHTMLDocument2> document; |
- GetContainingDocument(document.Receive()); |
- if (document) { |
- base::win::ScopedBstr url; |
- if (SUCCEEDED(document->get_URL(url.Receive()))) |
- base::WideToUTF8(url, url.Length(), &document_url_); |
- } |
- |
- // Probe to see whether the host implements the privileged service. |
- base::win::ScopedComPtr<IChromeFramePrivileged> service; |
- HRESULT service_hr = DoQueryService(SID_ChromeFramePrivileged, |
- m_spClientSite, |
- service.Receive()); |
- if (SUCCEEDED(service_hr) && service) { |
- // Does the host want privileged mode? |
- boolean wants_privileged = false; |
- service_hr = service->GetWantsPrivileged(&wants_privileged); |
- |
- if (SUCCEEDED(service_hr) && wants_privileged) |
- set_is_privileged(true); |
- |
- url_fetcher_->set_privileged_mode(is_privileged()); |
- } |
- |
- std::wstring profile_name(GetHostProcessName(false)); |
- if (is_privileged()) { |
- base::win::ScopedBstr profile_name_arg; |
- service_hr = service->GetChromeProfileName(profile_name_arg.Receive()); |
- if (S_OK == service_hr && profile_name_arg) |
- profile_name.assign(profile_name_arg, profile_name_arg.Length()); |
- } |
- |
- std::string utf8_url; |
- if (url_.Length()) { |
- base::WideToUTF8(url_, url_.Length(), &utf8_url); |
- } |
- |
- InitializeAutomationSettings(); |
- |
- |
- url_fetcher_->set_frame_busting(!is_privileged()); |
- automation_client_->SetUrlFetcher(url_fetcher_.get()); |
- if (!InitializeAutomation(profile_name, IsIEInPrivate(), true, |
- GURL(utf8_url), GURL(), false)) { |
- DLOG(ERROR) << "Failed to navigate to url:" << utf8_url; |
- return E_FAIL; |
- } |
- |
- // Log a metric that Chrome Frame is being used in Widget mode |
- UMA_LAUNCH_TYPE_COUNT(RENDERER_TYPE_CHROME_WIDGET); |
- } |
- |
- return hr; |
-} |
- |
-HRESULT ChromeFrameActivex::GetObjectScriptId(IHTMLObjectElement* object_elem, |
- BSTR* id) { |
- DCHECK(object_elem != NULL); |
- DCHECK(id != NULL); |
- |
- HRESULT hr = E_FAIL; |
- if (object_elem) { |
- base::win::ScopedComPtr<IHTMLElement> elem; |
- hr = elem.QueryFrom(object_elem); |
- if (elem) { |
- hr = elem->get_id(id); |
- } |
- } |
- |
- return hr; |
-} |
- |
-HRESULT ChromeFrameActivex::GetObjectElement(IHTMLObjectElement** element) { |
- DCHECK(m_spClientSite); |
- if (!m_spClientSite) |
- return E_UNEXPECTED; |
- |
- base::win::ScopedComPtr<IOleControlSite> site; |
- HRESULT hr = site.QueryFrom(m_spClientSite); |
- if (site) { |
- base::win::ScopedComPtr<IDispatch> disp; |
- hr = site->GetExtendedControl(disp.Receive()); |
- if (disp) { |
- hr = disp.QueryInterface(element); |
- } else { |
- DCHECK(FAILED(hr)); |
- } |
- } |
- |
- return hr; |
-} |
- |
-HRESULT ChromeFrameActivex::CreateScriptBlockForEvent( |
- IHTMLElement2* insert_after, BSTR instance_id, BSTR script, |
- BSTR event_name) { |
- DCHECK(insert_after); |
- DCHECK_GT(::SysStringLen(event_name), 0UL); // should always have this |
- |
- // This might be 0 if not specified in the HTML document. |
- if (!::SysStringLen(instance_id)) { |
- // TODO(tommi): Should we give ourselves an ID if this happens? |
- NOTREACHED() << "Need to handle this"; |
- return E_INVALIDARG; |
- } |
- |
- base::win::ScopedComPtr<IHTMLDocument2> document; |
- HRESULT hr = GetContainingDocument(document.Receive()); |
- if (SUCCEEDED(hr)) { |
- base::win::ScopedComPtr<IHTMLElement> element, new_element; |
- document->createElement(base::win::ScopedBstr(L"script"), |
- element.Receive()); |
- if (element) { |
- base::win::ScopedComPtr<IHTMLScriptElement> script_element; |
- if (SUCCEEDED(hr = script_element.QueryFrom(element))) { |
- script_element->put_htmlFor(instance_id); |
- script_element->put_event(event_name); |
- script_element->put_text(script); |
- |
- hr = insert_after->insertAdjacentElement( |
- base::win::ScopedBstr(L"afterEnd"), |
- element, |
- new_element.Receive()); |
- } |
- } |
- } |
- |
- return hr; |
-} |
- |
-void ChromeFrameActivex::FireEvent(const EventHandlers& handlers, |
- const std::string& arg) { |
- if (handlers.size()) { |
- base::win::ScopedComPtr<IDispatch> event; |
- if (SUCCEEDED(CreateDomEvent("event", arg, "", event.Receive()))) { |
- FireEvent(handlers, event); |
- } |
- } |
-} |
- |
-void ChromeFrameActivex::FireEvent(const EventHandlers& handlers, |
- IDispatch* event) { |
- DCHECK(event != NULL); |
- VARIANT arg = { VT_DISPATCH }; |
- arg.pdispVal = event; |
- DISPPARAMS params = { &arg, NULL, 1, 0 }; |
- for (EventHandlers::const_iterator it = handlers.begin(); |
- it != handlers.end(); |
- ++it) { |
- HRESULT hr = (*it)->Invoke(DISPID_VALUE, IID_NULL, LOCALE_USER_DEFAULT, |
- DISPATCH_METHOD, ¶ms, NULL, NULL, NULL); |
- // 0x80020101 == SCRIPT_E_REPORTED. |
- // When the script we're invoking has an error, we get this error back. |
- DLOG_IF(ERROR, FAILED(hr) && hr != 0x80020101) |
- << base::StringPrintf(L"Failed to invoke script: 0x%08X", hr); |
- } |
-} |
- |
-void ChromeFrameActivex::FireEvent(const EventHandlers& handlers, |
- IDispatch* event, BSTR target) { |
- DCHECK(event != NULL); |
- // Arguments in reverse order to event handler function declaration, |
- // because that's what DISPPARAMS requires. |
- VARIANT args[2] = { { VT_BSTR }, { VT_DISPATCH }, }; |
- args[0].bstrVal = target; |
- args[1].pdispVal = event; |
- DISPPARAMS params = { args, NULL, arraysize(args), 0 }; |
- for (EventHandlers::const_iterator it = handlers.begin(); |
- it != handlers.end(); |
- ++it) { |
- HRESULT hr = (*it)->Invoke(DISPID_VALUE, IID_NULL, LOCALE_USER_DEFAULT, |
- DISPATCH_METHOD, ¶ms, NULL, NULL, NULL); |
- // 0x80020101 == SCRIPT_E_REPORTED. |
- // When the script we're invoking has an error, we get this error back. |
- DLOG_IF(ERROR, FAILED(hr) && hr != 0x80020101) |
- << base::StringPrintf(L"Failed to invoke script: 0x%08X", hr); |
- } |
-} |
- |
-HRESULT ChromeFrameActivex::InstallTopLevelHook(IOleClientSite* client_site) { |
- return E_FAIL; |
-} |
- |
-HRESULT ChromeFrameActivex::registerBhoIfNeeded() { |
- if (!m_spUnkSite) { |
- NOTREACHED() << "Invalid client site"; |
- return E_FAIL; |
- } |
- |
- if (NavigationManager::GetThreadInstance() != NULL) { |
- DVLOG(1) << "BHO already loaded"; |
- return S_OK; |
- } |
- |
- base::win::ScopedComPtr<IWebBrowser2> web_browser2; |
- HRESULT hr = DoQueryService(SID_SWebBrowserApp, m_spUnkSite, |
- web_browser2.Receive()); |
- if (FAILED(hr) || web_browser2.get() == NULL) { |
- DLOG(WARNING) << "Failed to get IWebBrowser2 from client site. Error:" |
- << base::StringPrintf(" 0x%08X", hr); |
- return hr; |
- } |
- |
- wchar_t bho_class_id_as_string[MAX_PATH] = {0}; |
- StringFromGUID2(CLSID_ChromeFrameBHO, bho_class_id_as_string, |
- arraysize(bho_class_id_as_string)); |
- |
- base::win::ScopedComPtr<IObjectWithSite> bho; |
- hr = bho.CreateInstance(CLSID_ChromeFrameBHO, NULL, CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- NOTREACHED() << "Failed to register ChromeFrame BHO. Error:" |
- << base::StringPrintf(" 0x%08X", hr); |
- return hr; |
- } |
- |
- hr = UrlMkSetSessionOption(URLMON_OPTION_USERAGENT_REFRESH, NULL, 0, 0); |
- if (FAILED(hr)) { |
- DLOG(ERROR) << "Failed to refresh user agent string from registry. " |
- << "UrlMkSetSessionOption returned " |
- << base::StringPrintf("0x%08x", hr); |
- return hr; |
- } |
- |
- hr = bho->SetSite(web_browser2); |
- if (FAILED(hr)) { |
- NOTREACHED() << "ChromeFrame BHO SetSite failed. Error:" |
- << base::StringPrintf(" 0x%08X", hr); |
- return hr; |
- } |
- |
- web_browser2->PutProperty(base::win::ScopedBstr(bho_class_id_as_string), |
- base::win::ScopedVariant(bho)); |
- return S_OK; |
-} |