diff options
Diffstat (limited to 'chrome/browser/automation')
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 106 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider.h | 7 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_gtk.cc | 12 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_mac.mm | 10 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_views.cc | 1 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_win.cc | 23 | ||||
-rw-r--r-- | chrome/browser/automation/ui_controls_win.cc | 15 |
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; |