WebKit Roll 70305:70328.
[chromium-blink-merge.git] / chrome_frame / chrome_frame_automation.h
blob47b03c097a4feef5396539742feaf663ab39657c
1 // Copyright (c) 2010 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.
5 #ifndef CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_
6 #define CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_
8 #include <atlbase.h>
9 #include <atlwin.h>
10 #include <string>
11 #include <map>
12 #include <vector>
14 #include "base/lock.h"
15 #include "base/ref_counted.h"
16 #include "base/scoped_handle.h"
17 #include "base/stack_container.h"
18 #include "base/task.h"
19 #include "base/timer.h"
20 #include "base/thread.h"
21 #include "chrome/common/page_zoom.h"
22 #include "chrome/test/automation/automation_proxy.h"
23 #include "chrome/test/automation/tab_proxy.h"
24 #include "chrome_frame/chrome_frame_delegate.h"
25 #include "chrome_frame/chrome_frame_histograms.h"
26 #include "chrome_frame/plugin_url_request.h"
27 #include "chrome_frame/sync_msg_reply_dispatcher.h"
29 // By a convoluated route, this timeout also winds up being the sync automation
30 // message timeout. See the ChromeFrameAutomationProxyImpl ctor and the
31 // AutomationProxy ctor for details.
32 const unsigned long kCommandExecutionTimeout = 60000; // NOLINT, 60 seconds
34 class ProxyFactory;
35 enum AutomationPageFontSize;
37 struct DECLSPEC_NOVTABLE ChromeFrameAutomationProxy { // NOLINT
38 virtual bool Send(IPC::Message* msg) = 0;
40 virtual void SendAsAsync(
41 IPC::SyncMessage* msg,
42 SyncMessageReplyDispatcher::SyncMessageCallContext* context,
43 void* key) = 0;
44 virtual void CancelAsync(void* key) = 0;
45 virtual scoped_refptr<TabProxy> CreateTabProxy(int handle) = 0;
46 virtual void ReleaseTabProxy(AutomationHandle handle) = 0;
47 virtual std::string server_version() = 0;
49 virtual void SendProxyConfig(const std::string&) = 0;
50 protected:
51 virtual ~ChromeFrameAutomationProxy() {}
54 // Forward declarations.
55 class ProxyFactory;
57 // We extend the AutomationProxy class to handle our custom
58 // IPC messages
59 class ChromeFrameAutomationProxyImpl
60 : public ChromeFrameAutomationProxy,
61 // We have to derive from automationproxy since we want access to some
62 // members (tracker_ & channel_) - simple aggregation wont work;
63 // .. and non-public inheritance is verboten.
64 public AutomationProxy {
65 public:
66 ~ChromeFrameAutomationProxyImpl();
67 virtual void SendAsAsync(
68 IPC::SyncMessage* msg,
69 SyncMessageReplyDispatcher::SyncMessageCallContext* context,
70 void* key);
72 // Called on the worker thread.
73 virtual void OnChannelError();
75 virtual void CancelAsync(void* key);
77 virtual scoped_refptr<TabProxy> CreateTabProxy(int handle);
78 virtual void ReleaseTabProxy(AutomationHandle handle);
80 virtual std::string server_version() {
81 return AutomationProxy::server_version();
84 virtual bool Send(IPC::Message* msg) {
85 return AutomationProxy::Send(msg);
88 virtual void SendProxyConfig(const std::string& p) {
89 AutomationProxy::SendProxyConfig(p);
92 protected:
93 friend class AutomationProxyCacheEntry;
94 ChromeFrameAutomationProxyImpl(AutomationProxyCacheEntry* entry,
95 int launch_timeout);
97 class CFMsgDispatcher;
98 class TabProxyNotificationMessageFilter;
100 scoped_refptr<CFMsgDispatcher> sync_;
101 scoped_refptr<TabProxyNotificationMessageFilter> message_filter_;
102 AutomationProxyCacheEntry* proxy_entry_;
105 // This class contains information used for launching chrome.
106 class ChromeFrameLaunchParams : // NOLINT
107 public base::RefCountedThreadSafe<ChromeFrameLaunchParams> {
108 public:
109 ChromeFrameLaunchParams(const GURL& url, const GURL& referrer,
110 const FilePath& profile_path,
111 const std::wstring& profile_name,
112 const std::wstring& language,
113 const std::wstring& extra_arguments,
114 bool incognito, bool widget_mode,
115 bool route_all_top_level_navigations)
116 : launch_timeout_(kCommandExecutionTimeout), url_(url),
117 referrer_(referrer), profile_path_(profile_path),
118 profile_name_(profile_name), language_(language),
119 extra_arguments_(extra_arguments), version_check_(true),
120 incognito_mode_(incognito), is_widget_mode_(widget_mode),
121 route_all_top_level_navigations_(route_all_top_level_navigations) {
124 ~ChromeFrameLaunchParams() {
127 void set_launch_timeout(int timeout) {
128 launch_timeout_ = timeout;
131 int launch_timeout() const {
132 return launch_timeout_;
135 const GURL& url() const {
136 return url_;
139 void set_url(const GURL& url) {
140 url_ = url;
143 const GURL& referrer() const {
144 return referrer_;
147 void set_referrer(const GURL& referrer) {
148 referrer_ = referrer;
151 const FilePath& profile_path() const {
152 return profile_path_;
155 const std::wstring& profile_name() const {
156 return profile_name_;
159 const std::wstring& language() const {
160 return language_;
163 const std::wstring& extra_arguments() const {
164 return extra_arguments_;
167 bool version_check() const {
168 return version_check_;
171 void set_version_check(bool check) {
172 version_check_ = check;
175 bool incognito() const {
176 return incognito_mode_;
179 bool widget_mode() const {
180 return is_widget_mode_;
183 void set_route_all_top_level_navigations(
184 bool route_all_top_level_navigations) {
185 route_all_top_level_navigations_ = route_all_top_level_navigations;
188 bool route_all_top_level_navigations() const {
189 return route_all_top_level_navigations_;
192 protected:
193 int launch_timeout_;
194 GURL url_;
195 GURL referrer_;
196 FilePath profile_path_;
197 std::wstring profile_name_;
198 std::wstring language_;
199 std::wstring extra_arguments_;
200 bool version_check_;
201 bool incognito_mode_;
202 bool is_widget_mode_;
203 bool route_all_top_level_navigations_;
205 private:
206 DISALLOW_COPY_AND_ASSIGN(ChromeFrameLaunchParams);
209 // Callback when chrome process launch is complete and automation handshake
210 // (Hello message) is established.
211 struct DECLSPEC_NOVTABLE LaunchDelegate { // NOLINT
212 virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy,
213 AutomationLaunchResult result) = 0;
214 virtual void AutomationServerDied() = 0;
215 }; // NOLINT
217 // Manages a cached ChromeFrameAutomationProxyImpl entry and holds
218 // reference-less pointers to LaunchDelegate(s) to be notified in case
219 // of automation server process changes.
220 class AutomationProxyCacheEntry
221 : public base::RefCounted<AutomationProxyCacheEntry> {
222 public:
223 AutomationProxyCacheEntry(ChromeFrameLaunchParams* params,
224 LaunchDelegate* delegate);
226 ~AutomationProxyCacheEntry();
228 void AddDelegate(LaunchDelegate* delegate);
229 void RemoveDelegate(LaunchDelegate* delegate, base::WaitableEvent* done,
230 bool* was_last_delegate);
232 void StartSendUmaInterval(ChromeFrameHistogramSnapshots* snapshots,
233 int send_interval);
235 DWORD WaitForThread(DWORD timeout) { // NOLINT
236 DCHECK(thread_.get());
237 return ::WaitForSingleObject(thread_->thread_handle(), timeout);
240 bool IsSameProfile(const std::wstring& name) const {
241 return lstrcmpiW(name.c_str(), profile_name.c_str()) == 0;
244 base::Thread* thread() const {
245 return thread_.get();
248 MessageLoop* message_loop() const {
249 return thread_->message_loop();
252 bool IsSameThread(PlatformThreadId id) const {
253 return thread_->thread_id() == id;
256 ChromeFrameAutomationProxyImpl* proxy() const {
257 DCHECK(IsSameThread(PlatformThread::CurrentId()));
258 return proxy_.get();
261 // Called by the proxy when the automation server has unexpectedly gone away.
262 void OnChannelError();
264 protected:
265 void CreateProxy(ChromeFrameLaunchParams* params,
266 LaunchDelegate* delegate);
267 void SendUMAData();
269 protected:
270 std::wstring profile_name;
271 scoped_ptr<base::Thread> thread_;
272 scoped_ptr<ChromeFrameAutomationProxyImpl> proxy_;
273 AutomationLaunchResult launch_result_;
274 typedef std::vector<LaunchDelegate*> LaunchDelegates;
275 LaunchDelegates launch_delegates_;
276 // Used for UMA histogram logging to measure the time for the chrome
277 // automation server to start;
278 base::TimeTicks automation_server_launch_start_time_;
279 ChromeFrameHistogramSnapshots* snapshots_;
280 int uma_send_interval_;
283 // We must create and destroy automation proxy in a thread with a message loop.
284 // Hence thread cannot be a member of the proxy.
285 class ProxyFactory {
286 public:
287 ProxyFactory();
288 virtual ~ProxyFactory();
290 // Fetches or creates a new automation server instance.
291 // delegate may be NULL. If non-null, a pointer to the delegate will
292 // be stored for the lifetime of the automation process or until
293 // ReleaseAutomationServer is called.
294 virtual void GetAutomationServer(LaunchDelegate* delegate,
295 ChromeFrameLaunchParams* params,
296 void** automation_server_id);
297 virtual bool ReleaseAutomationServer(void* server_id,
298 LaunchDelegate* delegate);
300 private:
301 typedef StackVector<scoped_refptr<AutomationProxyCacheEntry>, 4> Vector;
302 Vector proxies_;
303 // Lock if we are going to call GetAutomationServer from more than one thread.
304 Lock lock_;
306 // Gathers histograms to be sent to Chrome.
307 ChromeFrameHistogramSnapshots chrome_frame_histograms_;
309 // Interval for sending UMA data
310 int uma_send_interval_;
313 // Handles all automation requests initiated from the chrome frame objects.
314 // These include the chrome tab/chrome frame activex/chrome frame npapi
315 // plugin objects.
316 class ChromeFrameAutomationClient
317 : public CWindowImpl<ChromeFrameAutomationClient>,
318 public TaskMarshallerThroughWindowsMessages<ChromeFrameAutomationClient>,
319 public base::RefCountedThreadSafe<ChromeFrameAutomationClient>,
320 public PluginUrlRequestDelegate,
321 public TabProxy::TabProxyDelegate,
322 public LaunchDelegate {
323 public:
324 ChromeFrameAutomationClient();
325 ~ChromeFrameAutomationClient();
327 // Called from UI thread.
328 virtual bool Initialize(ChromeFrameDelegate* chrome_frame_delegate,
329 ChromeFrameLaunchParams* chrome_launch_params);
330 void Uninitialize();
331 void NotifyAndUninitialize();
333 virtual bool InitiateNavigation(const std::string& url,
334 const std::string& referrer,
335 bool is_privileged);
336 virtual bool NavigateToIndex(int index);
337 bool ForwardMessageFromExternalHost(const std::string& message,
338 const std::string& origin,
339 const std::string& target);
340 bool SetProxySettings(const std::string& json_encoded_proxy_settings);
342 virtual void SetEnableExtensionAutomation(
343 const std::vector<std::string>& functions_enabled);
345 void FindInPage(const std::wstring& search_string,
346 FindInPageDirection forward,
347 FindInPageCase match_case,
348 bool find_next);
350 virtual void InstallExtension(const FilePath& crx_path, void* user_data);
352 virtual void LoadExpandedExtension(const FilePath& path, void* user_data);
354 // Starts a request to get the list of enabled extensions' base directories.
355 // Response comes back as ChromeFrameDelegate::OnEnabledExtensions().
356 virtual void GetEnabledExtensions(void* user_data);
358 virtual void InstallExtensionComplete(
359 const FilePath& path,
360 void* user_data,
361 AutomationMsg_ExtensionResponseValues res);
363 virtual void GetEnabledExtensionsComplete(
364 void* user_data,
365 std::vector<FilePath>* extension_directories);
367 virtual void OnChromeFrameHostMoved();
369 TabProxy* tab() const { return tab_.get(); }
371 BEGIN_MSG_MAP(ChromeFrameAutomationClient)
372 CHAIN_MSG_MAP(
373 TaskMarshallerThroughWindowsMessages<ChromeFrameAutomationClient>)
374 END_MSG_MAP()
376 // Resizes the hosted chrome window. This is brokered to the chrome
377 // automation instance as the host browser could be running under low IL,
378 // which would cause the SetWindowPos call to fail.
379 void Resize(int width, int height, int flags);
381 // Sets the passed in window as the parent of the external tab.
382 void SetParentWindow(HWND parent_window);
384 void SendContextMenuCommandToChromeFrame(int selected_command);
386 HWND tab_window() const {
387 return tab_window_;
390 void ReleaseAutomationServer();
392 // Returns the version number of plugin dll.
393 std::wstring GetVersion() const;
395 // BitBlts the contents of the chrome window to the print dc.
396 void Print(HDC print_dc, const RECT& print_bounds);
398 // Called in full tab mode and indicates a request to chrome to print
399 // the whole tab.
400 void PrintTab();
402 void set_use_chrome_network(bool use_chrome_network) {
403 use_chrome_network_ = use_chrome_network;
405 bool use_chrome_network() const {
406 return use_chrome_network_;
409 #ifdef UNIT_TEST
410 void set_proxy_factory(ProxyFactory* factory) {
411 proxy_factory_ = factory;
413 #endif
415 void set_handle_top_level_requests(bool handle_top_level_requests) {
416 handle_top_level_requests_ = handle_top_level_requests;
419 // Url request manager set up.
420 void SetUrlFetcher(PluginUrlRequestManager* url_fetcher);
422 // Called if the same instance of the ChromeFrameAutomationClient object
423 // is reused.
424 bool Reinitialize(ChromeFrameDelegate* chrome_frame_delegate,
425 PluginUrlRequestManager* url_fetcher);
427 // Attaches an existing external tab to this automation client instance.
428 void AttachExternalTab(uint64 external_tab_cookie);
429 void BlockExternalTab(uint64 cookie);
431 void SetPageFontSize(enum AutomationPageFontSize);
433 // For IDeleteBrowsingHistorySupport
434 void RemoveBrowsingData(int remove_mask);
436 // Sets the current zoom level on the tab.
437 void SetZoomLevel(PageZoom::Function zoom_level);
439 // Fires before unload and unload handlers on the page if any. Allows the
440 // the website to put up a confirmation dialog on unload.
441 void OnUnload(bool* should_unload);
443 void set_route_all_top_level_navigations(
444 bool route_all_top_level_navigations) {
445 route_all_top_level_navigations_ = route_all_top_level_navigations;
448 protected:
449 // ChromeFrameAutomationProxy::LaunchDelegate implementation.
450 virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy,
451 AutomationLaunchResult result);
452 virtual void AutomationServerDied();
454 // TabProxyDelegate implementation
455 virtual void OnMessageReceived(TabProxy* tab, const IPC::Message& msg);
456 virtual void OnChannelError(TabProxy* tab);
458 void CreateExternalTab();
459 AutomationLaunchResult CreateExternalTabComplete(HWND chrome_window,
460 HWND tab_window,
461 int tab_handle);
462 // Called in UI thread. Here we fire event to the client notifying for
463 // the result of Initialize() method call.
464 void InitializeComplete(AutomationLaunchResult result);
466 virtual void OnFinalMessage(HWND wnd) {
467 Release();
470 scoped_refptr<ChromeFrameLaunchParams> launch_params() {
471 return chrome_launch_params_;
474 private:
475 void OnMessageReceivedUIThread(const IPC::Message& msg);
476 void OnChannelErrorUIThread();
478 HWND chrome_window() const { return chrome_window_; }
479 void BeginNavigate();
480 void BeginNavigateCompleted(AutomationMsg_NavigationResponseValues result);
482 // Helpers
483 void ReportNavigationError(AutomationMsg_NavigationResponseValues error_code,
484 const std::string& url);
486 bool ProcessUrlRequestMessage(TabProxy* tab, const IPC::Message& msg,
487 bool ui_thread);
489 // PluginUrlRequestDelegate implementation. Simply adds tab's handle
490 // as parameter and forwards to Chrome via IPC.
491 virtual void OnResponseStarted(int request_id, const char* mime_type,
492 const char* headers, int size, base::Time last_modified,
493 const std::string& redirect_url, int redirect_status);
494 virtual void OnReadComplete(int request_id, const std::string& data);
495 virtual void OnResponseEnd(int request_id, const URLRequestStatus& status);
496 virtual void OnCookiesRetrieved(bool success, const GURL& url,
497 const std::string& cookie_string, int cookie_id);
499 bool is_initialized() const {
500 return init_state_ == INITIALIZED;
503 HWND parent_window_;
504 PlatformThreadId ui_thread_id_;
506 void* automation_server_id_;
507 ChromeFrameAutomationProxy* automation_server_;
509 HWND chrome_window_;
510 scoped_refptr<TabProxy> tab_;
511 ChromeFrameDelegate* chrome_frame_delegate_;
513 // Handle to the underlying chrome window. This is a child of the external
514 // tab window.
515 HWND tab_window_;
517 // Keeps track of the version of Chrome we're talking to.
518 std::string automation_server_version_;
520 typedef enum InitializationState {
521 UNINITIALIZED = 0,
522 INITIALIZING,
523 INITIALIZED,
524 UNINITIALIZING,
527 InitializationState init_state_;
528 bool use_chrome_network_;
529 bool handle_top_level_requests_;
530 ProxyFactory* proxy_factory_;
531 int tab_handle_;
532 // Only used if we attach to an existing tab.
533 uint64 external_tab_cookie_;
535 // Set to true if we received a navigation request prior to the automation
536 // server being initialized.
537 bool navigate_after_initialization_;
539 scoped_refptr<ChromeFrameLaunchParams> chrome_launch_params_;
541 // Cache security manager for URL zone checking
542 ScopedComPtr<IInternetSecurityManager> security_manager_;
544 // When host network stack is used, this object is in charge of
545 // handling network requests.
546 PluginUrlRequestManager* url_fetcher_;
547 PluginUrlRequestManager::ThreadSafeFlags url_fetcher_flags_;
549 // set to true if the host needs to get notified of all top level navigations
550 // in this page. This typically applies to hosts which would render the new
551 // page without chrome frame. Defaults to false.
552 bool route_all_top_level_navigations_;
554 friend class BeginNavigateContext;
555 friend class CreateExternalTabContext;
558 #endif // CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_