summaryrefslogtreecommitdiffstats
path: root/chrome/browser/automation
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/automation')
-rw-r--r--chrome/browser/automation/automation_provider.cc106
-rw-r--r--chrome/browser/automation/automation_provider.h7
-rw-r--r--chrome/browser/automation/automation_provider_gtk.cc12
-rw-r--r--chrome/browser/automation/automation_provider_mac.mm10
-rw-r--r--chrome/browser/automation/automation_provider_views.cc1
-rw-r--r--chrome/browser/automation/automation_provider_win.cc23
-rw-r--r--chrome/browser/automation/ui_controls_win.cc15
7 files changed, 152 insertions, 22 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index a2b7d8d..d8bfa76 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -86,6 +86,11 @@
#include "chrome/browser/automation/ui_controls.h"
#endif // !defined(OS_MACOSX)
+#if defined(TOOLKIT_VIEWS)
+#include "views/focus/focus_manager.h"
+#include "views/view.h"
+#endif // defined(TOOLKIT_VIEWS)
+
using base::Time;
class AutomationInterstitialPage : public InterstitialPage {
@@ -345,7 +350,11 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowCount,
GetConstrainedWindowCount)
IPC_MESSAGE_HANDLER(AutomationMsg_FindInPage, HandleFindInPageRequest)
+#if defined(TOOLKIT_VIEWS)
IPC_MESSAGE_HANDLER(AutomationMsg_GetFocusedViewID, GetFocusedViewID)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForFocusedViewIDToChange,
+ WaitForFocusedViewIDToChange)
+#endif
IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_InspectElement,
HandleInspectElementRequest)
IPC_MESSAGE_HANDLER(AutomationMsg_DownloadDirectory, GetDownloadDirectory)
@@ -497,6 +506,7 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoginWithUserAndPass,
LoginWithUserAndPass)
#endif
+ IPC_MESSAGE_HANDLER(AutomationMsg_IsPopUpMenuOpen, IsPopUpMenuOpen)
IPC_END_MESSAGE_MAP()
}
@@ -2528,3 +2538,99 @@ void AutomationProvider::SetContentSetting(
*success = true;
}
}
+
+#if defined(TOOLKIT_VIEWS)
+void AutomationProvider::GetFocusedViewID(int handle, int* view_id) {
+ *view_id = -1;
+ if (window_tracker_->ContainsHandle(handle)) {
+ gfx::NativeWindow window = window_tracker_->GetResource(handle);
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManagerForNativeWindow(window);
+ DCHECK(focus_manager);
+ views::View* focused_view = focus_manager->GetFocusedView();
+ if (focused_view)
+ *view_id = focused_view->GetID();
+ }
+}
+
+// Helper class that waits until the focus has changed to a view other
+// than the one with the provided view id.
+class ViewFocusChangeWaiter : public views::FocusChangeListener {
+ public:
+ ViewFocusChangeWaiter(views::FocusManager* focus_manager,
+ int previous_view_id,
+ AutomationProvider* automation,
+ IPC::Message* reply_message)
+ : focus_manager_(focus_manager),
+ previous_view_id_(previous_view_id),
+ automation_(automation),
+ reply_message_(reply_message),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+ focus_manager_->AddFocusChangeListener(this);
+ // Call the focus change notification once in case the focus has
+ // already changed.
+ FocusWillChange(NULL, focus_manager_->GetFocusedView());
+ }
+
+ ~ViewFocusChangeWaiter() {
+ focus_manager_->RemoveFocusChangeListener(this);
+ }
+
+ // Inherited from FocusChangeListener
+ virtual void FocusWillChange(views::View* focused_before,
+ views::View* focused_now) {
+ // This listener is called before focus actually changes. Post a task
+ // that will get run after focus changes.
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &ViewFocusChangeWaiter::FocusChanged,
+ focused_before,
+ focused_now));
+ }
+
+ private:
+ void FocusChanged(views::View* focused_before,
+ views::View* focused_now) {
+ if (focused_now && focused_now->GetID() != previous_view_id_) {
+ AutomationMsg_WaitForFocusedViewIDToChange::WriteReplyParams(
+ reply_message_, true, focused_now->GetID());
+
+ automation_->Send(reply_message_);
+ delete this;
+ }
+ }
+
+ views::FocusManager* focus_manager_;
+ int previous_view_id_;
+ AutomationProvider* automation_;
+ IPC::Message* reply_message_;
+ ScopedRunnableMethodFactory<ViewFocusChangeWaiter> method_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewFocusChangeWaiter);
+};
+
+void AutomationProvider::WaitForFocusedViewIDToChange(
+ int handle, int previous_view_id, IPC::Message* reply_message) {
+ if (!window_tracker_->ContainsHandle(handle))
+ return;
+ gfx::NativeWindow window = window_tracker_->GetResource(handle);
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManagerForNativeWindow(window);
+
+ // The waiter will respond to the IPC and delete itself when done.
+ new ViewFocusChangeWaiter(focus_manager,
+ previous_view_id,
+ this,
+ reply_message);
+}
+#else
+void AutomationProvider::GetFocusedViewID(int handle, int* view_id) {
+ NOTIMPLEMENTED();
+};
+
+void AutomationProvider::WaitForFocusedViewIDToChange(
+ int handle, int previous_view_id, IPC::Message* reply_message) {
+ NOTIMPLEMENTED();
+}
+#endif // defined(TOOLKIT_VIEWS)
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index e5b36bf..29aba68 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -247,6 +247,9 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
#endif // defined(OS_WIN)
void GetFocusedViewID(int handle, int* view_id);
+ void WaitForFocusedViewIDToChange(int handle,
+ int previous_view_id,
+ IPC::Message* reply_message);
// Helper function to find the browser window that contains a given
// NavigationController and activate that tab.
@@ -579,6 +582,10 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
// Returns NULL on failure.
RenderViewHost* GetViewForTab(int tab_handle);
+ // Returns true if any popup menu is open. Currently only fully implemented
+ // on Windows and doesn't support bookmark menus.
+ void IsPopUpMenuOpen(int handle, bool* success, bool* is_open);
+
typedef ObserverList<NotificationObserver> NotificationObserverList;
typedef std::map<NavigationController*, LoginHandler*> LoginHandlerMap;
typedef std::map<int, ExtensionPortContainer*> PortContainerMap;
diff --git a/chrome/browser/automation/automation_provider_gtk.cc b/chrome/browser/automation/automation_provider_gtk.cc
index 601e81a..c617f3f 100644
--- a/chrome/browser/automation/automation_provider_gtk.cc
+++ b/chrome/browser/automation/automation_provider_gtk.cc
@@ -79,10 +79,6 @@ void AutomationProvider::IsWindowMaximized(int handle, bool* is_maximized,
NOTIMPLEMENTED();
}
-void AutomationProvider::GetFocusedViewID(int handle, int* view_id) {
- NOTIMPLEMENTED();
-}
-
void AutomationProvider::PrintAsync(int tab_handle) {
NOTIMPLEMENTED();
}
@@ -228,3 +224,11 @@ void AutomationProvider::GetWindowTitle(int handle, string16* text) {
text->assign(UTF8ToUTF16(title));
}
+void AutomationProvider::IsPopUpMenuOpen(
+ int handle, bool* success, bool* is_open) {
+ *success = true;
+ *is_open = true;
+ // A GTK implementation of this method is not currently needed; GTK menus
+ // pop up immediately so there's no need to wait until they appear.
+ NOTIMPLEMENTED();
+}
diff --git a/chrome/browser/automation/automation_provider_mac.mm b/chrome/browser/automation/automation_provider_mac.mm
index f58b7a8..08a9575 100644
--- a/chrome/browser/automation/automation_provider_mac.mm
+++ b/chrome/browser/automation/automation_provider_mac.mm
@@ -66,10 +66,6 @@ void AutomationProvider::IsWindowMaximized(int handle, bool* is_maximized,
NOTIMPLEMENTED();
}
-void AutomationProvider::GetFocusedViewID(int handle, int* view_id) {
- NOTIMPLEMENTED();
-}
-
void AutomationProvider::PrintAsync(int tab_handle) {
NOTIMPLEMENTED();
}
@@ -159,3 +155,9 @@ void AutomationProvider::GetWindowTitle(int handle, string16* text) {
text->assign(base::SysNSStringToUTF16(title));
}
+void AutomationProvider::IsPopUpMenuOpen(
+ int handle, bool* success, bool* is_open) {
+ *success = false;
+ *is_open = false;
+ NOTIMPLEMENTED();
+}
diff --git a/chrome/browser/automation/automation_provider_views.cc b/chrome/browser/automation/automation_provider_views.cc
index f161105..a827b06 100644
--- a/chrome/browser/automation/automation_provider_views.cc
+++ b/chrome/browser/automation/automation_provider_views.cc
@@ -33,4 +33,3 @@ void AutomationProvider::WindowGetViewBounds(int handle, int view_id,
}
}
}
-
diff --git a/chrome/browser/automation/automation_provider_win.cc b/chrome/browser/automation/automation_provider_win.cc
index 9539498..9474e90 100644
--- a/chrome/browser/automation/automation_provider_win.cc
+++ b/chrome/browser/automation/automation_provider_win.cc
@@ -231,19 +231,6 @@ void AutomationProvider::WindowSimulateDrag(int handle,
}
}
-void AutomationProvider::GetFocusedViewID(int handle, int* view_id) {
- *view_id = -1;
- if (window_tracker_->ContainsHandle(handle)) {
- HWND hwnd = window_tracker_->GetResource(handle);
- views::FocusManager* focus_manager =
- views::FocusManager::GetFocusManagerForNativeView(hwnd);
- DCHECK(focus_manager);
- views::View* focused_view = focus_manager->GetFocusedView();
- if (focused_view)
- *view_id = focused_view->GetID();
- }
-}
-
void AutomationProvider::GetWindowBounds(int handle, gfx::Rect* bounds,
bool* success) {
*success = false;
@@ -506,3 +493,13 @@ void AutomationProvider::GetWindowTitle(int handle, string16* text) {
::GetWindowText(window, WriteInto(&result, length), length);
text->assign(WideToUTF16(result));
}
+
+void AutomationProvider::IsPopUpMenuOpen(
+ int handle, bool* success, bool* is_open) {
+ *success = true;
+
+ // Check for the existence of a pop-up menu using its
+ // window class (#32768). Note that this won't cover
+ // bookmark menus.
+ *is_open = (::FindWindow(L"#32768", 0) != NULL);
+}
diff --git a/chrome/browser/automation/ui_controls_win.cc b/chrome/browser/automation/ui_controls_win.cc
index 3ff1a5c..aba7248 100644
--- a/chrome/browser/automation/ui_controls_win.cc
+++ b/chrome/browser/automation/ui_controls_win.cc
@@ -166,6 +166,21 @@ bool SendKeyPressImpl(base::KeyboardCode key,
scoped_refptr<InputDispatcher> dispatcher(
task ? new InputDispatcher(task, WM_KEYUP) : NULL);
+ // If a pop-up menu is open, it won't receive events sent using SendInput.
+ // Check for a pop-up menu using its window class (#32768) and if one
+ // exists, send the key event directly there.
+ HWND popup_menu = ::FindWindow(L"#32768", 0);
+ if (popup_menu != NULL) {
+ WPARAM w_param = win_util::KeyboardCodeToWin(key);
+ LPARAM l_param = 0;
+ ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param);
+ ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param);
+
+ if (dispatcher.get())
+ dispatcher->AddRef();
+ return true;
+ }
+
INPUT input[8] = { 0 }; // 8, assuming all the modifiers are activated
int i = 0;