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