diff options
author | twiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-16 02:24:18 +0000 |
---|---|---|
committer | twiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-16 02:24:18 +0000 |
commit | 2b19e2feeac2a01b2068595bd2913a194a6527e5 (patch) | |
tree | fff83de7ba198462e1d00b96911685418dd130bd /chrome_frame | |
parent | 00a3768102287ae6f8ff5e28347a920759d3374d (diff) | |
download | chromium_src-2b19e2feeac2a01b2068595bd2913a194a6527e5.zip chromium_src-2b19e2feeac2a01b2068595bd2913a194a6527e5.tar.gz chromium_src-2b19e2feeac2a01b2068595bd2913a194a6527e5.tar.bz2 |
Clone of issue 600130. (http://codereview.chromium.org/600130)
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/593111
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39077 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r-- | chrome_frame/chrome_frame_activex.cc | 128 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_activex.h | 12 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_automation.cc | 4 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_automation.h | 2 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_delegate.h | 6 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_plugin.h | 4 |
6 files changed, 154 insertions, 2 deletions
diff --git a/chrome_frame/chrome_frame_activex.cc b/chrome_frame/chrome_frame_activex.cc index 295ceaa..15ae065 100644 --- a/chrome_frame/chrome_frame_activex.cc +++ b/chrome_frame/chrome_frame_activex.cc @@ -7,6 +7,7 @@ #include <wininet.h> #include <algorithm> +#include <map> #include "base/basictypes.h" #include "base/command_line.h" @@ -15,6 +16,7 @@ #include "base/path_service.h" #include "base/process_util.h" #include "base/scoped_bstr_win.h" +#include "base/singleton.h" #include "base/string_util.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" @@ -22,7 +24,94 @@ #include "googleurl/src/gurl.h" #include "chrome_frame/utils.h" -ChromeFrameActivex::ChromeFrameActivex() { +namespace { + +// Class used to maintain a mapping from top-level windows to ChromeFrameActivex +// instances. +class TopLevelWindowMapping { + public: + typedef std::vector<HWND> WindowList; + + static TopLevelWindowMapping* instance() { + 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); +}; + +// Message pump hook function that monitors for WM_MOVE and WM_MOVING +// messages on a top-level window, and passes notification to the appropriate +// Chrome-Frame instances. +LRESULT CALLBACK TopWindowProc(int code, WPARAM wparam, LPARAM lparam) { + CWPSTRUCT *info = reinterpret_cast<CWPSTRUCT*>(lparam); + const UINT &message = info->message; + const HWND &message_hwnd = info->hwnd; + + switch (message) { + case WM_MOVE: + case WM_MOVING: { + TopLevelWindowMapping::WindowList cf_instances = + TopLevelWindowMapping::instance()->GetInstances(message_hwnd); + TopLevelWindowMapping::WindowList::iterator + iter(cf_instances.begin()), end(cf_instances.end()); + for (;iter != end; ++iter) { + PostMessage(*iter, WM_HOST_MOVED_NOTIFICATION, NULL, NULL); + } + break; + } + default: + break; + } + + return CallNextHookEx(0, code, wparam, lparam); +} + +HHOOK InstallLocalWindowHook(HWND window) { + if (!window) + return NULL; + + DWORD proc_thread = ::GetWindowThreadProcessId(window, NULL); + if (!proc_thread) + return NULL; + + // Note that this hook is installed as a LOCAL hook. + return ::SetWindowsHookEx(WH_CALLWNDPROC, + TopWindowProc, + NULL, + proc_thread); +} + +} // unnamed namespace + +ChromeFrameActivex::ChromeFrameActivex() + : chrome_wndproc_hook_(NULL) { } HRESULT ChromeFrameActivex::FinalConstruct() { @@ -43,6 +132,11 @@ ChromeFrameActivex::~ChromeFrameActivex() { DCHECK(onreadystatechanged_.size() == 0); DCHECK(onextensionready_.size() == 0); + if (chrome_wndproc_hook_) { + BOOL unhook_success = ::UnhookWindowsHookEx(chrome_wndproc_hook_); + DCHECK(unhook_success); + } + // ChromeFramePlugin::Uninitialize() Base::Uninitialize(); } @@ -50,6 +144,17 @@ ChromeFrameActivex::~ChromeFrameActivex() { 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; +} + +LRESULT ChromeFrameActivex::OnHostMoved(UINT message, WPARAM wparam, + LPARAM lparam, BOOL& handled) { + Base::OnHostMoved(); return 0; } @@ -449,3 +554,24 @@ void ChromeFrameActivex::FireEvent(const EventHandlers& handlers, << StringPrintf(L"Failed to invoke script: 0x%08X", hr); } } + +HRESULT ChromeFrameActivex::InstallTopLevelHook(IOleClientSite* client_site) { + // Get the parent window of the site, and install our hook on the topmost + // window of the parent. + ScopedComPtr<IOleWindow> ole_window; + HRESULT hr = ole_window.QueryFrom(client_site); + if (FAILED(hr)) + return hr; + + HWND parent_wnd; + hr = ole_window->GetWindow(&parent_wnd); + if (FAILED(hr)) + return hr; + + HWND top_window = ::GetAncestor(parent_wnd, GA_ROOT); + chrome_wndproc_hook_ = InstallLocalWindowHook(top_window); + if (chrome_wndproc_hook_) + TopLevelWindowMapping::instance()->AddMapping(top_window, m_hWnd); + + return chrome_wndproc_hook_ ? S_OK : E_FAIL; +} diff --git a/chrome_frame/chrome_frame_activex.h b/chrome_frame/chrome_frame_activex.h index 31c85b1..1d4f1e9 100644 --- a/chrome_frame/chrome_frame_activex.h +++ b/chrome_frame/chrome_frame_activex.h @@ -22,6 +22,8 @@ // Include without path to make GYP build see it. #include "chrome_tab.h" // NOLINT +#define WM_HOST_MOVED_NOTIFICATION (WM_APP + 1) + // ChromeFrameActivex: Implementation of the ActiveX control that is // responsible for hosting a chrome frame, i.e. an iframe like widget which // hosts the the chrome window. This object delegates to Chrome.exe @@ -48,6 +50,7 @@ END_COM_MAP() BEGIN_MSG_MAP(ChromeFrameActivex) MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_HOST_MOVED_NOTIFICATION, OnHostMoved) CHAIN_MSG_MAP(Base) END_MSG_MAP() @@ -74,7 +77,7 @@ END_MSG_MAP() // Used to setup the document_url_ member needed for completing navigation. // Create external tab (possibly in incognito mode). - HRESULT IOleObject_SetClientSite(IOleClientSite *pClientSite); + HRESULT IOleObject_SetClientSite(IOleClientSite* client_site); // Overridden to perform security checks. STDMETHOD(put_src)(BSTR src); @@ -95,6 +98,8 @@ END_MSG_MAP() private: LRESULT OnCreate(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled); // NO_LINT + LRESULT OnHostMoved(UINT message, WPARAM wparam, LPARAM lparam, + BOOL& handled); // NO_LINT HRESULT GetContainingDocument(IHTMLDocument2** doc); HRESULT GetDocumentWindow(IHTMLWindow2** window); @@ -123,6 +128,11 @@ END_MSG_MAP() void FireEvent(const EventHandlers& handlers, IDispatch* event, BSTR target); + // Installs a hook on the top-level window hosting the control. + HRESULT InstallTopLevelHook(IOleClientSite* client_site); + + // A hook attached to the top-level window containing the ActiveX control. + HHOOK chrome_wndproc_hook_; }; #endif // CHROME_FRAME_CHROME_FRAME_ACTIVEX_H_ diff --git a/chrome_frame/chrome_frame_automation.cc b/chrome_frame/chrome_frame_automation.cc index f505ffe..5775d3b 100644 --- a/chrome_frame/chrome_frame_automation.cc +++ b/chrome_frame/chrome_frame_automation.cc @@ -705,6 +705,10 @@ void ChromeFrameAutomationClient::InstallExtensionComplete( } } +void ChromeFrameAutomationClient::OnChromeFrameHostMoved() { + tab_->OnHostMoved(); +} + void ChromeFrameAutomationClient::LoadExpandedExtension( const FilePath& path, void* user_data) { diff --git a/chrome_frame/chrome_frame_automation.h b/chrome_frame/chrome_frame_automation.h index 8b2f801..f9e37c4 100644 --- a/chrome_frame/chrome_frame_automation.h +++ b/chrome_frame/chrome_frame_automation.h @@ -191,6 +191,8 @@ class ChromeFrameAutomationClient void* user_data, AutomationMsg_ExtensionResponseValues res); + virtual void OnChromeFrameHostMoved(); + TabProxy* tab() const { return tab_.get(); } BEGIN_MSG_MAP(ChromeFrameAutomationClient) diff --git a/chrome_frame/chrome_frame_delegate.h b/chrome_frame/chrome_frame_delegate.h index 49ae1c1..11eaa30 100644 --- a/chrome_frame/chrome_frame_delegate.h +++ b/chrome_frame/chrome_frame_delegate.h @@ -37,6 +37,10 @@ class ChromeFrameDelegate { // messages. virtual bool IsValid() const = 0; + // To be called when the top-most window of an application hosting + // ChromeFrame is moved. + virtual void OnHostMoved() = 0; + protected: ~ChromeFrameDelegate() {} }; @@ -71,6 +75,8 @@ class ChromeFrameDelegateImpl : public ChromeFrameDelegate { return true; } + virtual void OnHostMoved() {} + protected: // Protected methods to be overriden. virtual void OnNavigationStateChanged(int tab_handle, int flags, diff --git a/chrome_frame/chrome_frame_plugin.h b/chrome_frame/chrome_frame_plugin.h index 293cb99..be85e26 100644 --- a/chrome_frame/chrome_frame_plugin.h +++ b/chrome_frame/chrome_frame_plugin.h @@ -86,6 +86,10 @@ END_MSG_MAP() return automation_client_.get() != NULL; } + virtual void OnHostMoved() { + automation_client_->OnChromeFrameHostMoved(); + } + protected: virtual void OnNavigationFailed(int tab_handle, int error_code, const GURL& gurl) { |