Home | History | Annotate | Download | only in automation
      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/base/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, WebKit::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