| OLD | NEW |
| (Empty) |
| 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 #ifndef CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_ | |
| 6 #define CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_ | |
| 7 | |
| 8 #include <atlbase.h> | |
| 9 #include <atlwin.h> | |
| 10 #include <map> | |
| 11 #include <string> | |
| 12 #include <vector> | |
| 13 | |
| 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/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" | |
| 26 | |
| 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 | |
| 31 | |
| 32 class ProxyFactory; | |
| 33 class NavigationConstraints; | |
| 34 enum AutomationPageFontSize; | |
| 35 | |
| 36 struct DECLSPEC_NOVTABLE ChromeFrameAutomationProxy { // NOLINT | |
| 37 virtual bool Send(IPC::Message* msg) = 0; | |
| 38 | |
| 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; | |
| 47 | |
| 48 protected: | |
| 49 virtual ~ChromeFrameAutomationProxy() {} | |
| 50 }; | |
| 51 | |
| 52 // Forward declarations. | |
| 53 class ProxyFactory; | |
| 54 | |
| 55 // We extend the AutomationProxy class to handle our custom | |
| 56 // IPC messages | |
| 57 class ChromeFrameAutomationProxyImpl | |
| 58 : public ChromeFrameAutomationProxy, | |
| 59 // We have to derive from automationproxy since we want access to some | |
| 60 // members (tracker_ & channel_) - simple aggregation wont work; | |
| 61 // .. and non-public inheritance is verboten. | |
| 62 public AutomationProxy { | |
| 63 public: | |
| 64 ~ChromeFrameAutomationProxyImpl(); | |
| 65 virtual void SendAsAsync( | |
| 66 IPC::SyncMessage* msg, | |
| 67 SyncMessageReplyDispatcher::SyncMessageCallContext* context, | |
| 68 void* key); | |
| 69 | |
| 70 // Called on the worker thread. | |
| 71 virtual void OnChannelError(); | |
| 72 | |
| 73 virtual void CancelAsync(void* key); | |
| 74 | |
| 75 virtual scoped_refptr<TabProxy> CreateTabProxy(int handle); | |
| 76 virtual void ReleaseTabProxy(AutomationHandle handle); | |
| 77 | |
| 78 virtual std::string server_version() { | |
| 79 return AutomationProxy::server_version(); | |
| 80 } | |
| 81 | |
| 82 virtual bool Send(IPC::Message* msg) { | |
| 83 return AutomationProxy::Send(msg); | |
| 84 } | |
| 85 | |
| 86 protected: | |
| 87 friend class AutomationProxyCacheEntry; | |
| 88 ChromeFrameAutomationProxyImpl(AutomationProxyCacheEntry* entry, | |
| 89 std::string channel_id, | |
| 90 base::TimeDelta launch_timeout); | |
| 91 | |
| 92 class CFMsgDispatcher; | |
| 93 class TabProxyNotificationMessageFilter; | |
| 94 | |
| 95 scoped_refptr<CFMsgDispatcher> sync_; | |
| 96 scoped_refptr<TabProxyNotificationMessageFilter> message_filter_; | |
| 97 AutomationProxyCacheEntry* proxy_entry_; | |
| 98 }; | |
| 99 | |
| 100 // This class contains information used for launching chrome. | |
| 101 class ChromeFrameLaunchParams : // NOLINT | |
| 102 public base::RefCountedThreadSafe<ChromeFrameLaunchParams> { | |
| 103 public: | |
| 104 ChromeFrameLaunchParams(const GURL& url, const GURL& referrer, | |
| 105 const base::FilePath& profile_path, | |
| 106 const std::wstring& profile_name, | |
| 107 const std::wstring& language, | |
| 108 bool incognito, bool widget_mode, | |
| 109 bool route_all_top_level_navigations) | |
| 110 : launch_timeout_(kCommandExecutionTimeout), url_(url), | |
| 111 referrer_(referrer), profile_path_(profile_path), | |
| 112 profile_name_(profile_name), language_(language), | |
| 113 version_check_(true), incognito_mode_(incognito), | |
| 114 is_widget_mode_(widget_mode), | |
| 115 route_all_top_level_navigations_(route_all_top_level_navigations) { | |
| 116 } | |
| 117 | |
| 118 ~ChromeFrameLaunchParams() { | |
| 119 } | |
| 120 | |
| 121 void set_launch_timeout(int timeout) { | |
| 122 launch_timeout_ = timeout; | |
| 123 } | |
| 124 | |
| 125 int launch_timeout() const { | |
| 126 return launch_timeout_; | |
| 127 } | |
| 128 | |
| 129 const GURL& url() const { | |
| 130 return url_; | |
| 131 } | |
| 132 | |
| 133 void set_url(const GURL& url) { | |
| 134 url_ = url; | |
| 135 } | |
| 136 | |
| 137 const GURL& referrer() const { | |
| 138 return referrer_; | |
| 139 } | |
| 140 | |
| 141 void set_referrer(const GURL& referrer) { | |
| 142 referrer_ = referrer; | |
| 143 } | |
| 144 | |
| 145 const base::FilePath& profile_path() const { | |
| 146 return profile_path_; | |
| 147 } | |
| 148 | |
| 149 const std::wstring& profile_name() const { | |
| 150 return profile_name_; | |
| 151 } | |
| 152 | |
| 153 const std::wstring& language() const { | |
| 154 return language_; | |
| 155 } | |
| 156 | |
| 157 bool version_check() const { | |
| 158 return version_check_; | |
| 159 } | |
| 160 | |
| 161 void set_version_check(bool check) { | |
| 162 version_check_ = check; | |
| 163 } | |
| 164 | |
| 165 bool incognito() const { | |
| 166 return incognito_mode_; | |
| 167 } | |
| 168 | |
| 169 bool widget_mode() const { | |
| 170 return is_widget_mode_; | |
| 171 } | |
| 172 | |
| 173 void set_route_all_top_level_navigations( | |
| 174 bool route_all_top_level_navigations) { | |
| 175 route_all_top_level_navigations_ = route_all_top_level_navigations; | |
| 176 } | |
| 177 | |
| 178 bool route_all_top_level_navigations() const { | |
| 179 return route_all_top_level_navigations_; | |
| 180 } | |
| 181 | |
| 182 protected: | |
| 183 int launch_timeout_; | |
| 184 GURL url_; | |
| 185 GURL referrer_; | |
| 186 base::FilePath profile_path_; | |
| 187 std::wstring profile_name_; | |
| 188 std::wstring language_; | |
| 189 bool version_check_; | |
| 190 bool incognito_mode_; | |
| 191 bool is_widget_mode_; | |
| 192 bool route_all_top_level_navigations_; | |
| 193 | |
| 194 private: | |
| 195 DISALLOW_COPY_AND_ASSIGN(ChromeFrameLaunchParams); | |
| 196 }; | |
| 197 | |
| 198 // Callback when chrome process launch is complete and automation handshake | |
| 199 // (Hello message) is established. All methods are invoked on the automation | |
| 200 // proxy's worker thread. | |
| 201 struct DECLSPEC_NOVTABLE LaunchDelegate { // NOLINT | |
| 202 virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy, | |
| 203 AutomationLaunchResult result) = 0; | |
| 204 virtual void AutomationServerDied() = 0; | |
| 205 }; // NOLINT | |
| 206 | |
| 207 // Manages a cached ChromeFrameAutomationProxyImpl entry and holds | |
| 208 // reference-less pointers to LaunchDelegate(s) to be notified in case | |
| 209 // of automation server process changes. | |
| 210 class AutomationProxyCacheEntry | |
| 211 : public base::RefCounted<AutomationProxyCacheEntry> { | |
| 212 public: | |
| 213 AutomationProxyCacheEntry(ChromeFrameLaunchParams* params, | |
| 214 LaunchDelegate* delegate); | |
| 215 | |
| 216 ~AutomationProxyCacheEntry(); | |
| 217 | |
| 218 void AddDelegate(LaunchDelegate* delegate); | |
| 219 void RemoveDelegate(LaunchDelegate* delegate, base::WaitableEvent* done, | |
| 220 bool* was_last_delegate); | |
| 221 | |
| 222 DWORD WaitForThread(DWORD timeout) { // NOLINT | |
| 223 DCHECK(thread_.get()); | |
| 224 return ::WaitForSingleObject(thread_->thread_handle().platform_handle(), | |
| 225 timeout); | |
| 226 } | |
| 227 | |
| 228 bool IsSameProfile(const std::wstring& name) const { | |
| 229 return lstrcmpiW(name.c_str(), profile_name.c_str()) == 0; | |
| 230 } | |
| 231 | |
| 232 base::Thread* thread() const { | |
| 233 return thread_.get(); | |
| 234 } | |
| 235 | |
| 236 base::MessageLoop* message_loop() const { | |
| 237 return thread_->message_loop(); | |
| 238 } | |
| 239 | |
| 240 bool IsSameThread(base::PlatformThreadId id) const { | |
| 241 return thread_->thread_id() == id; | |
| 242 } | |
| 243 | |
| 244 ChromeFrameAutomationProxyImpl* proxy() const { | |
| 245 DCHECK(IsSameThread(base::PlatformThread::CurrentId())); | |
| 246 return proxy_.get(); | |
| 247 } | |
| 248 | |
| 249 // Called by the proxy when the automation server has unexpectedly gone away. | |
| 250 void OnChannelError(); | |
| 251 | |
| 252 protected: | |
| 253 void CreateProxy(ChromeFrameLaunchParams* params, | |
| 254 LaunchDelegate* delegate); | |
| 255 | |
| 256 protected: | |
| 257 std::wstring profile_name; | |
| 258 scoped_ptr<base::Thread> thread_; | |
| 259 scoped_ptr<ChromeFrameAutomationProxyImpl> proxy_; | |
| 260 AutomationLaunchResult launch_result_; | |
| 261 typedef std::vector<LaunchDelegate*> LaunchDelegates; | |
| 262 LaunchDelegates launch_delegates_; | |
| 263 // Used for UMA histogram logging to measure the time for the chrome | |
| 264 // automation server to start; | |
| 265 base::TimeTicks automation_server_launch_start_time_; | |
| 266 }; | |
| 267 | |
| 268 // We must create and destroy automation proxy in a thread with a message loop. | |
| 269 // Hence thread cannot be a member of the proxy. | |
| 270 class ProxyFactory { | |
| 271 public: | |
| 272 ProxyFactory(); | |
| 273 virtual ~ProxyFactory(); | |
| 274 | |
| 275 // Fetches or creates a new automation server instance. | |
| 276 // delegate may be NULL. If non-null, a pointer to the delegate will | |
| 277 // be stored for the lifetime of the automation process or until | |
| 278 // ReleaseAutomationServer is called. | |
| 279 virtual void GetAutomationServer(LaunchDelegate* delegate, | |
| 280 ChromeFrameLaunchParams* params, | |
| 281 void** automation_server_id); | |
| 282 virtual bool ReleaseAutomationServer(void* server_id, | |
| 283 LaunchDelegate* delegate); | |
| 284 | |
| 285 private: | |
| 286 typedef base::StackVector<scoped_refptr<AutomationProxyCacheEntry>, 4> Vector; | |
| 287 Vector proxies_; | |
| 288 // Lock if we are going to call GetAutomationServer from more than one thread. | |
| 289 base::Lock lock_; | |
| 290 }; | |
| 291 | |
| 292 // Handles all automation requests initiated from the chrome frame objects. | |
| 293 // These include the chrome tab/chrome frame activex plugin objects. | |
| 294 class ChromeFrameAutomationClient | |
| 295 : public CWindowImpl<ChromeFrameAutomationClient>, | |
| 296 public TaskMarshallerThroughWindowsMessages<ChromeFrameAutomationClient>, | |
| 297 public base::RefCountedThreadSafe<ChromeFrameAutomationClient>, | |
| 298 public PluginUrlRequestDelegate, | |
| 299 public TabProxy::TabProxyDelegate, | |
| 300 public LaunchDelegate { | |
| 301 public: | |
| 302 ChromeFrameAutomationClient(); | |
| 303 ~ChromeFrameAutomationClient(); | |
| 304 | |
| 305 // Called from UI thread. | |
| 306 virtual bool Initialize(ChromeFrameDelegate* chrome_frame_delegate, | |
| 307 ChromeFrameLaunchParams* chrome_launch_params); | |
| 308 void Uninitialize(); | |
| 309 void NotifyAndUninitialize(); | |
| 310 | |
| 311 virtual bool InitiateNavigation( | |
| 312 const std::string& url, | |
| 313 const std::string& referrer, | |
| 314 NavigationConstraints* navigation_constraints); | |
| 315 | |
| 316 void FindInPage(const std::wstring& search_string, | |
| 317 FindInPageDirection forward, | |
| 318 FindInPageCase match_case, | |
| 319 bool find_next); | |
| 320 | |
| 321 TabProxy* tab() const { return tab_.get(); } | |
| 322 | |
| 323 BEGIN_MSG_MAP(ChromeFrameAutomationClient) | |
| 324 CHAIN_MSG_MAP( | |
| 325 TaskMarshallerThroughWindowsMessages<ChromeFrameAutomationClient>) | |
| 326 END_MSG_MAP() | |
| 327 | |
| 328 // Sets the passed in window as the parent of the external tab. | |
| 329 void SetParentWindow(HWND parent_window); | |
| 330 | |
| 331 HWND tab_window() const { | |
| 332 return tab_window_; | |
| 333 } | |
| 334 | |
| 335 void ReleaseAutomationServer(); | |
| 336 | |
| 337 // Returns the version number of plugin dll. | |
| 338 std::wstring GetVersion() const; | |
| 339 | |
| 340 // BitBlts the contents of the chrome window to the print dc. | |
| 341 void Print(HDC print_dc, const RECT& print_bounds); | |
| 342 | |
| 343 void set_use_chrome_network(bool use_chrome_network) { | |
| 344 use_chrome_network_ = use_chrome_network; | |
| 345 } | |
| 346 | |
| 347 bool use_chrome_network() const { | |
| 348 return use_chrome_network_; | |
| 349 } | |
| 350 | |
| 351 #ifdef UNIT_TEST | |
| 352 void set_proxy_factory(ProxyFactory* factory) { | |
| 353 proxy_factory_ = factory; | |
| 354 } | |
| 355 #endif | |
| 356 | |
| 357 void set_handle_top_level_requests(bool handle_top_level_requests) { | |
| 358 handle_top_level_requests_ = handle_top_level_requests; | |
| 359 } | |
| 360 | |
| 361 // Url request manager set up. | |
| 362 void SetUrlFetcher(PluginUrlRequestManager* url_fetcher); | |
| 363 | |
| 364 void SetPageFontSize(enum AutomationPageFontSize); | |
| 365 | |
| 366 // For IDeleteBrowsingHistorySupport | |
| 367 void RemoveBrowsingData(int remove_mask); | |
| 368 | |
| 369 protected: | |
| 370 // ChromeFrameAutomationProxy::LaunchDelegate implementation. | |
| 371 virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy, | |
| 372 AutomationLaunchResult result); | |
| 373 virtual void AutomationServerDied(); | |
| 374 | |
| 375 // TabProxyDelegate implementation | |
| 376 virtual bool OnMessageReceived(TabProxy* tab, const IPC::Message& msg); | |
| 377 virtual void OnChannelError(TabProxy* tab); | |
| 378 | |
| 379 virtual void OnFinalMessage(HWND wnd) { | |
| 380 Release(); | |
| 381 } | |
| 382 | |
| 383 scoped_refptr<ChromeFrameLaunchParams> launch_params() { | |
| 384 return chrome_launch_params_; | |
| 385 } | |
| 386 | |
| 387 private: | |
| 388 void OnMessageReceivedUIThread(const IPC::Message& msg); | |
| 389 void OnChannelErrorUIThread(); | |
| 390 | |
| 391 HWND chrome_window() const { return chrome_window_; } | |
| 392 void BeginNavigateCompleted(AutomationMsg_NavigationResponseValues result); | |
| 393 | |
| 394 // Helpers | |
| 395 void ReportNavigationError(AutomationMsg_NavigationResponseValues error_code, | |
| 396 const std::string& url); | |
| 397 | |
| 398 bool is_initialized() const { | |
| 399 return init_state_ == INITIALIZED; | |
| 400 } | |
| 401 | |
| 402 HWND parent_window_; | |
| 403 base::PlatformThreadId ui_thread_id_; | |
| 404 | |
| 405 void* automation_server_id_; | |
| 406 ChromeFrameAutomationProxy* automation_server_; | |
| 407 | |
| 408 HWND chrome_window_; | |
| 409 scoped_refptr<TabProxy> tab_; | |
| 410 ChromeFrameDelegate* chrome_frame_delegate_; | |
| 411 | |
| 412 // Handle to the underlying chrome window. This is a child of the external | |
| 413 // tab window. | |
| 414 HWND tab_window_; | |
| 415 | |
| 416 // Keeps track of the version of Chrome we're talking to. | |
| 417 std::string automation_server_version_; | |
| 418 | |
| 419 typedef enum InitializationState { | |
| 420 UNINITIALIZED = 0, | |
| 421 INITIALIZING, | |
| 422 INITIALIZED, | |
| 423 UNINITIALIZING, | |
| 424 }; | |
| 425 | |
| 426 InitializationState init_state_; | |
| 427 bool use_chrome_network_; | |
| 428 bool handle_top_level_requests_; | |
| 429 ProxyFactory* proxy_factory_; | |
| 430 int tab_handle_; | |
| 431 // The SessionId used by Chrome as the id in the Javascript Tab object. | |
| 432 int session_id_; | |
| 433 | |
| 434 // Set to true if we received a navigation request prior to the automation | |
| 435 // server being initialized. | |
| 436 bool navigate_after_initialization_; | |
| 437 | |
| 438 scoped_refptr<ChromeFrameLaunchParams> chrome_launch_params_; | |
| 439 | |
| 440 // Cache security manager for URL zone checking | |
| 441 base::win::ScopedComPtr<IInternetSecurityManager> security_manager_; | |
| 442 | |
| 443 // When host network stack is used, this object is in charge of | |
| 444 // handling network requests. | |
| 445 PluginUrlRequestManager* url_fetcher_; | |
| 446 PluginUrlRequestManager::ThreadSafeFlags url_fetcher_flags_; | |
| 447 | |
| 448 // set to true if the host needs to get notified of all top level navigations | |
| 449 // in this page. This typically applies to hosts which would render the new | |
| 450 // page without chrome frame. Defaults to false. | |
| 451 bool route_all_top_level_navigations_; | |
| 452 | |
| 453 friend class BeginNavigateContext; | |
| 454 friend class CreateExternalTabContext; | |
| 455 }; | |
| 456 | |
| 457 #endif // CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_ | |
| OLD | NEW |