Only sync parent directory once after a leveldb file rename.
[chromium-blink-merge.git] / chrome_frame / chrome_frame_automation.h
blob150a778341c1874619db1d647fd4472966e2826c
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.
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 <map>
11 #include <string>
12 #include <vector>
14 #include "base/containers/stack_container.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_handle.h"
17 #include "base/synchronization/lock.h"
18 #include "base/threading/thread.h"
19 #include "base/timer.h"
20 #include "chrome/test/automation/automation_proxy.h"
21 #include "chrome/test/automation/tab_proxy.h"
22 #include "chrome_frame/chrome_frame_delegate.h"
23 #include "chrome_frame/plugin_url_request.h"
24 #include "chrome_frame/sync_msg_reply_dispatcher.h"
25 #include "content/public/common/page_zoom.h"
27 // By a convoluated route, this timeout also winds up being the sync automation
28 // message timeout. See the ChromeFrameAutomationProxyImpl ctor and the
29 // AutomationProxy ctor for details.
30 const unsigned long kCommandExecutionTimeout = 60000; // NOLINT, 60 seconds
32 class ProxyFactory;
33 class NavigationConstraints;
34 enum AutomationPageFontSize;
36 struct DECLSPEC_NOVTABLE ChromeFrameAutomationProxy { // NOLINT
37 virtual bool Send(IPC::Message* msg) = 0;
39 virtual void SendAsAsync(
40 IPC::SyncMessage* msg,
41 SyncMessageReplyDispatcher::SyncMessageCallContext* context,
42 void* key) = 0;
43 virtual void CancelAsync(void* key) = 0;
44 virtual scoped_refptr<TabProxy> CreateTabProxy(int handle) = 0;
45 virtual void ReleaseTabProxy(AutomationHandle handle) = 0;
46 virtual std::string server_version() = 0;
48 virtual void SendProxyConfig(const std::string&) = 0;
49 protected:
50 virtual ~ChromeFrameAutomationProxy() {}
53 // Forward declarations.
54 class ProxyFactory;
56 // We extend the AutomationProxy class to handle our custom
57 // IPC messages
58 class ChromeFrameAutomationProxyImpl
59 : public ChromeFrameAutomationProxy,
60 // We have to derive from automationproxy since we want access to some
61 // members (tracker_ & channel_) - simple aggregation wont work;
62 // .. and non-public inheritance is verboten.
63 public AutomationProxy {
64 public:
65 ~ChromeFrameAutomationProxyImpl();
66 virtual void SendAsAsync(
67 IPC::SyncMessage* msg,
68 SyncMessageReplyDispatcher::SyncMessageCallContext* context,
69 void* key);
71 // Called on the worker thread.
72 virtual void OnChannelError();
74 virtual void CancelAsync(void* key);
76 virtual scoped_refptr<TabProxy> CreateTabProxy(int handle);
77 virtual void ReleaseTabProxy(AutomationHandle handle);
79 virtual std::string server_version() {
80 return AutomationProxy::server_version();
83 virtual bool Send(IPC::Message* msg) {
84 return AutomationProxy::Send(msg);
87 virtual void SendProxyConfig(const std::string& p) {
88 AutomationProxy::SendProxyConfig(p);
91 protected:
92 friend class AutomationProxyCacheEntry;
93 ChromeFrameAutomationProxyImpl(AutomationProxyCacheEntry* entry,
94 std::string channel_id,
95 base::TimeDelta 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 base::FilePath& profile_path,
111 const std::wstring& profile_name,
112 const std::wstring& language,
113 bool incognito, bool widget_mode,
114 bool route_all_top_level_navigations)
115 : launch_timeout_(kCommandExecutionTimeout), url_(url),
116 referrer_(referrer), profile_path_(profile_path),
117 profile_name_(profile_name), language_(language),
118 version_check_(true), incognito_mode_(incognito),
119 is_widget_mode_(widget_mode),
120 route_all_top_level_navigations_(route_all_top_level_navigations) {
123 ~ChromeFrameLaunchParams() {
126 void set_launch_timeout(int timeout) {
127 launch_timeout_ = timeout;
130 int launch_timeout() const {
131 return launch_timeout_;
134 const GURL& url() const {
135 return url_;
138 void set_url(const GURL& url) {
139 url_ = url;
142 const GURL& referrer() const {
143 return referrer_;
146 void set_referrer(const GURL& referrer) {
147 referrer_ = referrer;
150 const base::FilePath& profile_path() const {
151 return profile_path_;
154 const std::wstring& profile_name() const {
155 return profile_name_;
158 const std::wstring& language() const {
159 return language_;
162 bool version_check() const {
163 return version_check_;
166 void set_version_check(bool check) {
167 version_check_ = check;
170 bool incognito() const {
171 return incognito_mode_;
174 bool widget_mode() const {
175 return is_widget_mode_;
178 void set_route_all_top_level_navigations(
179 bool route_all_top_level_navigations) {
180 route_all_top_level_navigations_ = route_all_top_level_navigations;
183 bool route_all_top_level_navigations() const {
184 return route_all_top_level_navigations_;
187 protected:
188 int launch_timeout_;
189 GURL url_;
190 GURL referrer_;
191 base::FilePath profile_path_;
192 std::wstring profile_name_;
193 std::wstring language_;
194 bool version_check_;
195 bool incognito_mode_;
196 bool is_widget_mode_;
197 bool route_all_top_level_navigations_;
199 private:
200 DISALLOW_COPY_AND_ASSIGN(ChromeFrameLaunchParams);
203 // Callback when chrome process launch is complete and automation handshake
204 // (Hello message) is established. All methods are invoked on the automation
205 // proxy's worker thread.
206 struct DECLSPEC_NOVTABLE LaunchDelegate { // NOLINT
207 virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy,
208 AutomationLaunchResult result) = 0;
209 virtual void AutomationServerDied() = 0;
210 }; // NOLINT
212 // Manages a cached ChromeFrameAutomationProxyImpl entry and holds
213 // reference-less pointers to LaunchDelegate(s) to be notified in case
214 // of automation server process changes.
215 class AutomationProxyCacheEntry
216 : public base::RefCounted<AutomationProxyCacheEntry> {
217 public:
218 AutomationProxyCacheEntry(ChromeFrameLaunchParams* params,
219 LaunchDelegate* delegate);
221 ~AutomationProxyCacheEntry();
223 void AddDelegate(LaunchDelegate* delegate);
224 void RemoveDelegate(LaunchDelegate* delegate, base::WaitableEvent* done,
225 bool* was_last_delegate);
227 DWORD WaitForThread(DWORD timeout) { // NOLINT
228 DCHECK(thread_.get());
229 return ::WaitForSingleObject(thread_->thread_handle().platform_handle(),
230 timeout);
233 bool IsSameProfile(const std::wstring& name) const {
234 return lstrcmpiW(name.c_str(), profile_name.c_str()) == 0;
237 base::Thread* thread() const {
238 return thread_.get();
241 MessageLoop* message_loop() const {
242 return thread_->message_loop();
245 bool IsSameThread(base::PlatformThreadId id) const {
246 return thread_->thread_id() == id;
249 ChromeFrameAutomationProxyImpl* proxy() const {
250 DCHECK(IsSameThread(base::PlatformThread::CurrentId()));
251 return proxy_.get();
254 // Called by the proxy when the automation server has unexpectedly gone away.
255 void OnChannelError();
257 protected:
258 void CreateProxy(ChromeFrameLaunchParams* params,
259 LaunchDelegate* delegate);
261 protected:
262 std::wstring profile_name;
263 scoped_ptr<base::Thread> thread_;
264 scoped_ptr<ChromeFrameAutomationProxyImpl> proxy_;
265 AutomationLaunchResult launch_result_;
266 typedef std::vector<LaunchDelegate*> LaunchDelegates;
267 LaunchDelegates launch_delegates_;
268 // Used for UMA histogram logging to measure the time for the chrome
269 // automation server to start;
270 base::TimeTicks automation_server_launch_start_time_;
273 // We must create and destroy automation proxy in a thread with a message loop.
274 // Hence thread cannot be a member of the proxy.
275 class ProxyFactory {
276 public:
277 ProxyFactory();
278 virtual ~ProxyFactory();
280 // Fetches or creates a new automation server instance.
281 // delegate may be NULL. If non-null, a pointer to the delegate will
282 // be stored for the lifetime of the automation process or until
283 // ReleaseAutomationServer is called.
284 virtual void GetAutomationServer(LaunchDelegate* delegate,
285 ChromeFrameLaunchParams* params,
286 void** automation_server_id);
287 virtual bool ReleaseAutomationServer(void* server_id,
288 LaunchDelegate* delegate);
290 private:
291 typedef base::StackVector<scoped_refptr<AutomationProxyCacheEntry>, 4> Vector;
292 Vector proxies_;
293 // Lock if we are going to call GetAutomationServer from more than one thread.
294 base::Lock lock_;
297 // Handles all automation requests initiated from the chrome frame objects.
298 // These include the chrome tab/chrome frame activex plugin objects.
299 class ChromeFrameAutomationClient
300 : public CWindowImpl<ChromeFrameAutomationClient>,
301 public TaskMarshallerThroughWindowsMessages<ChromeFrameAutomationClient>,
302 public base::RefCountedThreadSafe<ChromeFrameAutomationClient>,
303 public PluginUrlRequestDelegate,
304 public TabProxy::TabProxyDelegate,
305 public LaunchDelegate {
306 public:
307 ChromeFrameAutomationClient();
308 ~ChromeFrameAutomationClient();
310 // Called from UI thread.
311 virtual bool Initialize(ChromeFrameDelegate* chrome_frame_delegate,
312 ChromeFrameLaunchParams* chrome_launch_params);
313 void Uninitialize();
314 void NotifyAndUninitialize();
316 virtual bool InitiateNavigation(
317 const std::string& url,
318 const std::string& referrer,
319 NavigationConstraints* navigation_constraints);
321 virtual bool NavigateToIndex(int index);
322 bool ForwardMessageFromExternalHost(const std::string& message,
323 const std::string& origin,
324 const std::string& target);
325 bool SetProxySettings(const std::string& json_encoded_proxy_settings);
327 void FindInPage(const std::wstring& search_string,
328 FindInPageDirection forward,
329 FindInPageCase match_case,
330 bool find_next);
332 virtual void OnChromeFrameHostMoved();
334 TabProxy* tab() const { return tab_.get(); }
336 BEGIN_MSG_MAP(ChromeFrameAutomationClient)
337 CHAIN_MSG_MAP(
338 TaskMarshallerThroughWindowsMessages<ChromeFrameAutomationClient>)
339 END_MSG_MAP()
341 // Resizes the hosted chrome window. This is brokered to the chrome
342 // automation instance as the host browser could be running under low IL,
343 // which would cause the SetWindowPos call to fail.
344 void Resize(int width, int height, int flags);
346 // Sets the passed in window as the parent of the external tab.
347 void SetParentWindow(HWND parent_window);
349 void SendContextMenuCommandToChromeFrame(int selected_command);
351 HWND tab_window() const {
352 return tab_window_;
355 void ReleaseAutomationServer();
357 // Returns the version number of plugin dll.
358 std::wstring GetVersion() const;
360 // BitBlts the contents of the chrome window to the print dc.
361 void Print(HDC print_dc, const RECT& print_bounds);
363 // Called in full tab mode and indicates a request to chrome to print
364 // the whole tab.
365 void PrintTab();
367 void set_use_chrome_network(bool use_chrome_network) {
368 use_chrome_network_ = use_chrome_network;
371 bool use_chrome_network() const {
372 return use_chrome_network_;
375 #ifdef UNIT_TEST
376 void set_proxy_factory(ProxyFactory* factory) {
377 proxy_factory_ = factory;
379 #endif
381 void set_handle_top_level_requests(bool handle_top_level_requests) {
382 handle_top_level_requests_ = handle_top_level_requests;
385 // Url request manager set up.
386 void SetUrlFetcher(PluginUrlRequestManager* url_fetcher);
388 // Attaches an existing external tab to this automation client instance.
389 void AttachExternalTab(uint64 external_tab_cookie);
390 void BlockExternalTab(uint64 cookie);
392 void SetPageFontSize(enum AutomationPageFontSize);
394 // For IDeleteBrowsingHistorySupport
395 void RemoveBrowsingData(int remove_mask);
397 // Sets the current zoom level on the tab.
398 void SetZoomLevel(content::PageZoom zoom_level);
400 // Fires before unload and unload handlers on the page if any. Allows the
401 // the website to put up a confirmation dialog on unload.
402 void OnUnload(bool* should_unload);
404 protected:
405 // ChromeFrameAutomationProxy::LaunchDelegate implementation.
406 virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy,
407 AutomationLaunchResult result);
408 virtual void AutomationServerDied();
410 // TabProxyDelegate implementation
411 virtual bool OnMessageReceived(TabProxy* tab, const IPC::Message& msg);
412 virtual void OnChannelError(TabProxy* tab);
414 void CreateExternalTab();
415 AutomationLaunchResult CreateExternalTabComplete(HWND chrome_window,
416 HWND tab_window,
417 int tab_handle,
418 int session_id);
419 // Called in UI thread. Here we fire event to the client notifying for
420 // the result of Initialize() method call.
421 void InitializeComplete(AutomationLaunchResult result);
423 virtual void OnFinalMessage(HWND wnd) {
424 Release();
427 scoped_refptr<ChromeFrameLaunchParams> launch_params() {
428 return chrome_launch_params_;
431 private:
432 void OnMessageReceivedUIThread(const IPC::Message& msg);
433 void OnChannelErrorUIThread();
435 HWND chrome_window() const { return chrome_window_; }
436 void BeginNavigate();
437 void BeginNavigateCompleted(AutomationMsg_NavigationResponseValues result);
439 // Helpers
440 void ReportNavigationError(AutomationMsg_NavigationResponseValues error_code,
441 const std::string& url);
443 bool ProcessUrlRequestMessage(TabProxy* tab, const IPC::Message& msg,
444 bool ui_thread);
446 // PluginUrlRequestDelegate implementation. Simply adds tab's handle
447 // as parameter and forwards to Chrome via IPC.
448 virtual void OnResponseStarted(
449 int request_id, const char* mime_type, const char* headers, int size,
450 base::Time last_modified, const std::string& redirect_url,
451 int redirect_status, const net::HostPortPair& socket_address,
452 uint64 upload_size);
453 virtual void OnReadComplete(int request_id, const std::string& data);
454 virtual void OnResponseEnd(int request_id,
455 const net::URLRequestStatus& status);
456 virtual void OnCookiesRetrieved(bool success, const GURL& url,
457 const std::string& cookie_string, int cookie_id);
459 bool is_initialized() const {
460 return init_state_ == INITIALIZED;
463 HWND parent_window_;
464 base::PlatformThreadId ui_thread_id_;
466 void* automation_server_id_;
467 ChromeFrameAutomationProxy* automation_server_;
469 HWND chrome_window_;
470 scoped_refptr<TabProxy> tab_;
471 ChromeFrameDelegate* chrome_frame_delegate_;
473 // Handle to the underlying chrome window. This is a child of the external
474 // tab window.
475 HWND tab_window_;
477 // Keeps track of the version of Chrome we're talking to.
478 std::string automation_server_version_;
480 typedef enum InitializationState {
481 UNINITIALIZED = 0,
482 INITIALIZING,
483 INITIALIZED,
484 UNINITIALIZING,
487 InitializationState init_state_;
488 bool use_chrome_network_;
489 bool handle_top_level_requests_;
490 ProxyFactory* proxy_factory_;
491 int tab_handle_;
492 // The SessionId used by Chrome as the id in the Javascript Tab object.
493 int session_id_;
494 // Only used if we attach to an existing tab.
495 uint64 external_tab_cookie_;
497 // Set to true if we received a navigation request prior to the automation
498 // server being initialized.
499 bool navigate_after_initialization_;
501 scoped_refptr<ChromeFrameLaunchParams> chrome_launch_params_;
503 // Cache security manager for URL zone checking
504 base::win::ScopedComPtr<IInternetSecurityManager> security_manager_;
506 // When host network stack is used, this object is in charge of
507 // handling network requests.
508 PluginUrlRequestManager* url_fetcher_;
509 PluginUrlRequestManager::ThreadSafeFlags url_fetcher_flags_;
511 // set to true if the host needs to get notified of all top level navigations
512 // in this page. This typically applies to hosts which would render the new
513 // page without chrome frame. Defaults to false.
514 bool route_all_top_level_navigations_;
516 friend class BeginNavigateContext;
517 friend class CreateExternalTabContext;
520 #endif // CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_