• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/automation/automation_provider.h"
6 
7 #include "base/bind.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"
31 
32 using content::NavigationController;
33 using content::RenderViewHost;
34 using content::WebContents;
35 
CreateExternalTab(const ExternalTabSettings & settings,HWND * tab_container_window,HWND * tab_window,int * tab_handle,int * session_id)36 void AutomationProvider::CreateExternalTab(
37     const ExternalTabSettings& settings,
38     HWND* tab_container_window,
39     HWND* tab_window,
40     int* tab_handle,
41     int* session_id) {
42   TRACE_EVENT_BEGIN_ETW("AutomationProvider::CreateExternalTab", 0, "");
43 
44   *tab_handle = 0;
45   *tab_container_window = NULL;
46   *tab_window = NULL;
47   *session_id = -1;
48   scoped_refptr<ExternalTabContainer> external_tab_container =
49       ExternalTabContainer::Create(this, automation_resource_message_filter_);
50 
51   Profile* profile = settings.is_incognito ?
52       profile_->GetOffTheRecordProfile() : profile_;
53 
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);
61 
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();
70   } else {
71     external_tab_container->Uninitialize();
72   }
73 
74   TRACE_EVENT_END_ETW("AutomationProvider::CreateExternalTab", 0, "");
75 }
76 
AddExternalTab(ExternalTabContainer * external_tab)77 bool AutomationProvider::AddExternalTab(ExternalTabContainer* external_tab) {
78   DCHECK(external_tab != NULL);
79 
80   WebContents* web_contents = external_tab->GetWebContents();
81   if (web_contents) {
82     int tab_handle = tab_tracker_->Add(&web_contents->GetController());
83     external_tab->SetTabHandle(tab_handle);
84     return true;
85   }
86 
87   return false;
88 }
89 
ProcessUnhandledAccelerator(const IPC::Message & message,int handle,const MSG & msg)90 void AutomationProvider::ProcessUnhandledAccelerator(
91     const IPC::Message& message, int handle, const MSG& msg) {
92   ExternalTabContainer* external_tab = GetExternalTabForHandle(handle);
93   if (external_tab) {
94     external_tab->ProcessUnhandledAccelerator(msg);
95   }
96   // This message expects no response.
97 }
98 
SetInitialFocus(const IPC::Message & message,int handle,bool reverse,bool restore_focus_to_view)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);
103   if (external_tab) {
104     external_tab->FocusThroughTabTraversal(reverse, restore_focus_to_view);
105   }
106   // This message expects no response.
107 }
108 
PrintAsync(int tab_handle)109 void AutomationProvider::PrintAsync(int tab_handle) {
110   WebContents* web_contents = GetWebContentsForHandle(tab_handle, NULL);
111   if (!web_contents)
112     return;
113 
114   printing::PrintViewManager* print_view_manager =
115       printing::PrintViewManager::FromWebContents(web_contents);
116   print_view_manager->PrintNow();
117 }
118 
GetExternalTabForHandle(int handle)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());
123   }
124 
125   return NULL;
126 }
127 
OnTabReposition(int tab_handle,const Reposition_Params & params)128 void AutomationProvider::OnTabReposition(int tab_handle,
129                                          const Reposition_Params& params) {
130   if (!tab_tracker_->ContainsHandle(tab_handle))
131     return;
132 
133   if (!IsWindow(params.window))
134     return;
135 
136   unsigned long process_id = 0;
137   unsigned long thread_id = 0;
138 
139   thread_id = GetWindowThreadProcessId(params.window, &process_id);
140 
141   if (thread_id != GetCurrentThreadId()) {
142     DCHECK_EQ(thread_id, GetCurrentThreadId());
143     return;
144   }
145 
146   SetWindowPos(params.window, params.window_insert_after, params.left,
147                params.top, params.width, params.height, params.flags);
148 
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();
153     }
154   }
155 }
156 
OnForwardContextMenuCommandToChrome(int tab_handle,int command)157 void AutomationProvider::OnForwardContextMenuCommandToChrome(int tab_handle,
158                                                              int command) {
159   ExternalTabContainer* external_tab = GetExternalTabForHandle(tab_handle);
160   if (external_tab)
161     external_tab->ExecuteContextMenuCommand(command);
162 }
163 
ConnectExternalTab(uint64 cookie,bool allow,HWND parent_window,HWND * tab_container_window,HWND * tab_window,int * tab_handle,int * session_id)164 void AutomationProvider::ConnectExternalTab(uint64 cookie,
165                                             bool allow,
166                                             HWND parent_window,
167                                             HWND* tab_container_window,
168                                             HWND* tab_window,
169                                             int* tab_handle,
170                                             int* session_id) {
171   TRACE_EVENT_BEGIN_ETW("AutomationProvider::ConnectExternalTab", 0, "");
172 
173   *tab_handle = 0;
174   *tab_container_window = NULL;
175   *tab_window = NULL;
176   *session_id = -1;
177 
178   scoped_refptr<ExternalTabContainer> external_tab_container =
179       ExternalTabContainer::RemovePendingTab(static_cast<uintptr_t>(cookie));
180   if (!external_tab_container.get()) {
181     NOTREACHED();
182     return;
183   }
184 
185   if (allow && AddExternalTab(external_tab_container)) {
186     external_tab_container->Reinitialize(this,
187                                          automation_resource_message_filter_,
188                                          parent_window);
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();
196   } else {
197     external_tab_container->Uninitialize();
198   }
199 
200   TRACE_EVENT_END_ETW("AutomationProvider::ConnectExternalTab", 0, "");
201 }
202 
OnBrowserMoved(int tab_handle)203 void AutomationProvider::OnBrowserMoved(int tab_handle) {
204   ExternalTabContainer* external_tab = GetExternalTabForHandle(tab_handle);
205   if (!external_tab) {
206     DLOG(WARNING) <<
207       "AutomationProvider::OnBrowserMoved called with invalid tab handle.";
208   }
209 }
210 
OnMessageFromExternalHost(int handle,const std::string & message,const std::string & origin,const std::string & target)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);
216   if (!view_host)
217     return;
218 
219   view_host->Send(new ChromeViewMsg_HandleMessageFromExternalHost(
220       view_host->GetRoutingID(), message, origin, target));
221 }
222 
NavigateInExternalTab(int handle,const GURL & url,const GURL & referrer,AutomationMsg_NavigationResponseValues * status)223 void AutomationProvider::NavigateInExternalTab(
224     int handle, const GURL& url, const GURL& referrer,
225     AutomationMsg_NavigationResponseValues* status) {
226   *status = AUTOMATION_MSG_NAVIGATION_ERROR;
227 
228   if (tab_tracker_->ContainsHandle(handle)) {
229     NavigationController* tab = tab_tracker_->GetResource(handle);
230     tab->LoadURL(
231         url,
232         content::Referrer(referrer, blink::WebReferrerPolicyDefault),
233         content::PAGE_TRANSITION_TYPED, std::string());
234     *status = AUTOMATION_MSG_NAVIGATION_SUCCESS;
235   }
236 }
237 
NavigateExternalTabAtIndex(int handle,int navigation_index,AutomationMsg_NavigationResponseValues * status)238 void AutomationProvider::NavigateExternalTabAtIndex(
239     int handle, int navigation_index,
240     AutomationMsg_NavigationResponseValues* status) {
241   *status = AUTOMATION_MSG_NAVIGATION_ERROR;
242 
243   if (tab_tracker_->ContainsHandle(handle)) {
244     NavigationController* tab = tab_tracker_->GetResource(handle);
245     tab->GoToIndex(navigation_index);
246     *status = AUTOMATION_MSG_NAVIGATION_SUCCESS;
247   }
248 }
249 
OnRunUnloadHandlers(int handle,IPC::Message * reply_message)250 void AutomationProvider::OnRunUnloadHandlers(
251     int handle, IPC::Message* reply_message) {
252   ExternalTabContainer* external_tab = GetExternalTabForHandle(handle);
253   if (external_tab) {
254     external_tab->RunUnloadHandlers(reply_message);
255   }
256 }
257 
OnSetZoomLevel(int handle,int zoom_level)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);
264       host->Zoom(zoom);
265     }
266   }
267 }
268