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 OnAttachExternalTab(
    117       const AttachExternalTabParams& attach_params) {}
    118   virtual void OnGoToHistoryEntryOffset(int offset) {}
    119   virtual void OnCloseTab() {}
    120 };
    121 
    122 // This interface enables tasks to be marshaled to desired threads.
    123 class TaskMarshaller {  // NOLINT
    124  public:
    125   virtual void PostTask(const tracked_objects::Location& from_here,
    126                         const base::Closure& task) = 0;
    127 };
    128 
    129 // T is expected to be something CWindowImpl derived, or at least to have
    130 // PostMessage(UINT, WPARAM) method. Do not forget to CHAIN_MSG_MAP
    131 template <class T> class TaskMarshallerThroughWindowsMessages
    132     : public TaskMarshaller {
    133  public:
    134   TaskMarshallerThroughWindowsMessages() {}
    135   virtual void PostTask(const tracked_objects::Location& posted_from,
    136                         const base::Closure& task) OVERRIDE {
    137     T* this_ptr = static_cast<T*>(this);
    138     if (this_ptr->IsWindow()) {
    139       this_ptr->AddRef();
    140       base::PendingTask* pending_task =
    141           new base::PendingTask(posted_from, task);
    142       PushTask(pending_task);
    143       this_ptr->PostMessage(MSG_EXECUTE_TASK,
    144                             reinterpret_cast<WPARAM>(pending_task));
    145     } else {
    146       DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
    147     }
    148   }
    149 
    150  protected:
    151   ~TaskMarshallerThroughWindowsMessages() {
    152     DeleteAllPendingTasks();
    153   }
    154 
    155   void DeleteAllPendingTasks() {
    156     base::AutoLock lock(lock_);
    157     DVLOG_IF(1, !pending_tasks_.empty()) << "Destroying "
    158                                          << pending_tasks_.size()
    159                                          << " pending tasks";
    160     while (!pending_tasks_.empty()) {
    161       base::PendingTask* task = pending_tasks_.front();
    162       pending_tasks_.pop();
    163       delete task;
    164     }
    165   }
    166 
    167   BEGIN_MSG_MAP(PostMessageMarshaller)
    168     MESSAGE_HANDLER(MSG_EXECUTE_TASK, ExecuteTask)
    169   END_MSG_MAP()
    170 
    171  private:
    172   enum { MSG_EXECUTE_TASK = WM_APP + 6 };
    173   inline LRESULT ExecuteTask(UINT, WPARAM wparam, LPARAM,
    174                              BOOL& handled) {  // NOLINT
    175     base::PendingTask* pending_task =
    176         reinterpret_cast<base::PendingTask*>(wparam);
    177     if (pending_task && PopTask(pending_task)) {
    178       pending_task->task.Run();
    179       delete pending_task;
    180     }
    181 
    182     T* this_ptr = static_cast<T*>(this);
    183     this_ptr->Release();
    184     return 0;
    185   }
    186 
    187   inline void PushTask(base::PendingTask* pending_task) {
    188     base::AutoLock lock(lock_);
    189     pending_tasks_.push(pending_task);
    190   }
    191 
    192   // If |pending_task| is front of the queue, removes the task and returns true,
    193   // otherwise we assume this is an already destroyed task (but Window message
    194   // had remained in the thread queue).
    195   inline bool PopTask(base::PendingTask* pending_task) {
    196     base::AutoLock lock(lock_);
    197     if (!pending_tasks_.empty() && pending_task == pending_tasks_.front()) {
    198       pending_tasks_.pop();
    199       return true;
    200     }
    201 
    202     return false;
    203   }
    204 
    205   base::Lock lock_;
    206   std::queue<base::PendingTask*> pending_tasks_;
    207 };
    208 
    209 #endif  // CHROME_FRAME_CHROME_FRAME_DELEGATE_H_
    210