OLD | NEW |
| (Empty) |
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 ContextMenuModel; | |
24 | |
25 namespace net { | |
26 class URLRequestStatus; | |
27 } | |
28 | |
29 namespace gfx { | |
30 class Rect; | |
31 } | |
32 | |
33 // A common interface supported by all the browser specific ChromeFrame | |
34 // implementations. | |
35 class ChromeFrameDelegate { | |
36 public: | |
37 typedef HWND WindowType; | |
38 | |
39 virtual WindowType GetWindow() const = 0; | |
40 virtual void GetBounds(RECT* bounds) = 0; | |
41 virtual std::string GetDocumentUrl() = 0; | |
42 virtual void OnAutomationServerReady() = 0; | |
43 virtual void OnAutomationServerLaunchFailed( | |
44 AutomationLaunchResult reason, const std::string& server_version) = 0; | |
45 virtual bool OnMessageReceived(const IPC::Message& msg) = 0; | |
46 virtual void OnChannelError() = 0; | |
47 | |
48 // This remains in interface since we call it if Navigate() | |
49 // returns immediate error. | |
50 virtual void OnLoadFailed(int error_code, const std::string& url) = 0; | |
51 | |
52 // Returns true if this instance is alive and well for processing automation | |
53 // messages. | |
54 virtual bool IsValid() const = 0; | |
55 | |
56 protected: | |
57 virtual ~ChromeFrameDelegate() {} | |
58 }; | |
59 | |
60 extern UINT kAutomationServerReady; | |
61 extern UINT kMessageFromChromeFrame; | |
62 | |
63 class ChromeFrameDelegateImpl : public ChromeFrameDelegate { | |
64 public: | |
65 virtual WindowType GetWindow() { return NULL; } | |
66 virtual void GetBounds(RECT* bounds) {} | |
67 virtual std::string GetDocumentUrl() { return std::string(); } | |
68 virtual void OnAutomationServerReady() {} | |
69 virtual void OnAutomationServerLaunchFailed( | |
70 AutomationLaunchResult reason, const std::string& server_version) {} | |
71 virtual void OnLoadFailed(int error_code, const std::string& url) {} | |
72 virtual bool OnMessageReceived(const IPC::Message& msg); | |
73 virtual void OnChannelError() {} | |
74 | |
75 static bool IsTabMessage(const IPC::Message& message); | |
76 | |
77 virtual bool IsValid() const { | |
78 return true; | |
79 } | |
80 }; | |
81 | |
82 // This interface enables tasks to be marshaled to desired threads. | |
83 class TaskMarshaller { // NOLINT | |
84 public: | |
85 virtual void PostTask(const tracked_objects::Location& from_here, | |
86 const base::Closure& task) = 0; | |
87 }; | |
88 | |
89 // T is expected to be something CWindowImpl derived, or at least to have | |
90 // PostMessage(UINT, WPARAM) method. Do not forget to CHAIN_MSG_MAP | |
91 template <class T> class TaskMarshallerThroughWindowsMessages | |
92 : public TaskMarshaller { | |
93 public: | |
94 TaskMarshallerThroughWindowsMessages() {} | |
95 virtual void PostTask(const tracked_objects::Location& posted_from, | |
96 const base::Closure& task) OVERRIDE { | |
97 T* this_ptr = static_cast<T*>(this); | |
98 if (this_ptr->IsWindow()) { | |
99 this_ptr->AddRef(); | |
100 base::PendingTask* pending_task = | |
101 new base::PendingTask(posted_from, task); | |
102 PushTask(pending_task); | |
103 this_ptr->PostMessage(MSG_EXECUTE_TASK, | |
104 reinterpret_cast<WPARAM>(pending_task)); | |
105 } else { | |
106 DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window."; | |
107 } | |
108 } | |
109 | |
110 protected: | |
111 ~TaskMarshallerThroughWindowsMessages() { | |
112 DeleteAllPendingTasks(); | |
113 } | |
114 | |
115 void DeleteAllPendingTasks() { | |
116 base::AutoLock lock(lock_); | |
117 DVLOG_IF(1, !pending_tasks_.empty()) << "Destroying " | |
118 << pending_tasks_.size() | |
119 << " pending tasks"; | |
120 while (!pending_tasks_.empty()) { | |
121 base::PendingTask* task = pending_tasks_.front(); | |
122 pending_tasks_.pop(); | |
123 delete task; | |
124 } | |
125 } | |
126 | |
127 BEGIN_MSG_MAP(PostMessageMarshaller) | |
128 MESSAGE_HANDLER(MSG_EXECUTE_TASK, ExecuteTask) | |
129 END_MSG_MAP() | |
130 | |
131 private: | |
132 enum { MSG_EXECUTE_TASK = WM_APP + 6 }; | |
133 inline LRESULT ExecuteTask(UINT, WPARAM wparam, LPARAM, | |
134 BOOL& handled) { // NOLINT | |
135 base::PendingTask* pending_task = | |
136 reinterpret_cast<base::PendingTask*>(wparam); | |
137 if (pending_task && PopTask(pending_task)) { | |
138 pending_task->task.Run(); | |
139 delete pending_task; | |
140 } | |
141 | |
142 T* this_ptr = static_cast<T*>(this); | |
143 this_ptr->Release(); | |
144 return 0; | |
145 } | |
146 | |
147 inline void PushTask(base::PendingTask* pending_task) { | |
148 base::AutoLock lock(lock_); | |
149 pending_tasks_.push(pending_task); | |
150 } | |
151 | |
152 // If |pending_task| is front of the queue, removes the task and returns true, | |
153 // otherwise we assume this is an already destroyed task (but Window message | |
154 // had remained in the thread queue). | |
155 inline bool PopTask(base::PendingTask* pending_task) { | |
156 base::AutoLock lock(lock_); | |
157 if (!pending_tasks_.empty() && pending_task == pending_tasks_.front()) { | |
158 pending_tasks_.pop(); | |
159 return true; | |
160 } | |
161 | |
162 return false; | |
163 } | |
164 | |
165 base::Lock lock_; | |
166 std::queue<base::PendingTask*> pending_tasks_; | |
167 }; | |
168 | |
169 #endif // CHROME_FRAME_CHROME_FRAME_DELEGATE_H_ | |
OLD | NEW |