1// Copyright (c) 2011 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#pragma once
14
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/string16.h"
25#include "chrome/browser/autofill/field_types.h"
26#include "chrome/common/automation_constants.h"
27#include "chrome/common/content_settings.h"
28#include "content/browser/browser_thread.h"
29#include "content/browser/cancelable_request.h"
30#include "content/browser/tab_contents/navigation_entry.h"
31#include "content/common/notification_observer.h"
32#include "ipc/ipc_channel.h"
33
34#if defined(OS_WIN)
35#include "ui/gfx/native_widget_types.h"
36#include "views/events/event.h"
37#endif  // defined(OS_WIN)
38
39class PopupMenuWaiter;
40class TabContents;
41struct AutomationMsg_Find_Params;
42struct Reposition_Params;
43struct ExternalTabSettings;
44
45namespace IPC {
46class ChannelProxy;
47}
48
49class AutofillProfile;
50class AutomationAutocompleteEditTracker;
51class AutomationBrowserTracker;
52class AutomationExtensionTracker;
53class AutomationResourceMessageFilter;
54class AutomationTabTracker;
55class AutomationWindowTracker;
56class Browser;
57class CreditCard;
58class DictionaryValue;
59class DownloadItem;
60class Extension;
61class ExtensionPortContainer;
62class ExtensionTestResultNotificationObserver;
63class ExternalTabContainer;
64class FilePath;
65class InitialLoadObserver;
66class ListValue;
67class LoginHandler;
68class MetricEventDurationObserver;
69class NavigationController;
70class NavigationControllerRestoredObserver;
71class Profile;
72class RenderViewHost;
73class TabContents;
74struct AutocompleteMatchData;
75
76namespace gfx {
77class Point;
78}
79
80class AutomationProvider
81    : public IPC::Channel::Listener,
82      public IPC::Message::Sender,
83      public base::SupportsWeakPtr<AutomationProvider>,
84      public base::RefCountedThreadSafe<AutomationProvider,
85                                        BrowserThread::DeleteOnUIThread> {
86 public:
87  explicit AutomationProvider(Profile* profile);
88
89  Profile* profile() const { return profile_; }
90
91  // Initializes a channel for a connection to an AutomationProxy.
92  // If channel_id starts with kNamedInterfacePrefix, it will act
93  // as a server, create a named IPC socket with channel_id as its
94  // path, and will listen on the socket for incoming connections.
95  // If channel_id does not, it will act as a client and establish
96  // a connection on its primary IPC channel. See ipc/ipc_channel_posix.cc
97  // for more information about kPrimaryIPCChannel.
98  bool InitializeChannel(const std::string& channel_id) WARN_UNUSED_RESULT;
99
100  // Sets the number of tabs that we expect; when this number of tabs has
101  // loaded, an AutomationMsg_InitialLoadsComplete message is sent.
102  void SetExpectedTabCount(size_t expected_tabs);
103
104  // Called when the inital set of tabs has finished loading.
105  // Call SetExpectedTabCount(0) to set this to true immediately.
106  void OnInitialTabLoadsComplete();
107
108  // Called when the ChromeOS network library has finished its first update.
109  void OnNetworkLibraryInit();
110
111  // Get the index of a particular NavigationController object
112  // in the given parent window.  This method uses
113  // TabStrip::GetIndexForNavigationController to get the index.
114  int GetIndexForNavigationController(const NavigationController* controller,
115                                      const Browser* parent) const;
116
117  // Add or remove a non-owning reference to a tab's LoginHandler.  This is for
118  // when a login prompt is shown for HTTP/FTP authentication.
119  // TODO(mpcomplete): The login handling is a fairly special purpose feature.
120  // Eventually we'll probably want ways to interact with the ChromeView of the
121  // login window in a generic manner, such that it can be used for anything,
122  // not just logins.
123  void AddLoginHandler(NavigationController* tab, LoginHandler* handler);
124  void RemoveLoginHandler(NavigationController* tab);
125
126  // IPC implementations
127  virtual bool Send(IPC::Message* msg);
128  virtual void OnChannelConnected(int pid);
129  virtual bool OnMessageReceived(const IPC::Message& msg);
130  virtual void OnChannelError();
131
132  IPC::Message* reply_message_release() {
133    IPC::Message* reply_message = reply_message_;
134    reply_message_ = NULL;
135    return reply_message;
136  }
137
138  // Adds the extension passed in to the extension tracker, and returns
139  // the associated handle. If the tracker already contains the extension,
140  // the handle is simply returned.
141  int AddExtension(const Extension* extension);
142
143#if defined(OS_WIN)
144  // Adds the external tab passed in to the tab tracker.
145  bool AddExternalTab(ExternalTabContainer* external_tab);
146#endif
147
148  // Get the DictionaryValue equivalent for a download item. Caller owns the
149  // DictionaryValue.
150  DictionaryValue* GetDictionaryFromDownloadItem(const DownloadItem* download);
151
152 protected:
153  friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
154  friend class DeleteTask<AutomationProvider>;
155  virtual ~AutomationProvider();
156
157  // Helper function to find the browser window that contains a given
158  // NavigationController and activate that tab.
159  // Returns the Browser if found.
160  Browser* FindAndActivateTab(NavigationController* contents);
161
162  // Convert a tab handle into a TabContents. If |tab| is non-NULL a pointer
163  // to the tab is also returned. Returns NULL in case of failure or if the tab
164  // is not of the TabContents type.
165  TabContents* GetTabContentsForHandle(int handle, NavigationController** tab);
166
167  // Returns the protocol version which typically is the module version.
168  virtual std::string GetProtocolVersion();
169
170  // Returns the associated view for the tab handle passed in.
171  // Returns NULL on failure.
172  RenderViewHost* GetViewForTab(int tab_handle);
173
174  // Called on IPC message deserialization failure. Prints an error message
175  // and closes the IPC channel.
176  void OnMessageDeserializationFailure();
177
178  scoped_ptr<AutomationAutocompleteEditTracker> autocomplete_edit_tracker_;
179  scoped_ptr<AutomationBrowserTracker> browser_tracker_;
180  scoped_ptr<InitialLoadObserver> initial_load_observer_;
181  scoped_ptr<MetricEventDurationObserver> metric_event_duration_observer_;
182  scoped_ptr<NavigationControllerRestoredObserver> restore_tracker_;
183  scoped_ptr<AutomationTabTracker> tab_tracker_;
184  scoped_ptr<AutomationWindowTracker> window_tracker_;
185
186  typedef std::map<NavigationController*, LoginHandler*> LoginHandlerMap;
187  LoginHandlerMap login_handler_map_;
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      TabContents* tab_contents,
202      bool with_json,
203      const 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();
217
218  // Clear and reinitialize the automation IPC channel.
219  bool ReinitializeChannel();
220
221  // IPC Message callbacks.
222  void WindowSimulateDrag(int handle,
223                          const std::vector<gfx::Point>& drag_path,
224                          int flags,
225                          bool press_escape_en_route,
226                          IPC::Message* reply_message);
227  void HandleUnused(const IPC::Message& message, int handle);
228  void SetFilteredInet(const IPC::Message& message, bool enabled);
229  void GetFilteredInetHitCount(int* hit_count);
230  void SetProxyConfig(const std::string& new_proxy_config);
231
232  // Responds to the FindInPage request, retrieves the search query parameters,
233  // launches an observer to listen for results and issues a StartFind request.
234  void HandleFindRequest(int handle,
235                         const AutomationMsg_Find_Params& params,
236                         IPC::Message* reply_message);
237
238  void OnSetPageFontSize(int tab_handle, int font_size);
239
240  // See browsing_data_remover.h for explanation of bitmap fields.
241  void RemoveBrowsingData(int remove_mask);
242
243  // Notify the JavaScript engine in the render to change its parameters
244  // while performing stress testing. See
245  // |ViewHostMsg_JavaScriptStressTestControl_Commands| in render_messages.h
246  // for information on the arguments.
247  void JavaScriptStressTestControl(int handle, int cmd, int param);
248
249  void InstallExtension(const FilePath& crx_path,
250                        IPC::Message* reply_message);
251
252  void WaitForExtensionTestResult(IPC::Message* reply_message);
253
254  void InstallExtensionAndGetHandle(const FilePath& crx_path,
255                                    bool with_ui,
256                                    IPC::Message* reply_message);
257
258  void UninstallExtension(int extension_handle,
259                          bool* success);
260
261  void ReloadExtension(int extension_handle,
262                       IPC::Message* reply_message);
263
264  void EnableExtension(int extension_handle,
265                       IPC::Message* reply_message);
266
267  void DisableExtension(int extension_handle,
268                        bool* success);
269
270  void ExecuteExtensionActionInActiveTabAsync(int extension_handle,
271                                              int browser_handle,
272                                              IPC::Message* reply_message);
273
274  void MoveExtensionBrowserAction(int extension_handle, int index,
275                                  bool* success);
276
277  void GetExtensionProperty(int extension_handle,
278                            AutomationMsg_ExtensionProperty type,
279                            bool* success,
280                            std::string* value);
281
282  // Asynchronous request for printing the current tab.
283  void PrintAsync(int tab_handle);
284
285  // Uses the specified encoding to override the encoding of the page in the
286  // specified tab.
287  void OverrideEncoding(int tab_handle,
288                        const std::string& encoding_name,
289                        bool* success);
290
291  // Selects all contents on the page.
292  void SelectAll(int tab_handle);
293
294  // Edit operations on the page.
295  void Cut(int tab_handle);
296  void Copy(int tab_handle);
297  void Paste(int tab_handle);
298
299  void ReloadAsync(int tab_handle);
300  void StopAsync(int tab_handle);
301  void SaveAsAsync(int tab_handle);
302
303  // Returns the extension for the given handle. Returns NULL if there is
304  // no extension for the handle.
305  const Extension* GetExtension(int extension_handle);
306
307  // Returns the extension for the given handle, if the handle is valid and
308  // the associated extension is enabled. Returns NULL otherwise.
309  const Extension* GetEnabledExtension(int extension_handle);
310
311  // Returns the extension for the given handle, if the handle is valid and
312  // the associated extension is disabled. Returns NULL otherwise.
313  const Extension* GetDisabledExtension(int extension_handle);
314
315  // Method called by the popup menu tracker when a popup menu is opened.
316  void NotifyPopupMenuOpened();
317
318#if defined(OS_WIN)
319  // The functions in this block are for use with external tabs, so they are
320  // Windows only.
321
322  // The container of an externally hosted tab calls this to reflect any
323  // accelerator keys that it did not process. This gives the tab a chance
324  // to handle the keys
325  void ProcessUnhandledAccelerator(const IPC::Message& message, int handle,
326                                   const MSG& msg);
327
328  void SetInitialFocus(const IPC::Message& message, int handle, bool reverse,
329                       bool restore_focus_to_view);
330
331  void OnTabReposition(int tab_handle,
332                       const Reposition_Params& params);
333
334  void OnForwardContextMenuCommandToChrome(int tab_handle, int command);
335
336  void CreateExternalTab(const ExternalTabSettings& settings,
337                         gfx::NativeWindow* tab_container_window,
338                         gfx::NativeWindow* tab_window,
339                         int* tab_handle,
340                         int* session_id);
341
342  void ConnectExternalTab(uint64 cookie,
343                          bool allow,
344                          gfx::NativeWindow parent_window,
345                          gfx::NativeWindow* tab_container_window,
346                          gfx::NativeWindow* tab_window,
347                          int* tab_handle,
348                          int* session_id);
349
350  void NavigateInExternalTab(
351      int handle, const GURL& url, const GURL& referrer,
352      AutomationMsg_NavigationResponseValues* status);
353  void NavigateExternalTabAtIndex(
354      int handle, int index, AutomationMsg_NavigationResponseValues* status);
355
356  // Handler for a message sent by the automation client.
357  void OnMessageFromExternalHost(int handle, const std::string& message,
358                                 const std::string& origin,
359                                 const std::string& target);
360
361  void OnBrowserMoved(int handle);
362
363  void OnRunUnloadHandlers(int handle, IPC::Message* reply_message);
364
365  void OnSetZoomLevel(int handle, int zoom_level);
366
367  ExternalTabContainer* GetExternalTabForHandle(int handle);
368#endif  // defined(OS_WIN)
369
370  scoped_ptr<IPC::ChannelProxy> channel_;
371  scoped_ptr<NotificationObserver> new_tab_ui_load_observer_;
372  scoped_ptr<NotificationObserver> find_in_page_observer_;
373  scoped_ptr<ExtensionTestResultNotificationObserver>
374      extension_test_result_observer_;
375  scoped_ptr<AutomationExtensionTracker> extension_tracker_;
376
377  // True iff connected to an AutomationProxy.
378  bool is_connected_;
379
380  // True iff browser finished loading initial set of tabs.
381  bool initial_tab_loads_complete_;
382
383  // True iff the Chrome OS network library finished initialization.
384  bool network_library_initialized_;
385
386  // ID of automation channel.
387  std::string channel_id_;
388
389  DISALLOW_COPY_AND_ASSIGN(AutomationProvider);
390};
391
392#endif  // CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_H_
393