1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/automation/automation_provider.h"
8 #include "base/callback.h"
9 #include "base/debug/trace_event.h"
10 #include "base/json/json_reader.h"
11 #include "base/run_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/automation/automation_browser_tracker.h"
14 #include "chrome/browser/automation/automation_tab_tracker.h"
15 #include "chrome/browser/automation/automation_window_tracker.h"
16 #include "chrome/browser/external_tab/external_tab_container.h"
17 #include "chrome/browser/printing/print_view_manager.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/sessions/session_tab_helper.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/common/automation_messages.h"
23 #include "chrome/common/render_messages.h"
24 #include "content/public/browser/navigation_controller.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/common/page_zoom.h"
28 #include "ui/events/keycodes/keyboard_codes.h"
29 #include "ui/views/focus/accelerator_handler.h"
30 #include "ui/views/widget/root_view.h"
32 using content::NavigationController;
33 using content::RenderViewHost;
34 using content::WebContents;
36 void AutomationProvider::CreateExternalTab(
37 const ExternalTabSettings& settings,
38 HWND* tab_container_window,
42 TRACE_EVENT_BEGIN_ETW("AutomationProvider::CreateExternalTab", 0, "");
45 *tab_container_window = NULL;
48 scoped_refptr<ExternalTabContainer> external_tab_container =
49 ExternalTabContainer::Create(this, automation_resource_message_filter_);
51 Profile* profile = settings.is_incognito ?
52 profile_->GetOffTheRecordProfile() : profile_;
54 // When the ExternalTabContainer window is created we grab a reference on it
55 // which is released when the window is destroyed.
56 external_tab_container->Init(profile, settings.parent, settings.dimensions,
57 settings.style, settings.load_requests_via_automation,
58 settings.handle_top_level_requests, NULL, settings.initial_url,
59 settings.referrer, settings.infobars_enabled,
60 settings.route_all_top_level_navigations);
62 if (AddExternalTab(external_tab_container)) {
63 WebContents* web_contents = external_tab_container->GetWebContents();
64 SessionTabHelper* session_tab_helper =
65 SessionTabHelper::FromWebContents(web_contents);
66 *tab_handle = external_tab_container->GetTabHandle();
67 *tab_container_window = external_tab_container->GetExternalTabHWND();
68 *tab_window = external_tab_container->GetContentHWND();
69 *session_id = session_tab_helper->session_id().id();
71 external_tab_container->Uninitialize();
74 TRACE_EVENT_END_ETW("AutomationProvider::CreateExternalTab", 0, "");
77 bool AutomationProvider::AddExternalTab(ExternalTabContainer* external_tab) {
78 DCHECK(external_tab != NULL);
80 WebContents* web_contents = external_tab->GetWebContents();
82 int tab_handle = tab_tracker_->Add(&web_contents->GetController());
83 external_tab->SetTabHandle(tab_handle);
90 void AutomationProvider::ProcessUnhandledAccelerator(
91 const IPC::Message& message, int handle, const MSG& msg) {
92 ExternalTabContainer* external_tab = GetExternalTabForHandle(handle);
94 external_tab->ProcessUnhandledAccelerator(msg);
96 // This message expects no response.
99 void AutomationProvider::SetInitialFocus(const IPC::Message& message,
100 int handle, bool reverse,
101 bool restore_focus_to_view) {
102 ExternalTabContainer* external_tab = GetExternalTabForHandle(handle);
104 external_tab->FocusThroughTabTraversal(reverse, restore_focus_to_view);
106 // This message expects no response.
109 void AutomationProvider::PrintAsync(int tab_handle) {
110 WebContents* web_contents = GetWebContentsForHandle(tab_handle, NULL);
114 printing::PrintViewManager* print_view_manager =
115 printing::PrintViewManager::FromWebContents(web_contents);
116 print_view_manager->PrintNow();
119 ExternalTabContainer* AutomationProvider::GetExternalTabForHandle(int handle) {
120 if (tab_tracker_->ContainsHandle(handle)) {
121 NavigationController* tab = tab_tracker_->GetResource(handle);
122 return ExternalTabContainer::GetContainerForTab(tab->GetWebContents());
128 void AutomationProvider::OnTabReposition(int tab_handle,
129 const Reposition_Params& params) {
130 if (!tab_tracker_->ContainsHandle(tab_handle))
133 if (!IsWindow(params.window))
136 unsigned long process_id = 0;
137 unsigned long thread_id = 0;
139 thread_id = GetWindowThreadProcessId(params.window, &process_id);
141 if (thread_id != GetCurrentThreadId()) {
142 DCHECK_EQ(thread_id, GetCurrentThreadId());
146 SetWindowPos(params.window, params.window_insert_after, params.left,
147 params.top, params.width, params.height, params.flags);
149 if (params.set_parent) {
150 if (IsWindow(params.parent_window)) {
151 if (!SetParent(params.window, params.parent_window))
152 DLOG(WARNING) << "SetParent failed. Error 0x%x" << GetLastError();
157 void AutomationProvider::OnForwardContextMenuCommandToChrome(int tab_handle,
159 ExternalTabContainer* external_tab = GetExternalTabForHandle(tab_handle);
161 external_tab->ExecuteContextMenuCommand(command);
164 void AutomationProvider::ConnectExternalTab(uint64 cookie,
167 HWND* tab_container_window,
171 TRACE_EVENT_BEGIN_ETW("AutomationProvider::ConnectExternalTab", 0, "");
174 *tab_container_window = NULL;
178 scoped_refptr<ExternalTabContainer> external_tab_container =
179 ExternalTabContainer::RemovePendingTab(static_cast<uintptr_t>(cookie));
180 if (!external_tab_container.get()) {
185 if (allow && AddExternalTab(external_tab_container)) {
186 external_tab_container->Reinitialize(this,
187 automation_resource_message_filter_,
189 WebContents* web_contents = external_tab_container->GetWebContents();
190 SessionTabHelper* session_tab_helper =
191 SessionTabHelper::FromWebContents(web_contents);
192 *tab_handle = external_tab_container->GetTabHandle();
193 *tab_container_window = external_tab_container->GetExternalTabHWND();
194 *tab_window = external_tab_container->GetContentHWND();
195 *session_id = session_tab_helper->session_id().id();
197 external_tab_container->Uninitialize();
200 TRACE_EVENT_END_ETW("AutomationProvider::ConnectExternalTab", 0, "");
203 void AutomationProvider::OnBrowserMoved(int tab_handle) {
204 ExternalTabContainer* external_tab = GetExternalTabForHandle(tab_handle);
207 "AutomationProvider::OnBrowserMoved called with invalid tab handle.";
211 void AutomationProvider::OnMessageFromExternalHost(int handle,
212 const std::string& message,
213 const std::string& origin,
214 const std::string& target) {
215 RenderViewHost* view_host = GetViewForTab(handle);
219 view_host->Send(new ChromeViewMsg_HandleMessageFromExternalHost(
220 view_host->GetRoutingID(), message, origin, target));
223 void AutomationProvider::NavigateInExternalTab(
224 int handle, const GURL& url, const GURL& referrer,
225 AutomationMsg_NavigationResponseValues* status) {
226 *status = AUTOMATION_MSG_NAVIGATION_ERROR;
228 if (tab_tracker_->ContainsHandle(handle)) {
229 NavigationController* tab = tab_tracker_->GetResource(handle);
232 content::Referrer(referrer, WebKit::WebReferrerPolicyDefault),
233 content::PAGE_TRANSITION_TYPED, std::string());
234 *status = AUTOMATION_MSG_NAVIGATION_SUCCESS;
238 void AutomationProvider::NavigateExternalTabAtIndex(
239 int handle, int navigation_index,
240 AutomationMsg_NavigationResponseValues* status) {
241 *status = AUTOMATION_MSG_NAVIGATION_ERROR;
243 if (tab_tracker_->ContainsHandle(handle)) {
244 NavigationController* tab = tab_tracker_->GetResource(handle);
245 tab->GoToIndex(navigation_index);
246 *status = AUTOMATION_MSG_NAVIGATION_SUCCESS;
250 void AutomationProvider::OnRunUnloadHandlers(
251 int handle, IPC::Message* reply_message) {
252 ExternalTabContainer* external_tab = GetExternalTabForHandle(handle);
254 external_tab->RunUnloadHandlers(reply_message);
258 void AutomationProvider::OnSetZoomLevel(int handle, int zoom_level) {
259 if (tab_tracker_->ContainsHandle(handle)) {
260 NavigationController* tab = tab_tracker_->GetResource(handle);
261 if (tab->GetWebContents() && tab->GetWebContents()->GetRenderViewHost()) {
262 RenderViewHost* host = tab->GetWebContents()->GetRenderViewHost();
263 content::PageZoom zoom = static_cast<content::PageZoom>(zoom_level);