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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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