| Index: chrome_frame/chrome_frame_automation.h
|
| ===================================================================
|
| --- chrome_frame/chrome_frame_automation.h (revision 0)
|
| +++ chrome_frame/chrome_frame_automation.h (revision 0)
|
| @@ -0,0 +1,356 @@
|
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_
|
| +#define CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_
|
| +
|
| +#include <atlbase.h>
|
| +#include <atlwin.h>
|
| +#include <string>
|
| +#include <map>
|
| +
|
| +#include "base/lock.h"
|
| +#include "base/ref_counted.h"
|
| +#include "base/scoped_handle.h"
|
| +#include "base/stack_container.h"
|
| +#include "base/task.h"
|
| +#include "base/timer.h"
|
| +#include "base/thread.h"
|
| +#include "chrome/test/automation/automation_proxy.h"
|
| +#include "chrome/test/automation/tab_proxy.h"
|
| +#include "chrome_frame/chrome_frame_delegate.h"
|
| +#include "chrome_frame/chrome_frame_histograms.h"
|
| +#include "chrome_frame/plugin_url_request.h"
|
| +
|
| +const unsigned long kCommandExecutionTimeout = 4000; // NOLINT, 4 seconds
|
| +
|
| +class ProxyFactory;
|
| +
|
| +struct DECLSPEC_NOVTABLE ChromeFrameAutomationProxy {
|
| + virtual bool Send(IPC::Message* msg) = 0;
|
| +
|
| + virtual void SendAsAsync(IPC::SyncMessage* msg, void* callback,
|
| + void* key) = 0;
|
| + virtual void CancelAsync(void* key) = 0;
|
| + virtual scoped_refptr<TabProxy> CreateTabProxy(int handle) = 0;
|
| + virtual std::string server_version() = 0;
|
| +
|
| + virtual void SendProxyConfig(const std::string&) = 0;
|
| + virtual void SetEnableExtensionAutomation(bool enable) = 0;
|
| + protected:
|
| + ~ChromeFrameAutomationProxy() {}
|
| +};
|
| +
|
| +// We extend the AutomationProxy class to handle our custom
|
| +// IPC messages
|
| +class ChromeFrameAutomationProxyImpl : public ChromeFrameAutomationProxy,
|
| + // We have to derive from automationproxy since we want access to some members
|
| + // (tracker_ & channel_) - simple aggregation wont work;
|
| + // .. and non-public inheritance is verboten.
|
| + public AutomationProxy {
|
| + public:
|
| + virtual void SendAsAsync(IPC::SyncMessage* msg, void* callback, void* key);
|
| +
|
| + virtual void CancelAsync(void* key);
|
| +
|
| + virtual scoped_refptr<TabProxy> CreateTabProxy(int handle);
|
| + virtual std::string server_version() {
|
| + return AutomationProxy::server_version();
|
| + }
|
| +
|
| +
|
| + virtual bool Send(IPC::Message* msg) {
|
| + return AutomationProxy::Send(msg);
|
| + }
|
| +
|
| + virtual void SendProxyConfig(const std::string& p) {
|
| + AutomationProxy::SendProxyConfig(p);
|
| + }
|
| +
|
| + virtual void SetEnableExtensionAutomation(bool e) {
|
| + AutomationProxy::SetEnableExtensionAutomation(e);
|
| + }
|
| +
|
| + protected:
|
| + explicit ChromeFrameAutomationProxyImpl(int launch_timeout);
|
| + ~ChromeFrameAutomationProxyImpl();
|
| + class CFMsgDispatcher;
|
| + scoped_refptr<CFMsgDispatcher> sync_;
|
| + friend class ProxyFactory;
|
| +};
|
| +
|
| +// We must create and destroy automation proxy in a thread with a message loop.
|
| +// Hence thread cannot be a member of the proxy.
|
| +class ProxyFactory {
|
| + public:
|
| + // Callback when chrome process launch is complete and automation handshake
|
| + // (Hello message) is established.
|
| + struct DECLSPEC_NOVTABLE LaunchDelegate {
|
| + virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy,
|
| + AutomationLaunchResult result) = 0;
|
| + };
|
| +
|
| + ProxyFactory();
|
| + ~ProxyFactory();
|
| + // FIXME: we should pass the result as output parameter, not as return value
|
| + // since, LaunchDelegate can be invoked before this function returns.
|
| + virtual void* GetAutomationServer(int launch_timeout,
|
| + const std::wstring& profile_name,
|
| + // Extra command line argument when launching Chrome
|
| + const std::wstring& extra_argument,
|
| + bool perform_version_check,
|
| + LaunchDelegate* delegate);
|
| + virtual bool ReleaseAutomationServer(void* server_id);
|
| +
|
| + private:
|
| + struct ProxyCacheEntry {
|
| + std::wstring profile_name;
|
| + int ref_count;
|
| + scoped_ptr<base::Thread> thread;
|
| + ChromeFrameAutomationProxyImpl* proxy;
|
| + AutomationLaunchResult launch_result;
|
| + explicit ProxyCacheEntry(const std::wstring& profile);
|
| + };
|
| +
|
| + void CreateProxy(ProxyCacheEntry* entry,
|
| + int launch_timeout,
|
| + const std::wstring& extra_chrome_arguments,
|
| + bool perform_version_check,
|
| + LaunchDelegate* delegate);
|
| + void DestroyProxy(ProxyCacheEntry* entry);
|
| +
|
| + void SendUMAData(ProxyCacheEntry* proxy_entry);
|
| +
|
| + typedef StackVector<ProxyCacheEntry*, 4> Vector;
|
| + Vector proxies_;
|
| + // Lock if we are going to call GetAutomationServer from more than one thread.
|
| + Lock lock_;
|
| +
|
| + // Used for UMA histogram logging to measure the time for the chrome
|
| + // automation server to start;
|
| + base::TimeTicks automation_server_launch_start_time_;
|
| +
|
| + // Gathers histograms to be sent to Chrome.
|
| + ChromeFrameHistogramSnapshots chrome_frame_histograms_;
|
| +
|
| + // Interval for sending UMA data
|
| + int uma_send_interval_;
|
| +};
|
| +
|
| +// T is expected to be something CWindowImpl derived, or at least to have
|
| +// PostMessage(UINT, WPARAM) method. Do not forget to CHAIN_MSG_MAP
|
| +template <class T> class TaskMarshallerThroughWindowsMessages {
|
| + public:
|
| + void PostTask(const tracked_objects::Location& from_here, Task* task) {
|
| + task->SetBirthPlace(from_here);
|
| + T* this_ptr = static_cast<T*>(this);
|
| + if (this_ptr->IsWindow()) {
|
| + this_ptr->PostMessage(MSG_EXECUTE_TASK, reinterpret_cast<WPARAM>(task));
|
| + } else {
|
| + DLOG(INFO) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
|
| + }
|
| + }
|
| +
|
| + BEGIN_MSG_MAP(PostMessageMarshaller)
|
| + MESSAGE_HANDLER(MSG_EXECUTE_TASK, ExecuteTask)
|
| + END_MSG_MAP()
|
| +
|
| + private:
|
| + enum { MSG_EXECUTE_TASK = WM_APP + 6 };
|
| + inline LRESULT ExecuteTask(UINT, WPARAM wparam, LPARAM,
|
| + BOOL& handled) { // NOLINT
|
| + Task* task = reinterpret_cast<Task*>(wparam);
|
| + task->Run();
|
| + delete task;
|
| + return 0;
|
| + }
|
| +};
|
| +
|
| +// Handles all automation requests initiated from the chrome frame objects.
|
| +// These include the chrome tab/chrome frame activex/chrome frame npapi
|
| +// plugin objects.
|
| +class ChromeFrameAutomationClient
|
| + : public CWindowImpl<ChromeFrameAutomationClient>,
|
| + public TaskMarshallerThroughWindowsMessages<ChromeFrameAutomationClient>,
|
| + public PluginRequestHandler,
|
| + public TabProxy::TabProxyDelegate,
|
| + public ProxyFactory::LaunchDelegate {
|
| + public:
|
| + ChromeFrameAutomationClient();
|
| + ~ChromeFrameAutomationClient();
|
| +
|
| + // Called from UI thread.
|
| + virtual bool Initialize(ChromeFrameDelegate* chrome_frame_delegate,
|
| + int automation_server_launch_timeout,
|
| + bool perform_version_check,
|
| + const std::wstring& profile_name,
|
| + const std::wstring& extra_chrome_arguments,
|
| + bool incognito);
|
| + void Uninitialize();
|
| +
|
| + virtual bool InitiateNavigation(const std::string& url);
|
| + virtual bool NavigateToIndex(int index);
|
| + bool ForwardMessageFromExternalHost(const std::string& message,
|
| + const std::string& origin,
|
| + const std::string& target);
|
| + bool SetProxySettings(const std::string& json_encoded_proxy_settings);
|
| +
|
| + virtual void SetEnableExtensionAutomation(bool enable_automation);
|
| +
|
| + void FindInPage(const std::wstring& search_string,
|
| + FindInPageDirection forward,
|
| + FindInPageCase match_case,
|
| + bool find_next);
|
| +
|
| + TabProxy* tab() const { return tab_.get(); }
|
| +
|
| + BEGIN_MSG_MAP(ChromeFrameAutomationClient)
|
| + CHAIN_MSG_MAP(
|
| + TaskMarshallerThroughWindowsMessages<ChromeFrameAutomationClient>)
|
| + END_MSG_MAP()
|
| +
|
| + void set_delegate(ChromeFrameDelegate* d) {
|
| + chrome_frame_delegate_ = d;
|
| + }
|
| +
|
| + // Resizes the hosted chrome window. This is brokered to the chrome
|
| + // automation instance as the host browser could be running under low IL,
|
| + // which would cause the SetWindowPos call to fail.
|
| + void Resize(int width, int height, int flags);
|
| +
|
| + // Sets the passed in window as the parent of the external tab.
|
| + void SetParentWindow(HWND parent_window);
|
| +
|
| + void SendContextMenuCommandToChromeFrame(int selected_command);
|
| +
|
| + HWND tab_window() const {
|
| + return tab_window_;
|
| + }
|
| +
|
| + void ReleaseAutomationServer();
|
| +
|
| + // Returns the version number of plugin dll.
|
| + std::wstring GetVersion() const;
|
| +
|
| + // BitBlts the contents of the chrome window to the print dc.
|
| + void Print(HDC print_dc, const RECT& print_bounds);
|
| +
|
| + // Called in full tab mode and indicates a request to chrome to print
|
| + // the whole tab.
|
| + void PrintTab();
|
| +
|
| + // PluginRequestHandler
|
| + bool AddRequest(PluginUrlRequest* request);
|
| + void RemoveRequest(PluginUrlRequest* request);
|
| + virtual bool Send(IPC::Message* msg);
|
| +
|
| + // URL request related
|
| + bool ReadRequest(int request_id, int bytes_to_read);
|
| + void RemoveRequest(int request_id, int reason, bool abort);
|
| + PluginUrlRequest* LookupRequest(int request_id) const;
|
| + bool IsValidRequest(PluginUrlRequest* request) const;
|
| + void CleanupRequests();
|
| +
|
| + void set_use_chrome_network(bool use_chrome_network) {
|
| + use_chrome_network_ = use_chrome_network;
|
| + }
|
| + bool use_chrome_network() const {
|
| + return use_chrome_network_;
|
| + }
|
| +
|
| +#ifdef UNIT_TEST
|
| + void set_proxy_factory(ProxyFactory* factory) {
|
| + proxy_factory_ = factory;
|
| + }
|
| +#endif
|
| +
|
| + void set_handle_top_level_requests(bool handle_top_level_requests) {
|
| + handle_top_level_requests_ = handle_top_level_requests;
|
| + }
|
| +
|
| + // Called if the same instance of the ChromeFrameAutomationClient object
|
| + // is reused.
|
| + bool Reinitialize(ChromeFrameDelegate* chrome_frame_delegate);
|
| +
|
| + // Attaches an existing external tab to this automation client instance.
|
| + void AttachExternalTab(intptr_t external_tab_cookie);
|
| +
|
| + protected:
|
| + // ChromeFrameAutomationProxy::LaunchDelegate implementation.
|
| + virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy,
|
| + AutomationLaunchResult result);
|
| + // TabProxyDelegate implementation
|
| + virtual void OnMessageReceived(TabProxy* tab, const IPC::Message& msg);
|
| +
|
| + void CreateExternalTab();
|
| + void CreateExternalTabComplete(HWND chrome_window, HWND tab_window,
|
| + int tab_handle);
|
| + // Called in UI thread. Here we fire event to the client notifying for
|
| + // the result of Initialize() method call.
|
| + void InitializeComplete(AutomationLaunchResult result);
|
| +
|
| + private:
|
| + typedef std::map<int, scoped_refptr<PluginUrlRequest> > RequestMap;
|
| +
|
| + // Usage: From bkgnd thread invoke:
|
| + // CallDelegate(FROM_HERE, NewRunnableMethod(chrome_frame_delegate_,
|
| + // ChromeFrameDelegate::Something,
|
| + // param1,
|
| + // param2));
|
| + void CallDelegate(const tracked_objects::Location& from_here,
|
| + Task* delegate_task);
|
| + // The workhorse method called in main/GUI thread which is going to
|
| + // execute ChromeFrameDelegate method encapsulated in delegate_task.
|
| + void CallDelegateImpl(Task* delegate_task);
|
| +
|
| + HWND chrome_window() const { return chrome_window_; }
|
| + void BeginNavigate(const GURL& url);
|
| + void BeginNavigateCompleted(AutomationMsg_NavigationResponseValues result);
|
| +
|
| + // Helpers
|
| + void ReportNavigationError(AutomationMsg_NavigationResponseValues error_code,
|
| + const std::string& url);
|
| +
|
| + bool is_initialized() const {
|
| + return init_state_ == INITIALIZED;
|
| + }
|
| +
|
| + bool incognito_;
|
| + HWND parent_window_;
|
| + PlatformThreadId ui_thread_id_;
|
| +
|
| + void* automation_server_id_;
|
| + ChromeFrameAutomationProxy* automation_server_;
|
| + HWND chrome_window_;
|
| + scoped_refptr<TabProxy> tab_;
|
| + ChromeFrameDelegate* chrome_frame_delegate_;
|
| + GURL url_;
|
| +
|
| + // Handle to the underlying chrome window. This is a child of the external
|
| + // tab window.
|
| + HWND tab_window_;
|
| +
|
| + // Keeps track of the version of Chrome we're talking to.
|
| + std::string automation_server_version_;
|
| +
|
| + // Map of outstanding requests
|
| + RequestMap request_map_;
|
| +
|
| + typedef enum InitializationState {
|
| + UNINITIALIZED = 0,
|
| + INITIALIZING,
|
| + INITIALIZED,
|
| + UNINITIALIZING,
|
| + };
|
| +
|
| + InitializationState init_state_;
|
| + bool use_chrome_network_;
|
| + bool handle_top_level_requests_;
|
| + ProxyFactory* proxy_factory_;
|
| + int tab_handle_;
|
| + // Only used if we attach to an existing tab.
|
| + intptr_t external_tab_cookie_;
|
| +};
|
| +
|
| +#endif // CHROME_FRAME_CHROME_FRAME_AUTOMATION_H_
|
|
|