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// This implements a browser-side endpoint for UI automation activity.
6// The client-side endpoint is implemented by AutomationProxy.
7// The entire lifetime of this object should be contained within that of
8// the BrowserProcess, and in particular the NotificationService that's
9// hung off of it.
10
11#ifndef CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_H_
12#define CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_H_
13
14#include <list>
15#include <map>
16#include <string>
17#include <vector>
18
19#include "base/basictypes.h"
20#include "base/compiler_specific.h"
21#include "base/memory/scoped_ptr.h"
22#include "base/memory/weak_ptr.h"
23#include "base/observer_list.h"
24#include "base/sequenced_task_runner_helpers.h"
25#include "base/strings/string16.h"
26#include "chrome/browser/common/cancelable_request.h"
27#include "chrome/common/automation_constants.h"
28#include "chrome/common/content_settings.h"
29#include "components/autofill/core/browser/field_types.h"
30#include "content/public/browser/browser_thread.h"
31#include "content/public/browser/notification_observer.h"
32#include "ipc/ipc_channel.h"
33#include "ipc/ipc_listener.h"
34#include "ipc/ipc_sender.h"
35
36#if defined(OS_WIN) && !defined(USE_AURA)
37#include "ui/gfx/native_widget_types.h"
38#endif  // defined(OS_WIN) && !defined(USE_AURA)
39
40class AutomationBrowserTracker;
41class AutomationResourceMessageFilter;
42class AutomationTabTracker;
43class AutomationWindowTracker;
44class Browser;
45class ExternalTabContainer;
46class FindInPageNotificationObserver;
47class InitialLoadObserver;
48class LoginHandler;
49class MetricEventDurationObserver;
50class NavigationControllerRestoredObserver;
51class NewTabUILoadObserver;
52class Profile;
53struct AutomationMsg_Find_Params;
54struct Reposition_Params;
55struct ExternalTabSettings;
56
57namespace IPC {
58class ChannelProxy;
59}
60
61namespace content {
62class NavigationController;
63class RenderViewHost;
64}
65
66namespace base {
67class DictionaryValue;
68}
69
70namespace content {
71class DownloadItem;
72class WebContents;
73}
74
75namespace gfx {
76class Point;
77}
78
79class AutomationProvider
80    : public IPC::Listener,
81      public IPC::Sender,
82      public base::SupportsWeakPtr<AutomationProvider>,
83      public base::RefCountedThreadSafe<
84          AutomationProvider, content::BrowserThread::DeleteOnUIThread> {
85 public:
86  explicit AutomationProvider(Profile* profile);
87
88  Profile* profile() const { return profile_; }
89
90  void set_profile(Profile* profile);
91
92  // Initializes a channel for a connection to an AutomationProxy.
93  // If channel_id starts with kNamedInterfacePrefix, it will act
94  // as a server, create a named IPC socket with channel_id as its
95  // path, and will listen on the socket for incoming connections.
96  // If channel_id does not, it will act as a client and establish
97  // a connection on its primary IPC channel. See ipc/ipc_channel_posix.cc
98  // for more information about kPrimaryIPCChannel.
99  bool InitializeChannel(const std::string& channel_id) WARN_UNUSED_RESULT;
100
101  virtual IPC::Channel::Mode GetChannelMode(bool use_named_interface);
102
103  // Sets the number of tabs that we expect; when this number of tabs has
104  // loaded, an AutomationMsg_InitialLoadsComplete message is sent.
105  void SetExpectedTabCount(size_t expected_tabs);
106
107  // Called when the inital set of tabs has finished loading.
108  // Call SetExpectedTabCount(0) to set this to true immediately.
109  void OnInitialTabLoadsComplete();
110
111  // Called when the chromeos WebUI OOBE/Login is ready.
112  void OnOOBEWebuiReady();
113
114  // Checks all of the initial load conditions, then sends the
115  // InitialLoadsComplete message over the automation channel.
116  void SendInitialLoadMessage();
117
118  // Call this before calling InitializeChannel. If called, send the
119  // InitialLoadsComplete message immediately when the automation channel is
120  // connected, without waiting for the initial load conditions to be met.
121  void DisableInitialLoadObservers();
122
123  // Get the index of a particular NavigationController object
124  // in the given parent window.  This method uses
125  // TabStrip::GetIndexForNavigationController to get the index.
126  int GetIndexForNavigationController(
127      const content::NavigationController* controller,
128      const Browser* parent) const;
129
130  // IPC::Sender implementation.
131  virtual bool Send(IPC::Message* msg) OVERRIDE;
132
133  // IPC::Listener implementation.
134  virtual void OnChannelConnected(int pid) OVERRIDE;
135  virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
136  virtual void OnChannelError() OVERRIDE;
137
138  IPC::Message* reply_message_release() {
139    IPC::Message* reply_message = reply_message_;
140    reply_message_ = NULL;
141    return reply_message;
142  }
143
144#if defined(OS_WIN)
145  // Adds the external tab passed in to the tab tracker.
146  bool AddExternalTab(ExternalTabContainer* external_tab);
147#endif
148
149  // Get the DictionaryValue equivalent for a download item. Caller owns the
150  // DictionaryValue.
151  base::DictionaryValue* GetDictionaryFromDownloadItem(
152      const content::DownloadItem* download,
153      bool incognito);
154
155 protected:
156  friend struct content::BrowserThread::DeleteOnThread<
157      content::BrowserThread::UI>;
158  friend class base::DeleteHelper<AutomationProvider>;
159  virtual ~AutomationProvider();
160
161  // Helper function to find the browser window that contains a given
162  // NavigationController and activate that tab.
163  // Returns the Browser if found.
164  Browser* FindAndActivateTab(content::NavigationController* contents);
165
166  // Convert a tab handle into a WebContents. If |tab| is non-NULL a pointer
167  // to the tab is also returned. Returns NULL in case of failure or if the tab
168  // is not of the WebContents type.
169  content::WebContents* GetWebContentsForHandle(
170      int handle, content::NavigationController** tab);
171
172  // Returns the protocol version which typically is the module version.
173  virtual std::string GetProtocolVersion();
174
175  // Returns the associated view for the tab handle passed in.
176  // Returns NULL on failure.
177  content::RenderViewHost* GetViewForTab(int tab_handle);
178
179  // Called on IPC message deserialization failure. Prints an error message
180  // and closes the IPC channel.
181  void OnMessageDeserializationFailure();
182
183  scoped_ptr<AutomationBrowserTracker> browser_tracker_;
184  scoped_ptr<InitialLoadObserver> initial_load_observer_;
185  scoped_ptr<MetricEventDurationObserver> metric_event_duration_observer_;
186  scoped_ptr<AutomationTabTracker> tab_tracker_;
187  scoped_ptr<AutomationWindowTracker> window_tracker_;
188
189  Profile* profile_;
190
191  // A pointer to reply message used when we do asynchronous processing in the
192  // message handler.
193  // TODO(phajdan.jr): Remove |reply_message_|, it is error-prone.
194  IPC::Message* reply_message_;
195
196  // Consumer for asynchronous history queries.
197  CancelableRequestConsumer consumer_;
198
199  // Sends a find request for a given query.
200  void SendFindRequest(
201      content::WebContents* web_contents,
202      bool with_json,
203      const base::string16& search_string,
204      bool forward,
205      bool match_case,
206      bool find_next,
207      IPC::Message* reply_message);
208
209  scoped_refptr<AutomationResourceMessageFilter>
210      automation_resource_message_filter_;
211
212  // True iff we should open a new automation IPC channel if it closes.
213  bool reinitialize_on_channel_error_;
214
215 private:
216  void OnUnhandledMessage(const IPC::Message& message);
217
218  // Clear and reinitialize the automation IPC channel.
219  bool ReinitializeChannel();
220
221  void HandleUnused(const IPC::Message& message, int handle);
222  void GetFilteredInetHitCount(int* hit_count);
223  void SetProxyConfig(const std::string& new_proxy_config);
224
225  // Responds to the FindInPage request, retrieves the search query parameters,
226  // launches an observer to listen for results and issues a StartFind request.
227  void HandleFindRequest(int handle,
228                         const AutomationMsg_Find_Params& params,
229                         IPC::Message* reply_message);
230
231  void OnSetPageFontSize(int tab_handle, int font_size);
232
233  // See browsing_data_remover.h for explanation of bitmap fields.
234  void RemoveBrowsingData(int remove_mask);
235
236  // Notify the JavaScript engine in the render to change its parameters
237  // while performing stress testing. See
238  // |ViewHostMsg_JavaScriptStressTestControl_Commands| in render_messages.h
239  // for information on the arguments.
240  void JavaScriptStressTestControl(int handle, int cmd, int param);
241
242  void BeginTracing(const std::string& category_patterns, bool* success);
243  void EndTracing(IPC::Message* reply_message);
244  void OnTraceDataCollected(IPC::Message* reply_message,
245                            const base::FilePath& path);
246
247  // Asynchronous request for printing the current tab.
248  void PrintAsync(int tab_handle);
249
250  // Uses the specified encoding to override the encoding of the page in the
251  // specified tab.
252  void OverrideEncoding(int tab_handle,
253                        const std::string& encoding_name,
254                        bool* success);
255
256  // Selects all contents on the page.
257  void SelectAll(int tab_handle);
258
259  // Edit operations on the page.
260  void Cut(int tab_handle);
261  void Copy(int tab_handle);
262  void Paste(int tab_handle);
263
264  void ReloadAsync(int tab_handle);
265  void StopAsync(int tab_handle);
266  void SaveAsAsync(int tab_handle);
267
268  // Method called by the popup menu tracker when a popup menu is opened.
269  void NotifyPopupMenuOpened();
270
271#if defined(OS_WIN)
272  // The functions in this block are for use with external tabs, so they are
273  // Windows only.
274
275  // The container of an externally hosted tab calls this to reflect any
276  // accelerator keys that it did not process. This gives the tab a chance
277  // to handle the keys
278  void ProcessUnhandledAccelerator(const IPC::Message& message, int handle,
279                                   const MSG& msg);
280
281  void SetInitialFocus(const IPC::Message& message, int handle, bool reverse,
282                       bool restore_focus_to_view);
283
284  void OnTabReposition(int tab_handle,
285                       const Reposition_Params& params);
286
287  void OnForwardContextMenuCommandToChrome(int tab_handle, int command);
288
289  void CreateExternalTab(const ExternalTabSettings& settings,
290                         HWND* tab_container_window,
291                         HWND* tab_window,
292                         int* tab_handle,
293                         int* session_id);
294
295  void ConnectExternalTab(uint64 cookie,
296                          bool allow,
297                          HWND parent_window,
298                          HWND* tab_container_window,
299                          HWND* tab_window,
300                          int* tab_handle,
301                          int* session_id);
302
303  void NavigateInExternalTab(
304      int handle, const GURL& url, const GURL& referrer,
305      AutomationMsg_NavigationResponseValues* status);
306  void NavigateExternalTabAtIndex(
307      int handle, int index, AutomationMsg_NavigationResponseValues* status);
308
309  // Handler for a message sent by the automation client.
310  void OnMessageFromExternalHost(int handle, const std::string& message,
311                                 const std::string& origin,
312                                 const std::string& target);
313
314  void OnBrowserMoved(int handle);
315
316  void OnRunUnloadHandlers(int handle, IPC::Message* reply_message);
317
318  void OnSetZoomLevel(int handle, int zoom_level);
319
320  ExternalTabContainer* GetExternalTabForHandle(int handle);
321#endif  // defined(OS_WIN)
322
323  scoped_ptr<IPC::ChannelProxy> channel_;
324  scoped_ptr<NewTabUILoadObserver> new_tab_ui_load_observer_;
325  scoped_ptr<FindInPageNotificationObserver> find_in_page_observer_;
326
327  // True iff we should enable observers that check for initial load conditions.
328  bool use_initial_load_observers_;
329
330  // True iff connected to an AutomationProxy.
331  bool is_connected_;
332
333  // True iff browser finished loading initial set of tabs.
334  bool initial_tab_loads_complete_;
335
336  // True iff ChromeOS webui login ui is ready.
337  bool login_webui_ready_;
338
339  // ID of automation channel.
340  std::string channel_id_;
341
342  DISALLOW_COPY_AND_ASSIGN(AutomationProvider);
343};
344
345#endif  // CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_H_
346