summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortwiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-16 02:24:18 +0000
committertwiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-16 02:24:18 +0000
commit2b19e2feeac2a01b2068595bd2913a194a6527e5 (patch)
treefff83de7ba198462e1d00b96911685418dd130bd
parent00a3768102287ae6f8ff5e28347a920759d3374d (diff)
downloadchromium_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
-rw-r--r--chrome/browser/automation/automation_provider.cc4
-rw-r--r--chrome/browser/automation/automation_provider.h3
-rw-r--r--chrome/browser/automation/automation_provider_win.cc10
-rw-r--r--chrome/browser/automation/chrome_frame_automation_provider.cc1
-rw-r--r--chrome/browser/external_tab_container.cc13
-rw-r--r--chrome/browser/external_tab_container.h10
-rw-r--r--chrome/browser/views/browser_bubble.cc38
-rw-r--r--chrome/browser/views/browser_bubble.h7
-rw-r--r--chrome/browser/views/frame/browser_bubble_host.cc43
-rw-r--r--chrome/browser/views/frame/browser_bubble_host.h42
-rw-r--r--chrome/browser/views/frame/browser_view.cc26
-rw-r--r--chrome/browser/views/frame/browser_view.h11
-rwxr-xr-xchrome/chrome_browser.gypi4
-rw-r--r--chrome/test/automation/automation_messages_internal.h7
-rw-r--r--chrome/test/automation/tab_proxy.cc4
-rw-r--r--chrome/test/automation/tab_proxy.h3
-rw-r--r--chrome_frame/chrome_frame_activex.cc128
-rw-r--r--chrome_frame/chrome_frame_activex.h12
-rw-r--r--chrome_frame/chrome_frame_automation.cc4
-rw-r--r--chrome_frame/chrome_frame_automation.h2
-rw-r--r--chrome_frame/chrome_frame_delegate.h6
-rw-r--r--chrome_frame/chrome_frame_plugin.h4
22 files changed, 332 insertions, 50 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 8cef80a..be3a44e 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -465,6 +465,9 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(AutomationMsg_ShutdownSessionService,
ShutdownSessionService)
IPC_MESSAGE_HANDLER(AutomationMsg_SaveAsAsync, SaveAsAsync)
+#if defined(OS_WIN)
+ IPC_MESSAGE_HANDLER(AutomationMsg_BrowserMove, OnBrowserMoved)
+#endif
IPC_END_MESSAGE_MAP()
}
@@ -2264,4 +2267,3 @@ void AutomationProvider::SaveAsAsync(int tab_handle) {
if (tab_contents)
tab_contents->OnSavePage();
}
-
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index de371f8..24b381a 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -229,6 +229,9 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
void SetProxyConfig(const std::string& new_proxy_config);
void IsFullscreen(int handle, bool* is_fullscreen);
void GetFullscreenBubbleVisibility(int handle, bool* is_visible);
+#if defined(OS_WIN)
+ void OnBrowserMoved(int handle);
+#endif
#if defined(OS_WIN)
void ScheduleMouseEvent(views::View* view,
diff --git a/chrome/browser/automation/automation_provider_win.cc b/chrome/browser/automation/automation_provider_win.cc
index d5457e9..59d9867 100644
--- a/chrome/browser/automation/automation_provider_win.cc
+++ b/chrome/browser/automation/automation_provider_win.cc
@@ -506,3 +506,13 @@ void AutomationProvider::SetEnableExtensionAutomation(
"SetEnableExtensionAutomation called with invalid tab handle.";
}
}
+
+void AutomationProvider::OnBrowserMoved(int tab_handle) {
+ ExternalTabContainer* external_tab = GetExternalTabForHandle(tab_handle);
+ if (external_tab) {
+ external_tab->WindowMoved();
+ } else {
+ DLOG(WARNING) <<
+ "AutomationProvider::OnBrowserMoved called with invalid tab handle.";
+ }
+}
diff --git a/chrome/browser/automation/chrome_frame_automation_provider.cc b/chrome/browser/automation/chrome_frame_automation_provider.cc
index f9e82f7..ab87b92 100644
--- a/chrome/browser/automation/chrome_frame_automation_provider.cc
+++ b/chrome/browser/automation/chrome_frame_automation_provider.cc
@@ -35,6 +35,7 @@ bool ChromeFrameAutomationProvider::IsValidMessage(uint32 type) {
case AutomationMsg_CreateExternalTab::ID:
case AutomationMsg_ConnectExternalTab::ID:
#if defined(OS_WIN)
+ case AutomationMsg_BrowserMove::ID:
case AutomationMsg_ProcessUnhandledAccelerator::ID:
case AutomationMsg_TabReposition::ID:
case AutomationMsg_ForwardContextMenuCommandToChrome::ID:
diff --git a/chrome/browser/external_tab_container.cc b/chrome/browser/external_tab_container.cc
index 9e098fd..837d006 100644
--- a/chrome/browser/external_tab_container.cc
+++ b/chrome/browser/external_tab_container.cc
@@ -256,7 +256,7 @@ void ExternalTabContainer::FocusThroughTabTraversal(bool reverse) {
// static
bool ExternalTabContainer::IsExternalTabContainer(HWND window) {
- if (GetProp(window, kWindowObjectKey) != NULL)
+ if (::GetProp(window, kWindowObjectKey) != NULL)
return true;
return false;
@@ -277,6 +277,17 @@ ExternalTabContainer* ExternalTabContainer::GetContainerForTab(
return container;
}
+// static
+ExternalTabContainer*
+ ExternalTabContainer::GetExternalContainerFromNativeWindow(
+ gfx::NativeView native_window) {
+ ExternalTabContainer* tab_container = NULL;
+ if (native_window) {
+ HANDLE handle = ::GetProp(native_window, kWindowObjectKey);
+ tab_container = reinterpret_cast<ExternalTabContainer*>(handle);
+ }
+ return tab_container;
+}
////////////////////////////////////////////////////////////////////////////////
// ExternalTabContainer, TabContentsDelegate implementation:
diff --git a/chrome/browser/external_tab_container.h b/chrome/browser/external_tab_container.h
index 0b25afb..154d258 100644
--- a/chrome/browser/external_tab_container.h
+++ b/chrome/browser/external_tab_container.h
@@ -13,6 +13,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "chrome/browser/views/frame/browser_bubble_host.h"
#include "chrome/browser/views/infobars/infobar_container.h"
#include "chrome/browser/views/unhandled_keyboard_event_handler.h"
#include "chrome/common/navigation_types.h"
@@ -39,7 +40,8 @@ class ExternalTabContainer : public TabContentsDelegate,
public views::WidgetWin,
public base::RefCounted<ExternalTabContainer>,
public views::AcceleratorTarget,
- public InfoBarContainer::Delegate {
+ public InfoBarContainer::Delegate,
+ public BrowserBubbleHost {
public:
typedef std::map<intptr_t, scoped_refptr<ExternalTabContainer> > PendingTabs;
@@ -89,6 +91,12 @@ class ExternalTabContainer : public TabContentsDelegate,
// ExternalTabContainer window
static bool IsExternalTabContainer(HWND window);
+ // A helper function that returns a pointer to the ExternalTabContainer
+ // instance associated with a native view. Returns NULL if the window
+ // is not an ExternalTabContainer.
+ static ExternalTabContainer* GetExternalContainerFromNativeWindow(
+ gfx::NativeView native_window);
+
// A helper method that retrieves the ExternalTabContainer object that
// hosts the given tab window.
static ExternalTabContainer* GetContainerForTab(HWND tab_window);
diff --git a/chrome/browser/views/browser_bubble.cc b/chrome/browser/views/browser_bubble.cc
index 1b690db..b199680 100644
--- a/chrome/browser/views/browser_bubble.cc
+++ b/chrome/browser/views/browser_bubble.cc
@@ -6,20 +6,35 @@
#include "app/l10n_util.h"
#include "chrome/browser/views/frame/browser_view.h"
+#if defined(OS_WIN)
+#include "chrome/browser/external_tab_container.h"
+#endif
#include "views/widget/root_view.h"
#include "views/window/window.h"
namespace {
-BrowserView* GetBrowserViewFromFrame(views::Widget* frame) {
- BrowserView* browser_view = NULL;
+BrowserBubbleHost* GetBubbleHostFromFrame(views::Widget* frame) {
+ if (!frame)
+ return NULL;
+
+ BrowserBubbleHost* bubble_host = NULL;
views::Window* window = frame->GetWindow();
if (window) {
- browser_view = BrowserView::GetBrowserViewForNativeWindow(
+ bubble_host = BrowserView::GetBrowserViewForNativeWindow(
window->GetNativeWindow());
- DCHECK(browser_view);
+ DCHECK(bubble_host);
+ }
+#if defined(OS_WIN)
+ // The frame may also be an ExternalTabContainer, which is also capable of
+ // hosting BrowserBubbles.
+ gfx::NativeView native_view = frame->GetNativeView();
+ if (!bubble_host) {
+ bubble_host =
+ ExternalTabContainer::GetExternalContainerFromNativeWindow(native_view);
}
- return browser_view;
+#endif
+ return bubble_host;
}
} // namespace
@@ -31,7 +46,8 @@ BrowserBubble::BrowserBubble(views::View* view, views::Widget* frame,
visible_(false),
delegate_(NULL),
attached_(false),
- drop_shadow_enabled_(drop_shadow) {
+ drop_shadow_enabled_(drop_shadow),
+ bubble_host_(GetBubbleHostFromFrame(frame)) {
gfx::Size size = view->GetPreferredSize();
bounds_.SetRect(origin.x(), origin.y(), size.width(), size.height());
InitPopup();
@@ -55,9 +71,8 @@ void BrowserBubble::DetachFromBrowser() {
return;
attached_ = false;
- BrowserView* browser_view = GetBrowserViewFromFrame(frame_);
- if (browser_view)
- browser_view->DetachBrowserBubble(this);
+ if (bubble_host_)
+ bubble_host_->DetachBrowserBubble(this);
}
void BrowserBubble::AttachToBrowser() {
@@ -65,9 +80,8 @@ void BrowserBubble::AttachToBrowser() {
if (attached_)
return;
- BrowserView* browser_view = GetBrowserViewFromFrame(frame_);
- if (browser_view)
- browser_view->AttachBrowserBubble(this);
+ if (bubble_host_)
+ bubble_host_->AttachBrowserBubble(this);
attached_ = true;
}
diff --git a/chrome/browser/views/browser_bubble.h b/chrome/browser/views/browser_bubble.h
index 012c552..feb55f8 100644
--- a/chrome/browser/views/browser_bubble.h
+++ b/chrome/browser/views/browser_bubble.h
@@ -8,6 +8,8 @@
#include "views/view.h"
#include "views/widget/widget.h"
+class BrowserBubbleHost;
+
// A class for creating a floating window that is "attached" to a particular
// Browser. If you don't install a delegate, the bubble will hide
// automatically when the browser moves. The bubble is only shown manually.
@@ -58,7 +60,7 @@ class BrowserBubble {
Delegate* delegate() const { return delegate_; }
void set_delegate(Delegate* del) { delegate_ = del; }
- // Notifications from BrowserView.
+ // Notifications from BrowserBubbleHost.
// With no delegate, both of these default to Hiding the bubble.
virtual void BrowserWindowMoved();
virtual void BrowserWindowClosing();
@@ -120,6 +122,9 @@ class BrowserBubble {
// Does the bubble have a drop-shadow.
bool drop_shadow_enabled_;
+ // Non-owning pointer to the host of this bubble.
+ BrowserBubbleHost* bubble_host_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserBubble);
};
diff --git a/chrome/browser/views/frame/browser_bubble_host.cc b/chrome/browser/views/frame/browser_bubble_host.cc
new file mode 100644
index 0000000..60809bf
--- /dev/null
+++ b/chrome/browser/views/frame/browser_bubble_host.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2010 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/browser/views/frame/browser_bubble_host.h"
+
+#include "base/logging.h"
+#include "chrome/browser/views/browser_bubble.h"
+
+void BrowserBubbleHost::WindowMoved() {
+ // Do safe iteration in case the bubble winds up closing as a result of this
+ // message.
+ for (BubbleSet::iterator i = browser_bubbles_.begin();
+ i != browser_bubbles_.end();) {
+ BubbleSet::iterator bubble = i++;
+ (*bubble)->BrowserWindowMoved();
+ }
+}
+
+void BrowserBubbleHost::AttachBrowserBubble(BrowserBubble* bubble) {
+ DCHECK(browser_bubbles_.find(bubble) == browser_bubbles_.end()) <<
+ "Attempt to register the same BrowserBubble multiple times.";
+ browser_bubbles_.insert(bubble);
+}
+
+void BrowserBubbleHost::DetachBrowserBubble(BrowserBubble* bubble) {
+ BubbleSet::iterator it = browser_bubbles_.find(bubble);
+ DCHECK(it != browser_bubbles_.end()) <<
+ "Attempt to detach an unrecognized BrowserBubble.";
+ if (it != browser_bubbles_.end())
+ browser_bubbles_.erase(it);
+}
+
+void BrowserBubbleHost::Close() {
+ // BrowserWindowClosing will usually cause the bubble to remove itself from
+ // the set, so we need to iterate in a way that's safe against deletion.
+ for (BubbleSet::iterator i = browser_bubbles_.begin();
+ i != browser_bubbles_.end();) {
+ BubbleSet::iterator bubble = i++;
+ (*bubble)->BrowserWindowClosing();
+ }
+}
+
diff --git a/chrome/browser/views/frame/browser_bubble_host.h b/chrome/browser/views/frame/browser_bubble_host.h
new file mode 100644
index 0000000..4763a50
--- /dev/null
+++ b/chrome/browser/views/frame/browser_bubble_host.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_VIEWS_FRAME_BROWSER_BUBBLE_HOST_H_
+#define CHROME_BROWSER_VIEWS_FRAME_BROWSER_BUBBLE_HOST_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+
+class BrowserBubble;
+
+// A class providing a hosting environment for BrowserBubble instances.
+// Allows for notification to attached BrowserBubbles of browser move, and
+// close events.
+class BrowserBubbleHost {
+ public:
+ BrowserBubbleHost() {}
+
+ // Invoked when the window containing the attached browser-bubbles is moved.
+ // Calls BrowserBubble::BrowserWindowMoved on all attached bubbles.
+ void WindowMoved();
+
+ // To be called when the frame containing the BrowserBubbleHost is closing.
+ // Calls BrowserBubble::BrowserWindowClosing on all attached bubbles.
+ void Close();
+
+ // Registers/Unregisters |bubble| to receive notifications when the host moves
+ // or is closed.
+ void AttachBrowserBubble(BrowserBubble* bubble);
+ void DetachBrowserBubble(BrowserBubble* bubble);
+
+ private:
+ // The set of bubbles associated with this host.
+ typedef std::set<BrowserBubble*> BubbleSet;
+ BubbleSet browser_bubbles_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserBubbleHost);
+};
+
+#endif // CHROME_BROWSER_VIEWS_FRAME_BROWSER_BUBBLE_HOST_H_
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index b6a3e17..f3ccddf 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -486,13 +486,7 @@ void BrowserView::WindowMoved() {
status_bubble_->Reposition();
- // Do safe iteration in case the bubble winds up closing as a result of this
- // message.
- for (BubbleSet::iterator i = browser_bubbles_.begin();
- i != browser_bubbles_.end();) {
- BubbleSet::iterator bubble = i++;
- (*bubble)->BrowserWindowMoved();
- }
+ BrowserBubbleHost::WindowMoved();
browser::HideBookmarkBubbleView();
@@ -653,16 +647,6 @@ void BrowserView::RegisterBrowserViewPrefs(PrefService* prefs) {
kDefaultHungPluginDetectFrequency);
}
-void BrowserView::AttachBrowserBubble(BrowserBubble* bubble) {
- browser_bubbles_.insert(bubble);
-}
-
-void BrowserView::DetachBrowserBubble(BrowserBubble* bubble) {
- BubbleSet::iterator it = browser_bubbles_.find(bubble);
- if (it != browser_bubbles_.end())
- browser_bubbles_.erase(it);
-}
-
bool BrowserView::IsPositionInWindowCaption(const gfx::Point& point) {
return GetBrowserViewLayout()->IsPositionInWindowCaption(point);
}
@@ -712,13 +696,7 @@ void BrowserView::SetBounds(const gfx::Rect& bounds) {
}
void BrowserView::Close() {
- // BrowserWindowClosing will usually cause the bubble to remove itself from
- // the set, so we need to iterate in a way that's safe against deletion.
- for (BubbleSet::iterator i = browser_bubbles_.begin();
- i != browser_bubbles_.end();) {
- BubbleSet::iterator bubble = i++;
- (*bubble)->BrowserWindowClosing();
- }
+ BrowserBubbleHost::Close();
frame_->GetWindow()->Close();
}
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index 02fa1e0..7732621 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -17,6 +17,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/views/frame/browser_bubble_host.h"
#include "chrome/browser/views/frame/browser_frame.h"
#include "chrome/browser/views/infobars/infobar_container.h"
#include "chrome/browser/views/tabs/tab_strip.h"
@@ -67,7 +68,8 @@ class SingleSplitView;
// A ClientView subclass that provides the contents of a browser window,
// including the TabStrip, toolbars, download shelves, the content area etc.
//
-class BrowserView : public BrowserWindow,
+class BrowserView : public BrowserBubbleHost,
+ public BrowserWindow,
public BrowserWindowTesting,
public NotificationObserver,
public TabStripModelObserver,
@@ -216,10 +218,6 @@ class BrowserView : public BrowserWindow,
// Register preferences specific to this view.
static void RegisterBrowserViewPrefs(PrefService* prefs);
- // Attach/Detach a BrowserBubble to the browser.
- void AttachBrowserBubble(BrowserBubble *bubble);
- void DetachBrowserBubble(BrowserBubble *bubble);
-
// Returns true if the specified point(BrowserView coordinates) is in
// in the window caption area of the browser window.
bool IsPositionInWindowCaption(const gfx::Point& point);
@@ -561,9 +559,6 @@ class BrowserView : public BrowserWindow,
// A bottom bar for showing extensions.
ExtensionShelf* extension_shelf_;
- typedef std::set<BrowserBubble*> BubbleSet;
- BubbleSet browser_bubbles_;
-
// The accessible name of this view.
std::wstring accessible_name_;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index c548fe5..aafc27e 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1929,6 +1929,8 @@
'browser/views/first_run_view_base.h',
'browser/views/frame/app_panel_browser_frame_view.cc',
'browser/views/frame/app_panel_browser_frame_view.h',
+ 'browser/views/frame/browser_bubble_host.cc',
+ 'browser/views/frame/browser_bubble_host.h',
'browser/views/frame/browser_extender.cc',
'browser/views/frame/browser_extender.h',
'browser/views/frame/browser_frame.h',
@@ -2521,6 +2523,8 @@
['include', '^browser/views/theme_install_bubble_view.h'],
['include', '^browser/views/toolbar_star_toggle.h'],
['include', '^browser/views/toolbar_star_toggle.cc'],
+ ['include', '^browser/views/frame/browser_bubble_host.cc'],
+ ['include', '^browser/views/frame/browser_bubble_host.h'],
['include', '^browser/views/frame/browser_view_layout.cc'],
['include', '^browser/views/frame/browser_view_layout.h'],
['include', '^browser/views/frame/browser_extender.cc'],
diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h
index a3f4945..eb74875 100644
--- a/chrome/test/automation/automation_messages_internal.h
+++ b/chrome/test/automation/automation_messages_internal.h
@@ -1192,4 +1192,11 @@ IPC_BEGIN_MESSAGES(Automation)
IPC_MESSAGE_ROUTED1(AutomationMsg_SaveAsAsync,
int /* tab handle */)
+#if defined(OS_WIN)
+ // An incoming message from an automation host to Chrome. Signals that
+ // the browser containing |tab_handle| has moved.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserMove,
+ int /* tab handle */)
+#endif
+
IPC_END_MESSAGES(Automation)
diff --git a/chrome/test/automation/tab_proxy.cc b/chrome/test/automation/tab_proxy.cc
index ccef84a..dbf4875 100644
--- a/chrome/test/automation/tab_proxy.cc
+++ b/chrome/test/automation/tab_proxy.cc
@@ -708,6 +708,10 @@ void TabProxy::SendContextMenuCommand(int selected_command) {
sender_->Send(new AutomationMsg_ForwardContextMenuCommandToChrome(
0, handle_, selected_command));
}
+
+void TabProxy::OnHostMoved() {
+ sender_->Send(new AutomationMsg_BrowserMove(0, handle_));
+}
#endif // defined(OS_WIN)
void TabProxy::SelectAll() {
diff --git a/chrome/test/automation/tab_proxy.h b/chrome/test/automation/tab_proxy.h
index d8055fa..326f0dc 100644
--- a/chrome/test/automation/tab_proxy.h
+++ b/chrome/test/automation/tab_proxy.h
@@ -360,6 +360,9 @@ class TabProxy : public AutomationResourceProxy {
// Sends the selected context menu command to the chrome instance
void SendContextMenuCommand(int selected_command);
+
+ // To be called when the window hosting the tab has moved.
+ void OnHostMoved();
#endif // defined(OS_WIN)
// Selects all contents on the page.
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) {