Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: chrome_frame/infobar_manager.cc

Issue 4766003: Preview CL for adding an Infobar facility to Google Chrome Frame.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 // Implementation of the manager for infobar windows.
6
7 #include "chrome_frame/infobar_manager.h"
8
9 #include <atlbase.h>
10 #include <atlapp.h> // Must be included AFTER base.
11 #include <atlcrack.h>
12 #include <atlmisc.h>
13 #include <atlwin.h>
14
15 #include "base/logging.h"
16 #include "base/task_queue.h"
17 //#include "ceee/common/windows_constants.h"
18 #include "chrome_frame/utils.h"
19
20 namespace {
21
22 const wchar_t kIeTabContentParentWindowClass[] = L"Shell DocObject View";
23
24 } // namespace
25
26 DISABLE_RUNNABLE_METHOD_REFCOUNT(InfobarManager);
27 DISABLE_RUNNABLE_METHOD_REFCOUNT(InfobarManager::DisplacedWindowManager);
28
29
30 InfobarManager::InfobarHostImpl::InfobarHostImpl(InfobarManager *manager)
31 : manager_(manager) {
32 }
33
34 HWND InfobarManager::InfobarHostImpl::GetContainerWindow() {
35 return manager_->container_window_;
36 }
37
38 void InfobarManager::InfobarHostImpl::UpdateLayout() {
39 manager_->UpdateLayout();
40 }
41
42 // DisplacedWindowManager subclasses IE content window's container window,
43 // handles WM_NCCALCSIZE to resize its client area. It also handles WM_SIZE and
44 // WM_MOVE messages to make infobars consistent with IE content window's size
45 // and position.
46 //
47 // Finally, allows delayed tasks to be scheduled on the window's event loop.
48 class InfobarManager::DisplacedWindowManager
49 : public CWindowImpl<DisplacedWindowManager> {
50 public:
51 DisplacedWindowManager(InfobarManager* manager)
52 : infobar_manager_(manager) {
53 }
54
55 // Returns true if the window is successfully subclassed, in which case this
56 // instance will take responsibility for its own destruction when the window
57 // is destroyed. If this method returns false, the caller should delete the
58 // instance immediately.
59 bool Initialize(HWND displaced_hwnd) {
60 PinModule();
61 if (!SubclassWindow(displaced_hwnd)) {
62 LOG(DFATAL) << "Failed to subclass IE Renderer HWND for infobar "
63 << "installation.";
64 return false;
65 }
66 return true;
67 }
68
69 virtual ~DisplacedWindowManager() {
70 if (IsWindow())
71 UnsubclassWindow();
72 }
73
74 // Triggers a deferred re-evaluation of the dimensions of the displaced
75 // window. InfobarManager::AdjustDisplacedWindowDimensions will be called
76 // with the natural dimensions of the displaced window.
77 virtual void UpdateLayout() {
78 PushTask(
79 NewRunnableMethod(this, &DisplacedWindowManager::DoUpdateLayout));
80 }
81
82 // Schedules a deferred task on the window message loop of this instance's
83 // managed window. The task may not occur if the window is destroyed first.
84 virtual void PushTask(Task* task) {
85 task_queue_.Push(task);
86 if (IsWindow())
87 PostMessage(TM_RUN_TASK_QUEUE, 0, 0);
88 }
89
90 BEGIN_MSG_MAP_EX(DisplacedWindowManager)
91 MSG_WM_NCCALCSIZE(OnNcCalcSize)
92 MSG_WM_DESTROY(OnDestroy)
93 MESSAGE_HANDLER(TM_RUN_TASK_QUEUE, OnRunTaskQueue)
94 END_MSG_MAP()
95
96 private:
97 enum DisplacedWindowUserMessages {
98 TM_RUN_TASK_QUEUE = WM_USER + 600,
99 };
100
101 LRESULT OnRunTaskQueue(UINT message,
102 WPARAM wparam,
103 LPARAM lparam,
104 BOOL& handled) {
105 task_queue_.Run();
106 handled = TRUE;
107 return 0;
108 }
109
110 void DoUpdateLayout() {
111 // Call SetWindowPos with SWP_FRAMECHANGED for IE window, then IE
112 // window would receive WM_NCCALCSIZE to recalculate its client size.
113 if (IsWindow())
114 ::SetWindowPos(m_hWnd,
115 NULL, 0, 0, 0, 0,
116 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
117 SWP_FRAMECHANGED);
118 }
119
120 // Handles WM_NCCALCSIZE message.
121 LRESULT OnNcCalcSize(BOOL calc_valid_rects, LPARAM lparam) {
122 // Adjust client area for infobar.
123 LRESULT ret = DefWindowProc(WM_NCCALCSIZE,
124 static_cast<WPARAM>(calc_valid_rects), lparam);
125 // Whether calc_valid_rects is true or false, we could treat beginning of
126 // lparam as a RECT object.
127 RECT* rect = reinterpret_cast<RECT*>(lparam);
128 if (infobar_manager_ != NULL)
129 infobar_manager_->AdjustDisplacedWindowDimensions(rect);
130
131 // If infobars reserve all the space and rect becomes empty, the container
132 // window won't receive subsequent WM_SIZE and WM_MOVE messages.
133 // In this case, we have to explicitly notify infobars to update their
134 // position.
135 //if (rect->right - rect->left <= 0 || rect->bottom - rect->top <= 0)
136 // PushTask(
137 // NewRunnableMethod(infobar_manager_,
138 // &InfobarManager::OnDisplacedWindowPositionChange)) ;
139 return ret;
140 }
141
142 // The displaced window has been destroyed. Inform the InfobarManager, who
143 // will orphan this instance. We will delete ourselves in OnFinalMessage.
144 void OnDestroy() {
145 infobar_manager_->OnDisplacedWindowDestroyed();
146 }
147
148 void OnFinalMessage(HWND) {
149 delete this;
150 }
151
152 InfobarManager* infobar_manager_;
153 TaskQueue task_queue_;
154 DISALLOW_COPY_AND_ASSIGN(DisplacedWindowManager);
155 };
156
157 InfobarManager::InfobarManager(HWND tab_window)
158 : container_window_(tab_window),
159 displaced_window_manager_(NULL),
160 infobar_host_impl_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
161 for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
amit 2010/11/12 00:04:49 Feels like an overkill for our rudimentary infobar
erikwright (departed) 2010/11/24 06:24:56 The TOP vs BOTTOM and sliding is unnecessary, but
162 infobars_[index].reset(
163 new InfobarWindow(static_cast<InfobarType>(index),
164 &infobar_host_impl_));
165 }
166 }
167
168 HRESULT InfobarManager::Show(InfobarContent* content,
169 InfobarType type,
170 int max_height) {
171 if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE ||
grt (UTC plus 2) 2010/11/10 17:59:29 This looks like programmer error. Change to DCHEC
erikwright (departed) 2010/11/24 06:24:56 Yes. A relic of the original code. Ideally, I'd li
172 infobars_[type] == NULL) {
grt (UTC plus 2) 2010/11/10 17:59:29 How about this one, programmer error or something
erikwright (departed) 2010/11/24 06:24:56 Yes. I'm updating it to only return success or fai
173 return E_INVALIDARG;
174 }
175
176 HRESULT hr = infobars_[type]->Show(content, max_height);
177 return hr;
178 }
179
180 bool InfobarManager::UpdateLayout() {
181 if (FindDisplacedWindow()) {
182 displaced_window_manager_->UpdateLayout();
183 return true;
184 } else {
185 return false;
186 }
187 }
188
189 HRESULT InfobarManager::Hide(InfobarType type) {
190 if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE ||
191 infobars_[type] == NULL) {
192 return E_INVALIDARG;
193 }
194
195 infobars_[type]->Hide();
196 return S_OK;
197 }
198
199 void InfobarManager::HideAll() {
200 for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index)
201 Hide(static_cast<InfobarType>(index));
202 }
203
204 // Callback function for EnumChildWindows. lParam should be the pointer to
205 // HWND variable where the handle of the window which class is
206 // kIeTabContentParentWindowClass will be written.
207 static BOOL CALLBACK FindDisplacedWindowProc(HWND hwnd, LPARAM lparam) {
208 HWND* window_handle = reinterpret_cast<HWND*>(lparam);
209 if (NULL == window_handle) {
grt (UTC plus 2) 2010/11/10 17:59:29 I prefer this style of comparison. For consistenc
erikwright (departed) 2010/11/24 06:24:56 Agreed. Not the least because scoped_ptr does not
210 // It makes no sense to continue enumeration.
211 return FALSE;
212 }
213
214 // Variable to hold the class name. The size does not matter as long as it
215 // is at least can hold kIeTabContentParentWindowClass.
216 wchar_t class_name[100];
217 if (::GetClassName(hwnd, class_name, arraysize(class_name)) &&
218 lstrcmpi(kIeTabContentParentWindowClass, class_name) == 0) {
219 // We found the window. Return its handle and stop enumeration.
220 *window_handle = hwnd;
221 return FALSE;
222 }
223 return TRUE;
224 }
225
226 bool InfobarManager::FindDisplacedWindow() {
227 if (displaced_window_manager_ == NULL) {
228 if (::IsWindow(container_window_)) {
229 // Find the window which is the container for the HTML view (parent of
230 // the content).
231 HWND displaced_window = NULL;
232 ::EnumChildWindows(container_window_, FindDisplacedWindowProc,
233 reinterpret_cast<LPARAM>(&displaced_window));
234
235 if (displaced_window == NULL) {
236 LOG(DFATAL) << "Failed to locate IE renderer HWND to displace for "
237 << "Infobar installation.";
238 } else {
239 scoped_ptr<DisplacedWindowManager> displaced_window_manager(
240 new DisplacedWindowManager(this));
241 if (displaced_window_manager->Initialize(displaced_window)) {
242 displaced_window_manager_ = displaced_window_manager.release();
243 }
244 }
245 }
246 }
247
248 return displaced_window_manager_ != NULL;
249 }
250
251 void InfobarManager::AdjustDisplacedWindowDimensions(RECT* rect) {
252 if (rect == NULL)
253 return;
254
255 for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
256 if (infobars_[index] != NULL)
257 infobars_[index]->ReserveSpace(rect);
258 }
259 }
260
261 void InfobarManager::OnDisplacedWindowDestroyed() {
262 for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
263 if (infobars_[index] != NULL)
264 infobars_[index]->Hide();
265 }
266 // Will be deleted in its OnFinalMessage
267 displaced_window_manager_ = NULL;
268 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698