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