summaryrefslogtreecommitdiffstats
path: root/chrome/browser/automation/automation_provider_views.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/automation/automation_provider_views.cc')
-rw-r--r--chrome/browser/automation/automation_provider_views.cc190
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);
+}