diff options
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 54 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider.h | 5 | ||||
-rw-r--r-- | chrome/browser/external_tab_container.cc | 57 | ||||
-rw-r--r-- | chrome/browser/external_tab_container.h | 8 | ||||
-rw-r--r-- | chrome/test/automation/automation_messages_internal.h | 20 | ||||
-rw-r--r-- | chrome/test/automation/tab_proxy.cc | 8 | ||||
-rw-r--r-- | chrome/test/automation/tab_proxy.h | 3 |
7 files changed, 119 insertions, 36 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index dc1cb10..b6f8462 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -770,6 +770,8 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) { SetAcceleratorsForTab) IPC_MESSAGE_HANDLER(AutomationMsg_ProcessUnhandledAccelerator, ProcessUnhandledAccelerator) + IPC_MESSAGE_HANDLER(AutomationMsg_SetInitialFocus, + SetInitialFocus) IPC_MESSAGE_HANDLER(AutomationMsg_WaitForTabToBeRestored, WaitForTabToBeRestored) IPC_MESSAGE_HANDLER(AutomationMsg_GetSecurityState, @@ -2105,18 +2107,10 @@ void AutomationProvider::SetAcceleratorsForTab(const IPC::Message& message, HACCEL accel_table, int accel_entry_count) { bool status = false; - if (tab_tracker_->ContainsHandle(handle)) { - NavigationController* tab = tab_tracker_->GetResource(handle); - TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB); - ExternalTabContainer* external_tab_container = - ExternalTabContainer::GetContainerForTab( - tab_contents->GetContainerHWND()); - // This call is only valid on an externally hosted tab - if (external_tab_container) { - external_tab_container->SetAccelerators(accel_table, - accel_entry_count); - status = true; - } + ExternalTabContainer* external_tab = GetExternalTabForHandle(handle); + if (external_tab) { + external_tab->SetAccelerators(accel_table, accel_entry_count); + status = true; } Send(new AutomationMsg_SetAcceleratorsForTabResponse(message.routing_id(), status)); @@ -2124,16 +2118,18 @@ void AutomationProvider::SetAcceleratorsForTab(const IPC::Message& message, void AutomationProvider::ProcessUnhandledAccelerator( const IPC::Message& message, int handle, const MSG& msg) { - if (tab_tracker_->ContainsHandle(handle)) { - NavigationController* tab = tab_tracker_->GetResource(handle); - TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB); - ExternalTabContainer* external_tab_container = - ExternalTabContainer::GetContainerForTab( - tab_contents->GetContainerHWND()); - // This call is only valid on an externally hosted tab - if (external_tab_container) { - external_tab_container->ProcessUnhandledAccelerator(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->SetInitialFocus(reverse); } // This message expects no response. } @@ -2391,6 +2387,20 @@ WebContents* AutomationProvider::GetWebContentsForHandle( return web_contents; } +ExternalTabContainer* AutomationProvider::GetExternalTabForHandle(int handle) { + if (tab_tracker_->ContainsHandle(handle)) { + NavigationController* tab = tab_tracker_->GetResource(handle); + TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB); + DCHECK(tab_contents); + if (tab_contents) { + HWND hwnd = tab_contents->GetContainerHWND(); + return ExternalTabContainer::GetContainerForTab(hwnd); + } + } + + return NULL; +} + TestingAutomationProvider::TestingAutomationProvider(Profile* profile) : AutomationProvider(profile) { BrowserList::AddObserver(this); diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index c223d3d..a8ca47f 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -30,6 +30,7 @@ class LoginHandler; class NavigationControllerRestoredObserver; +class ExternalTabContainer; class AutomationProvider : public base::RefCounted<AutomationProvider>, public IPC::Channel::Listener, @@ -248,6 +249,8 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, void ProcessUnhandledAccelerator(const IPC::Message& message, int handle, const MSG& msg); + void SetInitialFocus(const IPC::Message& message, int handle, bool reverse); + // See comment in AutomationMsg_WaitForTabToBeRestored. void WaitForTabToBeRestored(const IPC::Message& message, int tab_handle); @@ -370,6 +373,8 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, // is not of the WebContents type. WebContents* GetWebContentsForHandle(int handle, NavigationController** tab); + ExternalTabContainer* GetExternalTabForHandle(int handle); + // Callback for history redirect queries. virtual void OnRedirectQueryComplete( HistoryService::Handle request_handle, diff --git a/chrome/browser/external_tab_container.cc b/chrome/browser/external_tab_container.cc index e80a01b..6e1d58e 100644 --- a/chrome/browser/external_tab_container.cc +++ b/chrome/browser/external_tab_container.cc @@ -74,12 +74,22 @@ bool ExternalTabContainer::Init(Profile* profile, HWND parent, // Create a TabContentsContainerView to handle focus cycling using Tab and // Shift-Tab. - // TODO(sanjeevr): We need to create a dummy FocusTraversable object to - // represent the frame of the external host. This will allow Tab and - // Shift-Tab to cycle into the external frame. tab_contents_container_ = new TabContentsContainerView(); root_view_.AddChildView(tab_contents_container_); + // Note that SetTabContents must be called after AddChildView is called tab_contents_container_->SetTabContents(tab_contents_); + // Add a dummy view to catch when the user tabs out of the tab + // Create a dummy FocusTraversable object to represent the frame of the + // external host. This will allow Tab and Shift-Tab to cycle into the + // external frame. When the tab_contents_container_ loses focus, + // the focus will be moved to this class (See OnSetFocus in this file). + // An alternative to using views::View and catching when the focus manager + // shifts the focus to the dummy view could be to implement our own view + // and handle AboutToRequestFocusFromTabTraversal. + views::View* dummy = new views::View(); + dummy->SetFocusable(true); + DCHECK(dummy->IsFocusable()); + root_view_.AddChildView(dummy); NavigationController* controller = tab_contents_->controller(); DCHECK(controller); @@ -104,7 +114,7 @@ bool ExternalTabContainer::Init(Profile* profile, HWND parent, } void ExternalTabContainer::OnDestroy() { - views::FocusManager * focus_manager = + views::FocusManager* focus_manager = views::FocusManager::GetFocusManager(GetHWND()); if (focus_manager) { focus_manager->RemoveKeystrokeListener(this); @@ -140,9 +150,21 @@ LRESULT ExternalTabContainer::OnSize(UINT, WPARAM, LPARAM, BOOL& handled) { return 0; } -// TODO(sanjeevr): The implementation of the TabContentsDelegate interface -// needs to be fully fleshed out based on the requirements of the -// "Chrome tab in external browser" feature. +LRESULT ExternalTabContainer::OnSetFocus(UINT msg, WPARAM wp, LPARAM lp, + BOOL& handled) { + if (automation_) { + views::FocusManager* focus_manager = + views::FocusManager::GetFocusManager(GetHWND()); + DCHECK(focus_manager); + if (focus_manager) { + focus_manager->ClearFocus(); + automation_->Send(new AutomationMsg_TabbedOut(win_util::IsShiftPressed(), + false)); + } + } + + return 0; +} void ExternalTabContainer::OpenURLFromTab(TabContents* source, const GURL& url, @@ -164,10 +186,10 @@ void ExternalTabContainer::OpenURLFromTab(TabContents* source, } void ExternalTabContainer::NavigationStateChanged(const TabContents* source, - unsigned changed_flags) { + unsigned changed_flags) { if (automation_) { automation_->Send( - new AutomationMsg_NavigationStateChanged(0,changed_flags)); + new AutomationMsg_NavigationStateChanged(0, changed_flags)); } } @@ -190,14 +212,16 @@ void ExternalTabContainer::LoadingStateChanged(TabContents* source) { void ExternalTabContainer::CloseContents(TabContents* source) { } -void ExternalTabContainer::MoveContents(TabContents* source, const gfx::Rect& pos) { +void ExternalTabContainer::MoveContents(TabContents* source, + const gfx::Rect& pos) { } bool ExternalTabContainer::IsPopup(TabContents* source) { return false; } -void ExternalTabContainer::URLStarredChanged(TabContents* source, bool starred) { +void ExternalTabContainer::URLStarredChanged(TabContents* source, + bool starred) { } void ExternalTabContainer::UpdateTargetURL(TabContents* source, @@ -213,7 +237,7 @@ void ExternalTabContainer::ContentsZoomChange(bool zoom_in) { } void ExternalTabContainer::ToolbarSizeChanged(TabContents* source, - bool finished) { + bool finished) { } void ExternalTabContainer::ForwardMessageToExternalHost( @@ -281,7 +305,7 @@ bool ExternalTabContainer::IsActive() { } bool ExternalTabContainer::ProcessKeyDown(HWND window, UINT message, - WPARAM wparam, LPARAM lparam) { + WPARAM wparam, LPARAM lparam) { if (!automation_) { return false; } @@ -324,6 +348,13 @@ void ExternalTabContainer::ProcessUnhandledAccelerator(const MSG& msg) { DispatchMessage(&msg); } +void ExternalTabContainer::SetInitialFocus(bool reverse) { + DCHECK(tab_contents_); + if (tab_contents_) { + tab_contents_->SetInitialFocus(reverse); + } +} + // static bool ExternalTabContainer::IsExternalTabContainer(HWND window) { std::wstring class_name = win_util::GetClassName(window); diff --git a/chrome/browser/external_tab_container.h b/chrome/browser/external_tab_container.h index b09f032..29c0d81 100644 --- a/chrome/browser/external_tab_container.h +++ b/chrome/browser/external_tab_container.h @@ -39,6 +39,7 @@ class ExternalTabContainer : public TabContentsDelegate, public: BEGIN_MSG_MAP(ExternalTabContainer) MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) MSG_WM_DESTROY(OnDestroy) END_MSG_MAP() @@ -114,6 +115,9 @@ class ExternalTabContainer : public TabContentsDelegate, // message it did not process void ProcessUnhandledAccelerator(const MSG& msg); + // See TabContents::SetInitialFocus + void SetInitialFocus(bool reverse); + // A helper method that tests whether the given window is an // ExternalTabContainer window static bool IsExternalTabContainer(HWND window); @@ -124,11 +128,13 @@ class ExternalTabContainer : public TabContentsDelegate, protected: LRESULT OnSize(UINT, WPARAM, LPARAM, BOOL& handled); + LRESULT OnSetFocus(UINT msg, WPARAM wp, LPARAM lp, BOOL& handled); + void OnDestroy(); void OnFinalMessage(HWND window); protected: - TabContents *tab_contents_; + TabContents* tab_contents_; AutomationProvider* automation_; NotificationRegistrar registrar_; diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h index 09c8390..9b31477 100644 --- a/chrome/test/automation/automation_messages_internal.h +++ b/chrome/test/automation/automation_messages_internal.h @@ -553,6 +553,26 @@ IPC_BEGIN_MESSAGES(Automation) IPC_MESSAGE_ROUTED2(AutomationMsg_ProcessUnhandledAccelerator, int, MSG) #endif // defined(OS_WIN) + // Sent by the external tab to the host to notify that the user has tabbed + // out of the tab. + // Request: + // - bool: |reverse| set to true when shift-tabbing out of the tab, false + // otherwise. + // Response: + // None expected + IPC_MESSAGE_ROUTED1(AutomationMsg_TabbedOut, bool) + + // Sent by the external tab host to ask focus to be set to either the first + // or last element on the page. + // Request: + // - int: handle of the tab + // - bool: |reverse| + // true: Focus will be set to the last focusable element + // false: Focus will be set to the first focusable element + // Response: + // None expected + IPC_MESSAGE_ROUTED2(AutomationMsg_SetInitialFocus, int, bool) + // This message is an outgoing message from Chrome to an external host. // It is a request to open a url // Request: diff --git a/chrome/test/automation/tab_proxy.cc b/chrome/test/automation/tab_proxy.cc index 61b50cf..e0e6102 100644 --- a/chrome/test/automation/tab_proxy.cc +++ b/chrome/test/automation/tab_proxy.cc @@ -641,6 +641,14 @@ bool TabProxy::ProcessUnhandledAccelerator(const MSG& msg) { // This message expects no response } +bool TabProxy::SetInitialFocus(bool reverse) { + if (!is_valid()) + return false; + return sender_->Send( + new AutomationMsg_SetInitialFocus(0, handle_, reverse)); + // This message expects no response +} + bool TabProxy::WaitForTabToBeRestored(uint32 timeout_ms) { if (!is_valid()) return false; diff --git a/chrome/test/automation/tab_proxy.h b/chrome/test/automation/tab_proxy.h index 932f5c7..f9a8339 100644 --- a/chrome/test/automation/tab_proxy.h +++ b/chrome/test/automation/tab_proxy.h @@ -219,6 +219,9 @@ class TabProxy : public AutomationResourceProxy { // to handle the keys bool ProcessUnhandledAccelerator(const MSG& msg); + // Ask the tab to set focus to either the first or last element on the page. + bool SetInitialFocus(bool reverse); + // Waits for the tab to finish being restored. Returns true on success. // timeout_ms gives the max amount of time to wait for restore to complete. bool WaitForTabToBeRestored(uint32 timeout_ms); |