diff options
Diffstat (limited to 'chrome/browser/automation/automation_provider_views.cc')
-rw-r--r-- | chrome/browser/automation/automation_provider_views.cc | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/chrome/browser/automation/automation_provider_views.cc b/chrome/browser/automation/automation_provider_views.cc new file mode 100644 index 0000000..f130079 --- /dev/null +++ b/chrome/browser/automation/automation_provider_views.cc @@ -0,0 +1,190 @@ +// Copyright (c) 2009 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/automation/automation_provider.h" + +#include "chrome/browser/automation/automation_browser_tracker.h" +#include "chrome/browser/automation/automation_window_tracker.h" +#include "chrome/browser/views/frame/browser_view.h" +#include "chrome/browser/views/toolbar_view.h" +#include "chrome/test/automation/automation_messages.h" +#include "gfx/point.h" +#include "views/controls/menu/menu_wrapper.h" +#include "views/focus/focus_manager.h" +#include "views/view.h" +#include "views/widget/root_view.h" +#include "views/widget/widget.h" + +void AutomationProvider::WindowGetViewBounds(int handle, int view_id, + bool screen_coordinates, + bool* success, + gfx::Rect* bounds) { + *success = false; + + if (window_tracker_->ContainsHandle(handle)) { + gfx::NativeWindow window = window_tracker_->GetResource(handle); + views::RootView* root_view = views::Widget::FindRootView(window); + if (root_view) { + views::View* view = root_view->GetViewByID(view_id); + if (view) { + *success = true; + gfx::Point point; + if (screen_coordinates) + views::View::ConvertPointToScreen(view, &point); + else + views::View::ConvertPointToView(view, root_view, &point); + *bounds = view->GetLocalBounds(false); + bounds->set_origin(point); + } + } + } +} + +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); +} + +class PopupMenuWaiter : public views::MenuListener { + public: + PopupMenuWaiter(ToolbarView* toolbar_view, + AutomationProvider* automation) + : toolbar_view_(toolbar_view), + automation_(automation), + reply_message_(NULL) { + toolbar_view_->AddMenuListener(this); + } + + // Implementation of views::MenuListener + virtual void OnMenuOpened() { + toolbar_view_->RemoveMenuListener(this); + automation_->popup_menu_opened_ = true; + automation_->popup_menu_waiter_ = NULL; + if (reply_message_) { + AutomationMsg_WaitForPopupMenuToOpen::WriteReplyParams( + reply_message_, true); + automation_->Send(reply_message_); + } + delete this; + } + + void set_reply_message(IPC::Message* reply_message) { + reply_message_ = reply_message; + } + + private: + ToolbarView* toolbar_view_; + AutomationProvider* automation_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(PopupMenuWaiter); +}; + +void AutomationProvider::StartTrackingPopupMenus( + int browser_handle, bool* success) { + if (browser_tracker_->ContainsHandle(browser_handle)) { + Browser* browser = browser_tracker_->GetResource(browser_handle); + BrowserView* browser_view = reinterpret_cast<BrowserView*>( + browser->window()); + ToolbarView* toolbar_view = browser_view->GetToolbarView(); + popup_menu_opened_ = false; + popup_menu_waiter_ = new PopupMenuWaiter(toolbar_view, this); + *success = true; + } +} + +void AutomationProvider::WaitForPopupMenuToOpen(IPC::Message* reply_message) { + // See if the menu already opened and return true if so. + if (popup_menu_opened_) { + AutomationMsg_WaitForPopupMenuToOpen::WriteReplyParams( + reply_message, true); + Send(reply_message); + return; + } + + // Otherwise, register this reply message with the waiter, + // which will handle responding to this IPC when the popup + // menu opens. + popup_menu_waiter_->set_reply_message(reply_message); +} |