// Copyright (c) 2012 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 "base/bind.h" #include "base/callback.h" #include "base/debug/trace_event.h" #include "base/json/json_reader.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/automation/automation_browser_tracker.h" #include "chrome/browser/automation/automation_tab_tracker.h" #include "chrome/browser/automation/automation_window_tracker.h" #include "chrome/browser/external_tab/external_tab_container.h" #include "chrome/browser/printing/print_view_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/common/automation_messages.h" #include "chrome/common/render_messages.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/page_zoom.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/focus/accelerator_handler.h" #include "ui/views/widget/root_view.h" using content::NavigationController; using content::RenderViewHost; using content::WebContents; void AutomationProvider::CreateExternalTab( const ExternalTabSettings& settings, HWND* tab_container_window, HWND* tab_window, int* tab_handle, int* session_id) { TRACE_EVENT_BEGIN_ETW("AutomationProvider::CreateExternalTab", 0, ""); *tab_handle = 0; *tab_container_window = NULL; *tab_window = NULL; *session_id = -1; scoped_refptr external_tab_container = ExternalTabContainer::Create(this, automation_resource_message_filter_); Profile* profile = settings.is_incognito ? profile_->GetOffTheRecordProfile() : profile_; // When the ExternalTabContainer window is created we grab a reference on it // which is released when the window is destroyed. external_tab_container->Init(profile, settings.parent, settings.dimensions, settings.style, settings.load_requests_via_automation, settings.handle_top_level_requests, NULL, settings.initial_url, settings.referrer, settings.infobars_enabled, settings.route_all_top_level_navigations); if (AddExternalTab(external_tab_container)) { WebContents* web_contents = external_tab_container->GetWebContents(); SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(web_contents); *tab_handle = external_tab_container->GetTabHandle(); *tab_container_window = external_tab_container->GetExternalTabHWND(); *tab_window = external_tab_container->GetContentHWND(); *session_id = session_tab_helper->session_id().id(); } else { external_tab_container->Uninitialize(); } TRACE_EVENT_END_ETW("AutomationProvider::CreateExternalTab", 0, ""); } bool AutomationProvider::AddExternalTab(ExternalTabContainer* external_tab) { DCHECK(external_tab != NULL); WebContents* web_contents = external_tab->GetWebContents(); if (web_contents) { int tab_handle = tab_tracker_->Add(&web_contents->GetController()); external_tab->SetTabHandle(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, bool restore_focus_to_view) { ExternalTabContainer* external_tab = GetExternalTabForHandle(handle); if (external_tab) { external_tab->FocusThroughTabTraversal(reverse, restore_focus_to_view); } // This message expects no response. } void AutomationProvider::PrintAsync(int tab_handle) { WebContents* web_contents = GetWebContentsForHandle(tab_handle, NULL); if (!web_contents) return; printing::PrintViewManager* print_view_manager = printing::PrintViewManager::FromWebContents(web_contents); print_view_manager->PrintNow(); } ExternalTabContainer* AutomationProvider::GetExternalTabForHandle(int handle) { if (tab_tracker_->ContainsHandle(handle)) { NavigationController* tab = tab_tracker_->GetResource(handle); return ExternalTabContainer::GetContainerForTab(tab->GetWebContents()); } return NULL; } void AutomationProvider::OnTabReposition(int tab_handle, const 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()) { DCHECK_EQ(thread_id, GetCurrentThreadId()); 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) { ExternalTabContainer* external_tab = GetExternalTabForHandle(tab_handle); if (external_tab) external_tab->ExecuteContextMenuCommand(command); } void AutomationProvider::ConnectExternalTab(uint64 cookie, bool allow, HWND parent_window, HWND* tab_container_window, HWND* tab_window, int* tab_handle, int* session_id) { TRACE_EVENT_BEGIN_ETW("AutomationProvider::ConnectExternalTab", 0, ""); *tab_handle = 0; *tab_container_window = NULL; *tab_window = NULL; *session_id = -1; scoped_refptr external_tab_container = ExternalTabContainer::RemovePendingTab(static_cast(cookie)); if (!external_tab_container.get()) { NOTREACHED(); return; } if (allow && AddExternalTab(external_tab_container)) { external_tab_container->Reinitialize(this, automation_resource_message_filter_, parent_window); WebContents* web_contents = external_tab_container->GetWebContents(); SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(web_contents); *tab_handle = external_tab_container->GetTabHandle(); *tab_container_window = external_tab_container->GetExternalTabHWND(); *tab_window = external_tab_container->GetContentHWND(); *session_id = session_tab_helper->session_id().id(); } else { external_tab_container->Uninitialize(); } TRACE_EVENT_END_ETW("AutomationProvider::ConnectExternalTab", 0, ""); } void AutomationProvider::OnBrowserMoved(int tab_handle) { ExternalTabContainer* external_tab = GetExternalTabForHandle(tab_handle); if (!external_tab) { DLOG(WARNING) << "AutomationProvider::OnBrowserMoved called with invalid tab handle."; } } void AutomationProvider::OnMessageFromExternalHost(int handle, const std::string& message, const std::string& origin, const std::string& target) { RenderViewHost* view_host = GetViewForTab(handle); if (!view_host) return; view_host->Send(new ChromeViewMsg_HandleMessageFromExternalHost( view_host->GetRoutingID(), message, origin, target)); } void AutomationProvider::NavigateInExternalTab( int handle, const GURL& url, const GURL& referrer, AutomationMsg_NavigationResponseValues* status) { *status = AUTOMATION_MSG_NAVIGATION_ERROR; if (tab_tracker_->ContainsHandle(handle)) { NavigationController* tab = tab_tracker_->GetResource(handle); tab->LoadURL( url, content::Referrer(referrer, blink::WebReferrerPolicyDefault), content::PAGE_TRANSITION_TYPED, std::string()); *status = AUTOMATION_MSG_NAVIGATION_SUCCESS; } } void AutomationProvider::NavigateExternalTabAtIndex( int handle, int navigation_index, AutomationMsg_NavigationResponseValues* status) { *status = AUTOMATION_MSG_NAVIGATION_ERROR; if (tab_tracker_->ContainsHandle(handle)) { NavigationController* tab = tab_tracker_->GetResource(handle); tab->GoToIndex(navigation_index); *status = AUTOMATION_MSG_NAVIGATION_SUCCESS; } } void AutomationProvider::OnRunUnloadHandlers( int handle, IPC::Message* reply_message) { ExternalTabContainer* external_tab = GetExternalTabForHandle(handle); if (external_tab) { external_tab->RunUnloadHandlers(reply_message); } } void AutomationProvider::OnSetZoomLevel(int handle, int zoom_level) { if (tab_tracker_->ContainsHandle(handle)) { NavigationController* tab = tab_tracker_->GetResource(handle); if (tab->GetWebContents() && tab->GetWebContents()->GetRenderViewHost()) { RenderViewHost* host = tab->GetWebContents()->GetRenderViewHost(); content::PageZoom zoom = static_cast(zoom_level); host->Zoom(zoom); } } }