Home | History | Annotate | Download | only in chrome_frame
      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 #ifndef CHROME_FRAME_CHROME_FRAME_DELEGATE_H_
      6 #define CHROME_FRAME_CHROME_FRAME_DELEGATE_H_
      7 
      8 #include <atlbase.h>
      9 #include <atlwin.h>
     10 #include <queue>
     11 #include <string>
     12 #include <vector>
     13 
     14 #include "base/callback.h"
     15 #include "base/files/file_path.h"
     16 #include "base/location.h"
     17 #include "base/pending_task.h"
     18 #include "base/synchronization/lock.h"
     19 #include "chrome/common/automation_constants.h"
     20 #include "ipc/ipc_message.h"
     21 
     22 class GURL;
     23 struct AttachExternalTabParams;
     24 struct AutomationURLRequest;
     25 struct ContextMenuModel;
     26 struct MiniContextMenuParams;
     27 struct NavigationInfo;
     28 
     29 namespace net {
     30 class URLRequestStatus;
     31 }
     32 
     33 namespace gfx {
     34 class Rect;
     35 }
     36 
     37 // A common interface supported by all the browser specific ChromeFrame
     38 // implementations.
     39 class ChromeFrameDelegate {
     40  public:
     41   typedef HWND WindowType;
     42 
     43   virtual WindowType GetWindow() const = 0;
     44   virtual void GetBounds(RECT* bounds) = 0;
     45   virtual std::string GetDocumentUrl() = 0;
     46   virtual void OnAutomationServerReady() = 0;
     47   virtual void OnAutomationServerLaunchFailed(
     48       AutomationLaunchResult reason, const std::string& server_version) = 0;
     49   virtual bool OnMessageReceived(const IPC::Message& msg) = 0;
     50   virtual void OnChannelError() = 0;
     51 
     52   // This remains in interface since we call it if Navigate()
     53   // returns immediate error.
     54   virtual void OnLoadFailed(int error_code, const std::string& url) = 0;
     55 
     56   // Returns true if this instance is alive and well for processing automation
     57   // messages.
     58   virtual bool IsValid() const = 0;
     59 
     60   // To be called when the top-most window of an application hosting
     61   // ChromeFrame is moved.
     62   virtual void OnHostMoved() = 0;
     63 
     64  protected:
     65   virtual ~ChromeFrameDelegate() {}
     66 };
     67 
     68 extern UINT kAutomationServerReady;
     69 extern UINT kMessageFromChromeFrame;
     70 
     71 class ChromeFrameDelegateImpl : public ChromeFrameDelegate {
     72  public:
     73   virtual WindowType GetWindow() { return NULL; }
     74   virtual void GetBounds(RECT* bounds) {}
     75   virtual std::string GetDocumentUrl() { return std::string(); }
     76   virtual void OnAutomationServerReady() {}
     77   virtual void OnAutomationServerLaunchFailed(
     78       AutomationLaunchResult reason, const std::string& server_version) {}
     79   virtual void OnLoadFailed(int error_code, const std::string& url) {}
     80   virtual bool OnMessageReceived(const IPC::Message& msg);
     81   virtual void OnChannelError() {}
     82 
     83   static bool IsTabMessage(const IPC::Message& message);
     84 
     85   virtual bool IsValid() const {
     86     return true;
     87   }
     88 
     89   virtual void OnHostMoved() {}
     90 
     91  protected:
     92   // Protected methods to be overridden.
     93   virtual void OnNavigationStateChanged(
     94       int flags, const NavigationInfo& nav_info) {}
     95   virtual void OnUpdateTargetUrl(const std::wstring& new_target_url) {}
     96   virtual void OnAcceleratorPressed(const MSG& accel_message) {}
     97   virtual void OnTabbedOut(bool reverse) {}
     98   virtual void OnOpenURL(
     99       const GURL& url, const GURL& referrer, int open_disposition) {}
    100   virtual void OnDidNavigate(const NavigationInfo& navigation_info) {}
    101   virtual void OnNavigationFailed(int error_code, const GURL& gurl) {}
    102   virtual void OnLoad(const GURL& url) {}
    103   virtual void OnMoveWindow(const gfx::Rect& pos) {}
    104   virtual void OnMessageFromChromeFrame(const std::string& message,
    105                                         const std::string& origin,
    106                                         const std::string& target) {}
    107   virtual void OnHandleContextMenu(const ContextMenuModel& context_menu_model,
    108                                    int align_flags,
    109                                    const MiniContextMenuParams& params) {}
    110   virtual void OnRequestStart(
    111       int request_id, const AutomationURLRequest& request) {}
    112   virtual void OnRequestRead(int request_id, int bytes_to_read) {}
    113   virtual void OnRequestEnd(int request_id,
    114                             const net::URLRequestStatus& status) {}
    115   virtual void OnDownloadRequestInHost(int request_id) {}
    116   virtual void OnSetCookieAsync(const GURL& url, const std::string& cookie) {}
    117   virtual void OnAttachExternalTab(
    118       const AttachExternalTabParams& attach_params) {}
    119   virtual void OnGoToHistoryEntryOffset(int offset) {}
    120 
    121   virtual void OnGetCookiesFromHost(const GURL& url, int cookie_id) {}
    122   virtual void OnCloseTab() {}
    123 };
    124 
    125 // This interface enables tasks to be marshaled to desired threads.
    126 class TaskMarshaller {  // NOLINT
    127  public:
    128   virtual void PostTask(const tracked_objects::Location& from_here,
    129                         const base::Closure& task) = 0;
    130 };
    131 
    132 // T is expected to be something CWindowImpl derived, or at least to have
    133 // PostMessage(UINT, WPARAM) method. Do not forget to CHAIN_MSG_MAP
    134 template <class T> class TaskMarshallerThroughWindowsMessages
    135     : public TaskMarshaller {
    136  public:
    137   TaskMarshallerThroughWindowsMessages() {}
    138   virtual void PostTask(const tracked_objects::Location& posted_from,
    139                         const base::Closure& task) OVERRIDE {
    140     T* this_ptr = static_cast<T*>(this);
    141     if (this_ptr->IsWindow()) {
    142       this_ptr->AddRef();
    143       base::PendingTask* pending_task =
    144           new base::PendingTask(posted_from, task);
    145       PushTask(pending_task);
    146       this_ptr->PostMessage(MSG_EXECUTE_TASK,
    147                             reinterpret_cast<WPARAM>(pending_task));
    148     } else {
    149       DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
    150     }
    151   }
    152 
    153  protected:
    154   ~TaskMarshallerThroughWindowsMessages() {
    155     DeleteAllPendingTasks();
    156   }
    157 
    158   void DeleteAllPendingTasks() {
    159     base::AutoLock lock(lock_);
    160     DVLOG_IF(1, !pending_tasks_.empty()) << "Destroying "
    161                                          << pending_tasks_.size()
    162                                          << " pending tasks";
    163     while (!pending_tasks_.empty()) {
    164       base::PendingTask* task = pending_tasks_.front();
    165       pending_tasks_.pop();
    166       delete task;
    167     }
    168   }
    169 
    170   BEGIN_MSG_MAP(PostMessageMarshaller)
    171     MESSAGE_HANDLER(MSG_EXECUTE_TASK, ExecuteTask)
    172   END_MSG_MAP()
    173 
    174  private:
    175   enum { MSG_EXECUTE_TASK = WM_APP + 6 };
    176   inline LRESULT ExecuteTask(UINT, WPARAM wparam, LPARAM,
    177                              BOOL& handled) {  // NOLINT
    178     base::PendingTask* pending_task =
    179         reinterpret_cast<base::PendingTask*>(wparam);
    180     if (pending_task && PopTask(pending_task)) {
    181       pending_task->task.Run();
    182       delete pending_task;
    183     }
    184 
    185     T* this_ptr = static_cast<T*>(this);
    186     this_ptr->Release();
    187     return 0;
    188   }
    189 
    190   inline void PushTask(base::PendingTask* pending_task) {
    191     base::AutoLock lock(lock_);
    192     pending_tasks_.push(pending_task);
    193   }
    194 
    195   // If |pending_task| is front of the queue, removes the task and returns true,
    196   // otherwise we assume this is an already destroyed task (but Window message
    197   // had remained in the thread queue).
    198   inline bool PopTask(base::PendingTask* pending_task) {
    199     base::AutoLock lock(lock_);
    200     if (!pending_tasks_.empty() && pending_task == pending_tasks_.front()) {
    201       pending_tasks_.pop();
    202       return true;
    203     }
    204 
    205     return false;
    206   }
    207 
    208   base::Lock lock_;
    209   std::queue<base::PendingTask*> pending_tasks_;
    210 };
    211 
    212 #endif  // CHROME_FRAME_CHROME_FRAME_DELEGATE_H_
    213