diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-21 18:52:44 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-21 18:52:44 +0000 |
commit | 5ae5bedf9983f3fda8829798ec9bcf53787b4b4f (patch) | |
tree | 54d729f79d9ec54778ffe3c226a0ac8e7a0d3a92 /chrome | |
parent | b15f5896af98fa5844071337339b54bbc2b3f236 (diff) | |
download | chromium_src-5ae5bedf9983f3fda8829798ec9bcf53787b4b4f.zip chromium_src-5ae5bedf9983f3fda8829798ec9bcf53787b4b4f.tar.gz chromium_src-5ae5bedf9983f3fda8829798ec9bcf53787b4b4f.tar.bz2 |
Implement SetWindowBounds and SetWindowVisible in AutomationProvider for Linux.
BUG=16616
TEST=covered by automation tests
Review URL: http://codereview.chromium.org/174195
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23992 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 579 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_gtk.cc | 62 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_win.cc | 478 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.cc | 65 |
5 files changed, 598 insertions, 588 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 86ccbb9..7f364cb 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -1,9 +1,11 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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 <set> + #include "app/l10n_util.h" #include "app/message_box_flags.h" #include "base/file_version_info.h" @@ -61,43 +63,13 @@ #include "chrome/browser/printing/print_job.h" #endif // defined(OS_WIN) -#if defined(OS_WIN) || defined(OS_LINUX) +#if !defined(OS_MACOSX) // TODO(port): Port these to the mac. #include "chrome/browser/automation/ui_controls.h" -#endif - -#if defined(OS_WIN) -#include "chrome/browser/views/bookmark_bar_view.h" -#include "views/widget/root_view.h" -#include "views/widget/widget_win.h" -#include "views/window/window.h" -#elif defined(OS_LINUX) -#include "chrome/browser/gtk/view_id_util.h" -#endif +#endif // !defined(OS_MACOSX) using base::Time; -#if defined(OS_WIN) -static void MoveMouse(const POINT& point) { - SetCursorPos(point.x, point.y); - - // Now, make sure that GetMessagePos returns the values we just set by - // simulating a mouse move. The value returned by GetMessagePos is updated - // when a mouse move event is removed from the event queue. - PostMessage(NULL, WM_MOUSEMOVE, 0, MAKELPARAM(point.x, point.y)); - MSG msg; - while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - ; - - // Verify -#ifndef NDEBUG - DWORD pos = GetMessagePos(); - DCHECK_EQ(point.x, GET_X_LPARAM(pos)); - DCHECK_EQ(point.y, GET_Y_LPARAM(pos)); -#endif -} -#endif - class InitialLoadObserver : public NotificationObserver { public: InitialLoadObserver(size_t tab_count, AutomationProvider* automation) @@ -1066,10 +1038,10 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBounds, WindowGetViewBounds) IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowBounds, SetWindowBounds) IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowVisible, SetWindowVisible) -#if defined(OS_WIN) || defined(OS_LINUX) +#if !defined(OS_MACOSX) IPC_MESSAGE_HANDLER(AutomationMsg_WindowClick, WindowSimulateClick) IPC_MESSAGE_HANDLER(AutomationMsg_WindowKeyPress, WindowSimulateKeyPress) -#endif +#endif // !defined(OS_MACOSX) #if defined(OS_WIN) IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowDrag, WindowSimulateDrag) @@ -1502,36 +1474,6 @@ void AutomationProvider::GetLastActiveBrowserWindow(int* handle) { *handle = browser_tracker_->Add(browser); } -#if defined(OS_WIN) -// TODO(port): Remove windowsisms. -BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM l_param) { - if (hwnd == reinterpret_cast<HWND>(l_param)) { - return FALSE; - } - return TRUE; -} - -void AutomationProvider::GetActiveWindow(int* handle) { - HWND window = GetForegroundWindow(); - - // Let's make sure this window belongs to our process. - if (EnumThreadWindows(::GetCurrentThreadId(), - EnumThreadWndProc, - reinterpret_cast<LPARAM>(window))) { - // We enumerated all the windows and did not find the foreground window, - // it is not our window, ignore it. - *handle = 0; - return; - } - - *handle = window_tracker_->Add(window); -} - -void AutomationProvider::GetWindowHWND(int handle, HWND* win32_handle) { - *win32_handle = window_tracker_->GetResource(handle); -} -#endif // defined(OS_WIN) - #if defined(OS_LINUX) // TODO(estade): use this implementation for all platforms? void AutomationProvider::GetActiveWindow(int* handle) { @@ -1571,253 +1513,17 @@ void AutomationProvider::ExecuteBrowserCommand( Send(reply_message); } -void AutomationProvider::WindowGetViewBounds(int handle, int view_id, - bool screen_coordinates, - bool* success, - gfx::Rect* bounds) { - *success = false; - - if (window_tracker_->ContainsHandle(handle)) { -#if defined(OS_WIN) - gfx::NativeWindow window = window_tracker_->GetResource(handle); - views::RootView* root_view = views::WidgetWin::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); - } - } -#elif defined(OS_LINUX) - gfx::NativeWindow window = window_tracker_->GetResource(handle); - GtkWidget* widget = ViewIDUtil::GetWidget(GTK_WIDGET(window), - static_cast<ViewID>(view_id)); - if (!widget) - return; - *success = true; - *bounds = gfx::Rect(0, 0, - widget->allocation.width, widget->allocation.height); - gint x, y; - if (screen_coordinates) { - gdk_window_get_origin(widget->window, &x, &y); - if (GTK_WIDGET_NO_WINDOW(widget)) { - x += widget->allocation.x; - y += widget->allocation.y; - } - } else { - gtk_widget_translate_coordinates(widget, GTK_WIDGET(window), - 0, 0, &x, &y); - } - bounds->set_origin(gfx::Point(x, y)); -#else - NOTIMPLEMENTED(); -#endif - } -} - -#if defined(OS_WIN) -// This task enqueues a mouse event on the event loop, so that the view -// that it's being sent to can do the requisite post-processing. -class MouseEventTask : public Task { - public: - MouseEventTask(views::View* view, - views::Event::EventType type, - const gfx::Point& point, - int flags) - : view_(view), type_(type), point_(point), flags_(flags) {} - virtual ~MouseEventTask() {} - - virtual void Run() { - views::MouseEvent event(type_, point_.x(), point_.y(), flags_); - // We need to set the cursor position before we process the event because - // some code (tab dragging, for instance) queries the actual cursor location - // rather than the location of the mouse event. Note that the reason why - // the drag code moved away from using mouse event locations was because - // our conversion to screen location doesn't work well with multiple - // monitors, so this only works reliably in a single monitor setup. - gfx::Point screen_location(point_.x(), point_.y()); - view_->ConvertPointToScreen(view_, &screen_location); - MoveMouse(screen_location.ToPOINT()); - switch (type_) { - case views::Event::ET_MOUSE_PRESSED: - view_->OnMousePressed(event); - break; - - case views::Event::ET_MOUSE_DRAGGED: - view_->OnMouseDragged(event); - break; - - case views::Event::ET_MOUSE_RELEASED: - view_->OnMouseReleased(event, false); - break; - - default: - NOTREACHED(); - } - } - - private: - views::View* view_; - views::Event::EventType type_; - gfx::Point point_; - int flags_; - - DISALLOW_COPY_AND_ASSIGN(MouseEventTask); -}; - -void AutomationProvider::ScheduleMouseEvent(views::View* view, - views::Event::EventType type, - const gfx::Point& point, - int flags) { - MessageLoop::current()->PostTask(FROM_HERE, - new MouseEventTask(view, type, point, flags)); -} - -#endif // defined(OS_WIN) - -// This task just adds another task to the event queue. This is useful if -// you want to ensure that any tasks added to the event queue after this one -// have already been processed by the time |task| is run. -class InvokeTaskLaterTask : public Task { - public: - explicit InvokeTaskLaterTask(Task* task) : task_(task) {} - virtual ~InvokeTaskLaterTask() {} - - virtual void Run() { - MessageLoop::current()->PostTask(FROM_HERE, task_); - } - - private: - Task* task_; - - DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask); -}; - -#if defined(OS_WIN) -// TODO(port): Replace POINT and other windowsisms. - -// This task sends a WindowDragResponse message with the appropriate -// routing ID to the automation proxy. This is implemented as a task so that -// we know that the mouse events (and any tasks that they spawn on the message -// loop) have been processed by the time this is sent. -class WindowDragResponseTask : public Task { - public: - WindowDragResponseTask(AutomationProvider* provider, - IPC::Message* reply_message) - : provider_(provider), reply_message_(reply_message) {} - virtual ~WindowDragResponseTask() {} - - virtual void Run() { - DCHECK(reply_message_ != NULL); - AutomationMsg_WindowDrag::WriteReplyParams(reply_message_, true); - provider_->Send(reply_message_); - } - - private: - AutomationProvider* provider_; - IPC::Message* reply_message_; - - DISALLOW_COPY_AND_ASSIGN(WindowDragResponseTask); -}; -#endif // defined(OS_WIN) - -#if defined(OS_WIN) || defined(OS_LINUX) +#if !defined(OS_MACOSX) void AutomationProvider::WindowSimulateClick(const IPC::Message& message, int handle, const gfx::Point& click, int flags) { - if (window_tracker_->ContainsHandle(handle)) { ui_controls::SendMouseMoveNotifyWhenDone(click.x(), click.y(), new ClickTask(click, flags)); } } -#endif -#if defined(OS_WIN) -void AutomationProvider::WindowSimulateDrag(int handle, - std::vector<POINT> drag_path, - int flags, - bool press_escape_en_route, - IPC::Message* reply_message) { - bool succeeded = false; - if (browser_tracker_->ContainsHandle(handle) && (drag_path.size() > 1)) { - gfx::NativeWindow window = - browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); - succeeded = true; - - UINT down_message = 0; - UINT up_message = 0; - WPARAM wparam_flags = 0; - if (flags & views::Event::EF_SHIFT_DOWN) - wparam_flags |= MK_SHIFT; - if (flags & views::Event::EF_CONTROL_DOWN) - wparam_flags |= MK_CONTROL; - if (flags & views::Event::EF_LEFT_BUTTON_DOWN) { - wparam_flags |= MK_LBUTTON; - down_message = WM_LBUTTONDOWN; - up_message = WM_LBUTTONUP; - } - if (flags & views::Event::EF_MIDDLE_BUTTON_DOWN) { - wparam_flags |= MK_MBUTTON; - down_message = WM_MBUTTONDOWN; - up_message = WM_MBUTTONUP; - } - if (flags & views::Event::EF_RIGHT_BUTTON_DOWN) { - wparam_flags |= MK_RBUTTON; - down_message = WM_LBUTTONDOWN; - up_message = WM_LBUTTONUP; - } - - Browser* browser = browser_tracker_->GetResource(handle); - DCHECK(browser); - HWND top_level_hwnd = - reinterpret_cast<HWND>(browser->window()->GetNativeHandle()); - POINT temp = drag_path[0]; - MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &temp, 1); - MoveMouse(temp); - SendMessage(top_level_hwnd, down_message, wparam_flags, - MAKELPARAM(drag_path[0].x, drag_path[0].y)); - for (int i = 1; i < static_cast<int>(drag_path.size()); ++i) { - temp = drag_path[i]; - MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &temp, 1); - MoveMouse(temp); - SendMessage(top_level_hwnd, WM_MOUSEMOVE, wparam_flags, - MAKELPARAM(drag_path[i].x, drag_path[i].y)); - } - POINT end = drag_path[drag_path.size() - 1]; - MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &end, 1); - MoveMouse(end); - - if (press_escape_en_route) { - // Press Escape. - ui_controls::SendKeyPress(window, VK_ESCAPE, - ((flags & views::Event::EF_CONTROL_DOWN) - == views::Event::EF_CONTROL_DOWN), - ((flags & views::Event::EF_SHIFT_DOWN) == - views::Event::EF_SHIFT_DOWN), - ((flags & views::Event::EF_ALT_DOWN) == - views::Event::EF_ALT_DOWN)); - } - SendMessage(top_level_hwnd, up_message, wparam_flags, - MAKELPARAM(end.x, end.y)); - - MessageLoop::current()->PostTask(FROM_HERE, new InvokeTaskLaterTask( - new WindowDragResponseTask(this, reply_message))); - } else { - AutomationMsg_WindowDrag::WriteReplyParams(reply_message, true); - Send(reply_message); - } -} -#endif // defined(OS_WIN) - -#if defined(OS_WIN) || defined(OS_LINUX) void AutomationProvider::WindowSimulateKeyPress(const IPC::Message& message, int handle, wchar_t key, @@ -1835,45 +1541,7 @@ void AutomationProvider::WindowSimulateKeyPress(const IPC::Message& message, ((flags & views::Event::EF_ALT_DOWN) == views::Event::EF_ALT_DOWN)); } -#endif - -#if defined(OS_WIN) -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::SetWindowBounds(int handle, const gfx::Rect& bounds, - bool* success) { - *success = false; - if (window_tracker_->ContainsHandle(handle)) { - HWND hwnd = window_tracker_->GetResource(handle); - if (::MoveWindow(hwnd, bounds.x(), bounds.y(), bounds.width(), - bounds.height(), true)) { - *success = true; - } - } -} - -void AutomationProvider::SetWindowVisible(int handle, bool visible, - bool* result) { - if (window_tracker_->ContainsHandle(handle)) { - HWND hwnd = window_tracker_->GetResource(handle); - ::ShowWindow(hwnd, visible ? SW_SHOW : SW_HIDE); - *result = true; - } else { - *result = false; - } -} -#endif // defined(OS_WIN) +#endif // !defined(OS_MACOSX) void AutomationProvider::IsWindowActive(int handle, bool* success, bool* is_active) { @@ -1887,15 +1555,6 @@ void AutomationProvider::IsWindowActive(int handle, bool* success, } } -// TODO(port): port this. -#if defined(OS_WIN) -void AutomationProvider::ActivateWindow(int handle) { - if (window_tracker_->ContainsHandle(handle)) { - ::SetActiveWindow(window_tracker_->GetResource(handle)); - } -} -#endif - void AutomationProvider::GetTabCount(int handle, int* tab_count) { *tab_count = -1; // -1 is the error code @@ -2030,17 +1689,6 @@ void AutomationProvider::GetTabURL(int handle, bool* success, GURL* url) { } } -#if defined(OS_WIN) -void AutomationProvider::GetTabHWND(int handle, HWND* tab_hwnd) { - *tab_hwnd = NULL; - - if (tab_tracker_->ContainsHandle(handle)) { - NavigationController* tab = tab_tracker_->GetResource(handle); - *tab_hwnd = tab->tab_contents()->GetNativeView(); - } -} -#endif // defined(OS_WIN) - void AutomationProvider::GetTabProcessID(int handle, int* process_id) { *process_id = -1; @@ -2192,30 +1840,6 @@ void AutomationProvider::HandleFindWindowLocationRequest(int handle, int* x, *y = position.y(); } -void AutomationProvider::GetBookmarkBarVisibility(int handle, bool* visible, - bool* animating) { - *visible = false; - *animating = false; - -#if defined(OS_WIN) - if (browser_tracker_->ContainsHandle(handle)) { - Browser* browser = browser_tracker_->GetResource(handle); - if (browser) { - BrowserWindowTesting* testing = - browser->window()->GetBrowserWindowTesting(); - BookmarkBarView* bookmark_bar = testing->GetBookmarkBarView(); - if (bookmark_bar) { - *animating = bookmark_bar->IsAnimating(); - *visible = browser->window()->IsBookmarkBarVisible(); - } - } - } -#else - // TODO(port): Enable when bookmarks ui is ported. - NOTIMPLEMENTED(); -#endif -} - void AutomationProvider::HandleInspectElementRequest( int handle, int x, int y, IPC::Message* reply_message) { TabContents* tab_contents = GetTabContentsForHandle(handle, NULL); @@ -2356,7 +1980,7 @@ void AutomationProvider::GetWindowForBrowser(int browser_handle, } } -#if defined(OS_WIN) || defined(OS_LINUX) +#if !defined(OS_MACOSX) void AutomationProvider::GetAutocompleteEditForBrowser( int browser_handle, bool* success, @@ -2373,35 +1997,7 @@ void AutomationProvider::GetAutocompleteEditForBrowser( *success = true; } } -#endif // defined(OS_WIN) || defined(OS_LINUX) - -#if defined(OS_WIN) -// TODO(port): Remove windowsisms. -void AutomationProvider::GetBrowserForWindow(int window_handle, - bool* success, - int* browser_handle) { - *success = false; - *browser_handle = 0; - - if (window_tracker_->ContainsHandle(window_handle)) { - HWND window = window_tracker_->GetResource(window_handle); - BrowserList::const_iterator iter = BrowserList::begin(); - Browser* browser = NULL; - for (;iter != BrowserList::end(); ++iter) { - HWND hwnd = reinterpret_cast<HWND>((*iter)->window()->GetNativeHandle()); - if (window == hwnd) { - browser = *iter; - break; - } - } - if (browser) { - // Add() returns the existing handle for the resource if any. - *browser_handle = browser_tracker_->Add(browser); - *success = true; - } - } -} -#endif // defined(OS_WIN) +#endif // !defined(OS_MACOSX) void AutomationProvider::ShowInterstitialPage(int tab_handle, const std::string& html_text, @@ -2471,49 +2067,6 @@ void AutomationProvider::CloseBrowserAsync(int browser_handle) { } } -#if defined(OS_WIN) -// TODO(port): Remove windowsisms. -void AutomationProvider::CreateExternalTab( - const IPC::ExternalTabSettings& settings, - gfx::NativeWindow* tab_container_window, gfx::NativeWindow* tab_window, - int* tab_handle) { - *tab_handle = 0; - *tab_container_window = NULL; - *tab_window = NULL; - ExternalTabContainer* external_tab_container = - new ExternalTabContainer(this, automation_resource_message_filter_); - Profile* profile = settings.is_off_the_record ? - profile_->GetOffTheRecordProfile() : profile_; - external_tab_container->Init(profile, settings.parent, settings.dimensions, - settings.style, settings.load_requests_via_automation, - settings.handle_top_level_requests, NULL); - - if (AddExternalTab(external_tab_container)) { - TabContents* tab_contents = external_tab_container->tab_contents(); - *tab_handle = external_tab_container->tab_handle(); - external_tab_container->set_tab_handle(*tab_handle); - *tab_container_window = external_tab_container->GetNativeView(); - *tab_window = tab_contents->GetNativeView(); - } else { - delete external_tab_container; - } -} - -bool AutomationProvider::AddExternalTab(ExternalTabContainer* external_tab) { - DCHECK(external_tab != NULL); - - TabContents* tab_contents = external_tab->tab_contents(); - if (tab_contents) { - int tab_handle = tab_tracker_->Add(&tab_contents->controller()); - external_tab->set_tab_handle(tab_handle); - return true; - } - - return false; -} - -#endif - void AutomationProvider::NavigateInExternalTab( int handle, const GURL& url, AutomationMsg_NavigationResponseValues* status) { @@ -2538,17 +2091,6 @@ void AutomationProvider::NavigateExternalTabAtIndex( } } -#if defined(OS_WIN) -void AutomationProvider::ProcessUnhandledAccelerator( - const IPC::Message& message, int handle, const MSG& msg) { - ExternalTabContainer* external_tab = GetExternalTabForHandle(handle); - if (external_tab) { - external_tab->ProcessUnhandledAccelerator(msg); - } - // This message expects no response. -} -#endif - void AutomationProvider::WaitForTabToBeRestored(int tab_handle, IPC::Message* reply_message) { if (tab_tracker_->ContainsHandle(tab_handle)) { @@ -2558,20 +2100,6 @@ void AutomationProvider::WaitForTabToBeRestored(int tab_handle, } } -void AutomationProvider::SetInitialFocus(const IPC::Message& message, - int handle, bool reverse) { -#if defined(OS_WIN) - ExternalTabContainer* external_tab = GetExternalTabForHandle(handle); - if (external_tab) { - external_tab->FocusThroughTabTraversal(reverse); - } - // This message expects no response. -#elif defined(OS_POSIX) - // TODO(port) enable this function. - NOTIMPLEMENTED(); -#endif -} - void AutomationProvider::GetSecurityState(int handle, bool* success, SecurityStyle* security_style, int* ssl_cert_status, @@ -2661,10 +2189,9 @@ void AutomationProvider::IsPageMenuCommandEnabled(int browser_handle, } } -#if defined(OS_WIN) -// TODO(port): Enable this. void AutomationProvider::PrintNow(int tab_handle, IPC::Message* reply_message) { +#if defined(OS_WIN) NavigationController* tab = NULL; TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab); if (tab_contents) { @@ -2676,18 +2203,12 @@ void AutomationProvider::PrintNow(int tab_handle, } AutomationMsg_PrintNow::WriteReplyParams(reply_message, false); Send(reply_message); +#else + // TODO(port): Remove once DocumentPrintedNotificationObserver is implemented. + NOTIMPLEMENTED(); +#endif // defined(OS_WIN) } -void AutomationProvider::PrintAsync(int tab_handle) { - NavigationController* tab = NULL; - TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab); - if (tab_contents) { - if (tab_contents->PrintNow()) - return; - } -} -#endif - void AutomationProvider::SavePage(int tab_handle, const std::wstring& file_name, const std::wstring& dir_path, @@ -2715,7 +2236,7 @@ void AutomationProvider::SavePage(int tab_handle, *success = true; } -#if defined(OS_WIN) || defined(OS_LINUX) +#if !defined(OS_MACOSX) // TODO(port): Enable these. void AutomationProvider::GetAutocompleteEditText(int autocomplete_edit_handle, bool* success, @@ -2838,7 +2359,7 @@ bool AutomationProvider::InterceptBrowserEventMessageFromExternalHost( return true; } -#endif // defined(OS_WIN) || defined(OS_LINUX) +#endif // !defined(OS_MACOSX) TabContents* AutomationProvider::GetTabContentsForHandle( int handle, NavigationController** tab) { @@ -2851,18 +2372,6 @@ TabContents* AutomationProvider::GetTabContentsForHandle( return NULL; } -#if defined(OS_WIN) -ExternalTabContainer* AutomationProvider::GetExternalTabForHandle(int handle) { - if (tab_tracker_->ContainsHandle(handle)) { - NavigationController* tab = tab_tracker_->GetResource(handle); - return ExternalTabContainer::GetContainerForTab( - tab->tab_contents()->GetNativeView()); - } - - return NULL; -} -#endif // defined(OS_WIN) - TestingAutomationProvider::TestingAutomationProvider(Profile* profile) : AutomationProvider(profile) { BrowserList::AddObserver(this); @@ -3062,58 +2571,6 @@ void AutomationProvider::SetEnableExtensionAutomation(bool automation_enabled) { AutomationExtensionFunction::SetEnabled(automation_enabled); } -#if defined(OS_WIN) -// TODO(port): Reposition_Params is win-specific. We'll need to port it. -void AutomationProvider::OnTabReposition( - int tab_handle, const IPC::Reposition_Params& params) { - if (!tab_tracker_->ContainsHandle(tab_handle)) - return; - - if (!IsWindow(params.window)) - return; - - unsigned long process_id = 0; - unsigned long thread_id = 0; - - thread_id = GetWindowThreadProcessId(params.window, &process_id); - - if (thread_id != GetCurrentThreadId()) { - NOTREACHED(); - return; - } - - SetWindowPos(params.window, params.window_insert_after, params.left, - params.top, params.width, params.height, params.flags); - - if (params.set_parent) { - if (IsWindow(params.parent_window)) { - if (!SetParent(params.window, params.parent_window)) - DLOG(WARNING) << "SetParent failed. Error 0x%x" << GetLastError(); - } - } -} - -void AutomationProvider::OnForwardContextMenuCommandToChrome(int tab_handle, - int command) { - if (tab_tracker_->ContainsHandle(tab_handle)) { - NavigationController* tab = tab_tracker_->GetResource(tab_handle); - if (!tab) { - NOTREACHED(); - return; - } - - TabContents* tab_contents = tab->tab_contents(); - if (!tab_contents || !tab_contents->delegate()) { - NOTREACHED(); - return; - } - - tab_contents->delegate()->ExecuteContextMenuCommand(command); - } -} - -#endif // defined(OS_WIN) - void AutomationProvider::GetWindowTitle(int handle, string16* text) { gfx::NativeWindow window = window_tracker_->GetResource(handle); text->assign(platform_util::GetWindowTitle(window)); diff --git a/chrome/browser/automation/automation_provider_gtk.cc b/chrome/browser/automation/automation_provider_gtk.cc new file mode 100644 index 0000000..31a5c99 --- /dev/null +++ b/chrome/browser/automation/automation_provider_gtk.cc @@ -0,0 +1,62 @@ +// 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/gtk/view_id_util.h" + +void AutomationProvider::SetWindowBounds(int handle, const gfx::Rect& bounds, + bool* success) { + *success = false; + if (window_tracker_->ContainsHandle(handle)) { + GtkWindow* window = window_tracker_->GetResource(handle); + gtk_window_move(window, bounds.x(), bounds.height()); + gtk_window_resize(window, bounds.width(), bounds.height()); + *success = true; + } +} + +void AutomationProvider::SetWindowVisible(int handle, bool visible, + bool* result) { + *result = false; + if (window_tracker_->ContainsHandle(handle)) { + GtkWindow* window = window_tracker_->GetResource(handle); + if (visible) { + gtk_window_present(window); + } else { + gtk_widget_hide(GTK_WIDGET(window)); + } + *result = true; + } +} + +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); + GtkWidget* widget = ViewIDUtil::GetWidget(GTK_WIDGET(window), + static_cast<ViewID>(view_id)); + if (!widget) + return; + *success = true; + *bounds = gfx::Rect(0, 0, + widget->allocation.width, widget->allocation.height); + gint x, y; + if (screen_coordinates) { + gdk_window_get_origin(widget->window, &x, &y); + if (GTK_WIDGET_NO_WINDOW(widget)) { + x += widget->allocation.x; + y += widget->allocation.y; + } + } else { + gtk_widget_translate_coordinates(widget, GTK_WIDGET(window), + 0, 0, &x, &y); + } + bounds->set_origin(gfx::Point(x, y)); + } +} diff --git a/chrome/browser/automation/automation_provider_win.cc b/chrome/browser/automation/automation_provider_win.cc new file mode 100644 index 0000000..3319ea5 --- /dev/null +++ b/chrome/browser/automation/automation_provider_win.cc @@ -0,0 +1,478 @@ +// 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/ui_controls.h" +#include "chrome/browser/browser_window.h" +#include "chrome/browser/external_tab_container.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/views/bookmark_bar_view.h" +#include "chrome/test/automation/automation_messages.h" +#include "views/widget/root_view.h" +#include "views/widget/widget_win.h" +#include "views/window/window.h" + +// This task just adds another task to the event queue. This is useful if +// you want to ensure that any tasks added to the event queue after this one +// have already been processed by the time |task| is run. +class InvokeTaskLaterTask : public Task { + public: + explicit InvokeTaskLaterTask(Task* task) : task_(task) {} + virtual ~InvokeTaskLaterTask() {} + + virtual void Run() { + MessageLoop::current()->PostTask(FROM_HERE, task_); + } + + private: + Task* task_; + + DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask); +}; + +static void MoveMouse(const POINT& point) { + SetCursorPos(point.x, point.y); + + // Now, make sure that GetMessagePos returns the values we just set by + // simulating a mouse move. The value returned by GetMessagePos is updated + // when a mouse move event is removed from the event queue. + PostMessage(NULL, WM_MOUSEMOVE, 0, MAKELPARAM(point.x, point.y)); + MSG msg; + while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) + ; + + // Verify +#ifndef NDEBUG + DWORD pos = GetMessagePos(); + DCHECK_EQ(point.x, GET_X_LPARAM(pos)); + DCHECK_EQ(point.y, GET_Y_LPARAM(pos)); +#endif +} + +BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM l_param) { + if (hwnd == reinterpret_cast<HWND>(l_param)) { + return FALSE; + } + return TRUE; +} + +void AutomationProvider::GetActiveWindow(int* handle) { + HWND window = GetForegroundWindow(); + + // Let's make sure this window belongs to our process. + if (EnumThreadWindows(::GetCurrentThreadId(), + EnumThreadWndProc, + reinterpret_cast<LPARAM>(window))) { + // We enumerated all the windows and did not find the foreground window, + // it is not our window, ignore it. + *handle = 0; + return; + } + + *handle = window_tracker_->Add(window); +} + +void AutomationProvider::GetWindowHWND(int handle, HWND* win32_handle) { + *win32_handle = window_tracker_->GetResource(handle); +} + +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::WidgetWin::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); + } + } + } +} + +// This task enqueues a mouse event on the event loop, so that the view +// that it's being sent to can do the requisite post-processing. +class MouseEventTask : public Task { + public: + MouseEventTask(views::View* view, + views::Event::EventType type, + const gfx::Point& point, + int flags) + : view_(view), type_(type), point_(point), flags_(flags) {} + virtual ~MouseEventTask() {} + + virtual void Run() { + views::MouseEvent event(type_, point_.x(), point_.y(), flags_); + // We need to set the cursor position before we process the event because + // some code (tab dragging, for instance) queries the actual cursor location + // rather than the location of the mouse event. Note that the reason why + // the drag code moved away from using mouse event locations was because + // our conversion to screen location doesn't work well with multiple + // monitors, so this only works reliably in a single monitor setup. + gfx::Point screen_location(point_.x(), point_.y()); + view_->ConvertPointToScreen(view_, &screen_location); + MoveMouse(screen_location.ToPOINT()); + switch (type_) { + case views::Event::ET_MOUSE_PRESSED: + view_->OnMousePressed(event); + break; + + case views::Event::ET_MOUSE_DRAGGED: + view_->OnMouseDragged(event); + break; + + case views::Event::ET_MOUSE_RELEASED: + view_->OnMouseReleased(event, false); + break; + + default: + NOTREACHED(); + } + } + + private: + views::View* view_; + views::Event::EventType type_; + gfx::Point point_; + int flags_; + + DISALLOW_COPY_AND_ASSIGN(MouseEventTask); +}; + +void AutomationProvider::ScheduleMouseEvent(views::View* view, + views::Event::EventType type, + const gfx::Point& point, + int flags) { + MessageLoop::current()->PostTask(FROM_HERE, + new MouseEventTask(view, type, point, flags)); +} + +// This task sends a WindowDragResponse message with the appropriate +// routing ID to the automation proxy. This is implemented as a task so that +// we know that the mouse events (and any tasks that they spawn on the message +// loop) have been processed by the time this is sent. +class WindowDragResponseTask : public Task { + public: + WindowDragResponseTask(AutomationProvider* provider, + IPC::Message* reply_message) + : provider_(provider), reply_message_(reply_message) {} + virtual ~WindowDragResponseTask() {} + + virtual void Run() { + DCHECK(reply_message_ != NULL); + AutomationMsg_WindowDrag::WriteReplyParams(reply_message_, true); + provider_->Send(reply_message_); + } + + private: + AutomationProvider* provider_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(WindowDragResponseTask); +}; + +void AutomationProvider::WindowSimulateDrag(int handle, + std::vector<POINT> drag_path, + int flags, + bool press_escape_en_route, + IPC::Message* reply_message) { + bool succeeded = false; + if (browser_tracker_->ContainsHandle(handle) && (drag_path.size() > 1)) { + gfx::NativeWindow window = + browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); + succeeded = true; + + UINT down_message = 0; + UINT up_message = 0; + WPARAM wparam_flags = 0; + if (flags & views::Event::EF_SHIFT_DOWN) + wparam_flags |= MK_SHIFT; + if (flags & views::Event::EF_CONTROL_DOWN) + wparam_flags |= MK_CONTROL; + if (flags & views::Event::EF_LEFT_BUTTON_DOWN) { + wparam_flags |= MK_LBUTTON; + down_message = WM_LBUTTONDOWN; + up_message = WM_LBUTTONUP; + } + if (flags & views::Event::EF_MIDDLE_BUTTON_DOWN) { + wparam_flags |= MK_MBUTTON; + down_message = WM_MBUTTONDOWN; + up_message = WM_MBUTTONUP; + } + if (flags & views::Event::EF_RIGHT_BUTTON_DOWN) { + wparam_flags |= MK_RBUTTON; + down_message = WM_LBUTTONDOWN; + up_message = WM_LBUTTONUP; + } + + Browser* browser = browser_tracker_->GetResource(handle); + DCHECK(browser); + HWND top_level_hwnd = + reinterpret_cast<HWND>(browser->window()->GetNativeHandle()); + POINT temp = drag_path[0]; + MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &temp, 1); + MoveMouse(temp); + SendMessage(top_level_hwnd, down_message, wparam_flags, + MAKELPARAM(drag_path[0].x, drag_path[0].y)); + for (int i = 1; i < static_cast<int>(drag_path.size()); ++i) { + temp = drag_path[i]; + MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &temp, 1); + MoveMouse(temp); + SendMessage(top_level_hwnd, WM_MOUSEMOVE, wparam_flags, + MAKELPARAM(drag_path[i].x, drag_path[i].y)); + } + POINT end = drag_path[drag_path.size() - 1]; + MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &end, 1); + MoveMouse(end); + + if (press_escape_en_route) { + // Press Escape. + ui_controls::SendKeyPress(window, VK_ESCAPE, + ((flags & views::Event::EF_CONTROL_DOWN) + == views::Event::EF_CONTROL_DOWN), + ((flags & views::Event::EF_SHIFT_DOWN) == + views::Event::EF_SHIFT_DOWN), + ((flags & views::Event::EF_ALT_DOWN) == + views::Event::EF_ALT_DOWN)); + } + SendMessage(top_level_hwnd, up_message, wparam_flags, + MAKELPARAM(end.x, end.y)); + + MessageLoop::current()->PostTask(FROM_HERE, new InvokeTaskLaterTask( + new WindowDragResponseTask(this, reply_message))); + } else { + AutomationMsg_WindowDrag::WriteReplyParams(reply_message, true); + Send(reply_message); + } +} + +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::GetBookmarkBarVisibility(int handle, bool* visible, + bool* animating) { + *visible = false; + *animating = false; + + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + BrowserWindowTesting* testing = + browser->window()->GetBrowserWindowTesting(); + BookmarkBarView* bookmark_bar = testing->GetBookmarkBarView(); + if (bookmark_bar) { + *animating = bookmark_bar->IsAnimating(); + *visible = browser->window()->IsBookmarkBarVisible(); + } + } + } +} + +void AutomationProvider::SetWindowBounds(int handle, const gfx::Rect& bounds, + bool* success) { + *success = false; + if (window_tracker_->ContainsHandle(handle)) { + HWND hwnd = window_tracker_->GetResource(handle); + if (::MoveWindow(hwnd, bounds.x(), bounds.y(), bounds.width(), + bounds.height(), true)) { + *success = true; + } + } +} + +void AutomationProvider::SetWindowVisible(int handle, bool visible, + bool* result) { + if (window_tracker_->ContainsHandle(handle)) { + HWND hwnd = window_tracker_->GetResource(handle); + ::ShowWindow(hwnd, visible ? SW_SHOW : SW_HIDE); + *result = true; + } else { + *result = false; + } +} + +void AutomationProvider::ActivateWindow(int handle) { + if (window_tracker_->ContainsHandle(handle)) { + ::SetActiveWindow(window_tracker_->GetResource(handle)); + } +} + +void AutomationProvider::GetTabHWND(int handle, HWND* tab_hwnd) { + *tab_hwnd = NULL; + + if (tab_tracker_->ContainsHandle(handle)) { + NavigationController* tab = tab_tracker_->GetResource(handle); + *tab_hwnd = tab->tab_contents()->GetNativeView(); + } +} + +void AutomationProvider::GetBrowserForWindow(int window_handle, + bool* success, + int* browser_handle) { + *success = false; + *browser_handle = 0; + + if (window_tracker_->ContainsHandle(window_handle)) { + HWND window = window_tracker_->GetResource(window_handle); + BrowserList::const_iterator iter = BrowserList::begin(); + Browser* browser = NULL; + for (;iter != BrowserList::end(); ++iter) { + HWND hwnd = reinterpret_cast<HWND>((*iter)->window()->GetNativeHandle()); + if (window == hwnd) { + browser = *iter; + break; + } + } + if (browser) { + // Add() returns the existing handle for the resource if any. + *browser_handle = browser_tracker_->Add(browser); + *success = true; + } + } +} + +void AutomationProvider::CreateExternalTab( + const IPC::ExternalTabSettings& settings, + gfx::NativeWindow* tab_container_window, gfx::NativeWindow* tab_window, + int* tab_handle) { + *tab_handle = 0; + *tab_container_window = NULL; + *tab_window = NULL; + ExternalTabContainer* external_tab_container = + new ExternalTabContainer(this, automation_resource_message_filter_); + Profile* profile = settings.is_off_the_record ? + profile_->GetOffTheRecordProfile() : profile_; + external_tab_container->Init(profile, settings.parent, settings.dimensions, + settings.style, settings.load_requests_via_automation, + settings.handle_top_level_requests, NULL); + + if (AddExternalTab(external_tab_container)) { + TabContents* tab_contents = external_tab_container->tab_contents(); + *tab_handle = external_tab_container->tab_handle(); + external_tab_container->set_tab_handle(*tab_handle); + *tab_container_window = external_tab_container->GetNativeView(); + *tab_window = tab_contents->GetNativeView(); + } else { + delete external_tab_container; + } +} + +bool AutomationProvider::AddExternalTab(ExternalTabContainer* external_tab) { + DCHECK(external_tab != NULL); + + TabContents* tab_contents = external_tab->tab_contents(); + if (tab_contents) { + int tab_handle = tab_tracker_->Add(&tab_contents->controller()); + external_tab->set_tab_handle(tab_handle); + return true; + } + + return false; +} + +void AutomationProvider::ProcessUnhandledAccelerator( + const IPC::Message& message, int handle, const MSG& msg) { + ExternalTabContainer* external_tab = GetExternalTabForHandle(handle); + if (external_tab) { + external_tab->ProcessUnhandledAccelerator(msg); + } + // This message expects no response. +} + +void AutomationProvider::SetInitialFocus(const IPC::Message& message, + int handle, bool reverse) { + ExternalTabContainer* external_tab = GetExternalTabForHandle(handle); + if (external_tab) { + external_tab->FocusThroughTabTraversal(reverse); + } + // This message expects no response. +} + +void AutomationProvider::PrintAsync(int tab_handle) { + NavigationController* tab = NULL; + TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab); + if (tab_contents) { + if (tab_contents->PrintNow()) + return; + } +} + +ExternalTabContainer* AutomationProvider::GetExternalTabForHandle(int handle) { + if (tab_tracker_->ContainsHandle(handle)) { + NavigationController* tab = tab_tracker_->GetResource(handle); + return ExternalTabContainer::GetContainerForTab( + tab->tab_contents()->GetNativeView()); + } + + return NULL; +} + +void AutomationProvider::OnTabReposition( + int tab_handle, const IPC::Reposition_Params& params) { + if (!tab_tracker_->ContainsHandle(tab_handle)) + return; + + if (!IsWindow(params.window)) + return; + + unsigned long process_id = 0; + unsigned long thread_id = 0; + + thread_id = GetWindowThreadProcessId(params.window, &process_id); + + if (thread_id != GetCurrentThreadId()) { + NOTREACHED(); + return; + } + + SetWindowPos(params.window, params.window_insert_after, params.left, + params.top, params.width, params.height, params.flags); + + if (params.set_parent) { + if (IsWindow(params.parent_window)) { + if (!SetParent(params.window, params.parent_window)) + DLOG(WARNING) << "SetParent failed. Error 0x%x" << GetLastError(); + } + } +} + +void AutomationProvider::OnForwardContextMenuCommandToChrome(int tab_handle, + int command) { + if (tab_tracker_->ContainsHandle(tab_handle)) { + NavigationController* tab = tab_tracker_->GetResource(tab_handle); + if (!tab) { + NOTREACHED(); + return; + } + + TabContents* tab_contents = tab->tab_contents(); + if (!tab_contents || !tab_contents->delegate()) { + NOTREACHED(); + return; + } + + tab_contents->delegate()->ExecuteContextMenuCommand(command); + } +} diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 9c5cd98..52fe57b 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -689,6 +689,8 @@ 'browser/automation/automation_extension_function.cc', 'browser/automation/automation_profile_impl.cc', 'browser/automation/automation_profile_impl.h', + 'browser/automation/automation_provider_gtk.cc', + 'browser/automation/automation_provider_win.cc', 'browser/automation/automation_provider.cc', 'browser/automation/automation_provider.h', 'browser/automation/automation_provider_list.cc', diff --git a/chrome/common/temp_scaffolding_stubs.cc b/chrome/common/temp_scaffolding_stubs.cc index 565bf02..08222c4 100644 --- a/chrome/common/temp_scaffolding_stubs.cc +++ b/chrome/common/temp_scaffolding_stubs.cc @@ -41,9 +41,6 @@ class TabContents; #if defined(OS_MACOSX) void AutomationProvider::GetActiveWindow(int* handle) { NOTIMPLEMENTED(); } -#endif - -void AutomationProvider::ActivateWindow(int handle) { NOTIMPLEMENTED(); } void AutomationProvider::SetWindowVisible(int handle, bool visible, bool* result) { NOTIMPLEMENTED(); } @@ -53,12 +50,6 @@ void AutomationProvider::SetWindowBounds(int handle, const gfx::Rect& bounds, NOTIMPLEMENTED(); } - -void AutomationProvider::GetFocusedViewID(int handle, int* view_id) { - NOTIMPLEMENTED(); -} - -#if defined(OS_MACOSX) void AutomationProvider::GetAutocompleteEditForBrowser( int browser_handle, bool* success, @@ -66,25 +57,7 @@ void AutomationProvider::GetAutocompleteEditForBrowser( *success = false; NOTIMPLEMENTED(); } -#endif -void AutomationProvider::GetBrowserForWindow(int window_handle, - bool* success, - int* browser_handle) { - *success = false; - NOTIMPLEMENTED(); -} - -void AutomationProvider::PrintNow(int tab_handle, - IPC::Message* reply_message) { - NOTIMPLEMENTED(); -} - -void AutomationProvider::PrintAsync(int tab_handle) { - NOTIMPLEMENTED(); -} - -#if defined(OS_MACOSX) void AutomationProvider::GetAutocompleteEditText(int autocomplete_edit_handle, bool* success, std::wstring* text) { @@ -120,8 +93,46 @@ void AutomationProvider::OnMessageFromExternalHost( const std::string& target) { NOTIMPLEMENTED(); } + +void AutomationProvider::WindowGetViewBounds(int handle, int view_id, + bool screen_coordinates, + bool* success, + gfx::Rect* bounds) { + *success = false; + NOTIMPLEMENTED(); +} + #endif // defined(OS_MACOSX) +void AutomationProvider::ActivateWindow(int handle) { NOTIMPLEMENTED(); } + +void AutomationProvider::GetFocusedViewID(int handle, int* view_id) { + NOTIMPLEMENTED(); +} + +void AutomationProvider::GetBrowserForWindow(int window_handle, + bool* success, + int* browser_handle) { + *success = false; + NOTIMPLEMENTED(); +} + +void AutomationProvider::PrintAsync(int tab_handle) { + NOTIMPLEMENTED(); +} + +void AutomationProvider::SetInitialFocus(const IPC::Message& message, + int handle, bool reverse) { + NOTIMPLEMENTED(); +} + +void AutomationProvider::GetBookmarkBarVisibility(int handle, bool* visible, + bool* animating) { + *visible = false; + *animating = false; + NOTIMPLEMENTED(); +} + //-------------------------------------------------------------------------- |