1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Implementation of the manager for infobar windows.
#include "ceee/ie/plugin/bho/infobar_manager.h"
#include <atlbase.h>
#include <atlapp.h> // Must be included AFTER base.
#include <atlcrack.h>
#include <atlmisc.h>
#include <atlwin.h>
#include "base/logging.h"
#include "ceee/common/windows_constants.h"
#include "chrome_frame/utils.h"
namespace {
enum ContainerWindowUserMessages {
TM_NOTIFY_UPDATE_POSITION = WM_USER + 600,
TM_DELAYED_CLOSE_INFOBAR = (TM_NOTIFY_UPDATE_POSITION + 1),
};
} // namespace
namespace infobar_api {
// ContainerWindow subclasses IE content window's container window, handles
// WM_NCCALCSIZE to resize its client area. It also handles WM_SIZE and WM_MOVE
// messages to make infobars consistent with IE content window's size and
// position.
class InfobarManager::ContainerWindow : public CWindowImpl<ContainerWindow> {
public:
ContainerWindow(HWND container, InfobarManager* manager)
: infobar_manager_(manager) {
PinModule();
destroyed_ = !::IsWindow(container) || !SubclassWindow(container);
}
virtual ~ContainerWindow() {
if (!destroyed_)
UnsubclassWindow();
}
bool destroyed() const {
return destroyed_;
}
BEGIN_MSG_MAP_EX(ContainerWindow)
MSG_WM_NCCALCSIZE(OnNcCalcSize)
MSG_WM_SIZE(OnSize)
MSG_WM_MOVE(OnMove)
MSG_WM_DESTROY(OnDestroy)
MESSAGE_HANDLER(TM_NOTIFY_UPDATE_POSITION, OnNotifyUpdatePosition)
MESSAGE_HANDLER(TM_DELAYED_CLOSE_INFOBAR, OnDelayedCloseInfobar)
END_MSG_MAP()
private:
// Handles WM_NCCALCSIZE message.
LRESULT OnNcCalcSize(BOOL calc_valid_rects, LPARAM lparam) {
// Adjust client area for infobar.
LRESULT ret = DefWindowProc(WM_NCCALCSIZE,
static_cast<WPARAM>(calc_valid_rects), lparam);
// Whether calc_valid_rects is true or false, we could treat beginning of
// lparam as a RECT object.
RECT* rect = reinterpret_cast<RECT*>(lparam);
if (infobar_manager_ != NULL)
infobar_manager_->OnContainerWindowNcCalcSize(rect);
// If infobars reserve all the space and rect becomes empty, the container
// window won't receive subsequent WM_SIZE and WM_MOVE messages.
// In this case, we have to explicitly notify infobars to update their
// position.
if (rect->right - rect->left <= 0 || rect->bottom - rect->top <= 0)
PostMessage(TM_NOTIFY_UPDATE_POSITION, 0, 0);
return ret;
}
// Handles WM_SIZE message.
void OnSize(UINT type, CSize size) {
DefWindowProc(WM_SIZE, static_cast<WPARAM>(type),
MAKELPARAM(size.cx, size.cy));
if (infobar_manager_ != NULL)
infobar_manager_->OnContainerWindowUpdatePosition();
}
// Handles WM_MOVE message.
void OnMove(CPoint point) {
if (infobar_manager_ != NULL)
infobar_manager_->OnContainerWindowUpdatePosition();
}
// Handles WM_DESTROY message.
void OnDestroy() {
// When refreshing IE window, this window may be destroyed.
if (infobar_manager_ != NULL)
infobar_manager_->OnContainerWindowDestroy();
if (m_hWnd && IsWindow())
UnsubclassWindow();
destroyed_ = true;
}
// Handles TM_NOTIFY_UPDATE_POSITION message - delayed window resize message.
LRESULT OnNotifyUpdatePosition(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled) {
if (infobar_manager_ != NULL)
infobar_manager_->OnContainerWindowUpdatePosition();
handled = TRUE;
return 0;
}
// Handles TM_DELAYED_CLOSE_INFOBAR - delayed infobar window close request.
LRESULT OnDelayedCloseInfobar(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled) {
if (infobar_manager_ != NULL) {
InfobarType type = static_cast<InfobarType>(wparam);
infobar_manager_->OnContainerWindowDelayedCloseInfobar(type);
}
handled = TRUE;
return 0;
}
// Pointer to infobar manager. This object is not owned by the class instance.
InfobarManager* infobar_manager_;
// True is this window was destroyed or not subclassed.
bool destroyed_;
DISALLOW_COPY_AND_ASSIGN(ContainerWindow);
};
InfobarManager::InfobarManager(HWND tab_window)
: tab_window_(tab_window) {
for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
// Note that when InfobarManager is being initialized the IE has not created
// the tab. Therefore we cannot find the container window here and have to
// pass interface for a function that finds windows to be called later.
infobars_[index].reset(
InfobarWindow::CreateInfobar(static_cast<InfobarType>(index), this));
}
}
HRESULT InfobarManager::Show(InfobarType type, int max_height,
const std::wstring& url, bool slide) {
if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE ||
infobars_[type] == NULL) {
return E_INVALIDARG;
}
// Set the URL. If the window is not created it will navigate there as soon as
// it is created.
infobars_[type]->Navigate(url);
// Create the window if not created.
if (!infobars_[type]->IsWindow()) {
infobars_[type]->Create(tab_window_, NULL, NULL,
WS_CHILD | WS_CLIPCHILDREN);
}
if (!infobars_[type]->IsWindow())
return E_UNEXPECTED;
HRESULT hr = infobars_[type]->Show(max_height, slide);
return hr;
}
HRESULT InfobarManager::Hide(InfobarType type) {
if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE ||
infobars_[type] == NULL) {
return E_INVALIDARG;
}
// There is a choice either to hide or to destroy the infobar window.
// This implementation destroys the infobar to save resources and stop all
// scripts that possibly still run in the window. If we want to just hide the
// infobar window instead then we should change Reset to Hide here, possibly
// navigate the infobar window to "about:blank" and make sure that the code
// in Show() does not try to create the chrome frame window again.
infobars_[type]->Reset();
return S_OK;
}
void InfobarManager::HideAll() {
for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index)
Hide(static_cast<InfobarType>(index));
}
// Callback function for EnumChildWindows. lParam should be the pointer to
// HWND variable where the handle of the window which class is
// kIeTabContentParentWindowClass will be written.
static BOOL CALLBACK FindContentParentWindowsProc(HWND hwnd, LPARAM lparam) {
HWND* window_handle = reinterpret_cast<HWND*>(lparam);
if (NULL == window_handle) {
// It makes no sense to continue enumeration.
return FALSE;
}
// Variable to hold the class name. The size does not matter as long as it
// is at least can hold kIeTabContentParentWindowClass.
wchar_t class_name[100];
if (::GetClassName(hwnd, class_name, arraysize(class_name)) &&
lstrcmpi(windows::kIeTabContentParentWindowClass, class_name) == 0) {
// We found the window. Return its handle and stop enumeration.
*window_handle = hwnd;
return FALSE;
}
return TRUE;
}
HWND InfobarManager::GetContainerWindow() {
if (container_window_ != NULL && container_window_->destroyed())
container_window_.reset(NULL);
if (container_window_ == NULL) {
if (tab_window_ != NULL && ::IsWindow(tab_window_)) {
// Find the window which is the container for the HTML view (parent of
// the content).
HWND content_parent_window = NULL;
::EnumChildWindows(tab_window_, FindContentParentWindowsProc,
reinterpret_cast<LPARAM>(&content_parent_window));
DCHECK(content_parent_window);
if (content_parent_window != NULL) {
container_window_.reset(
new ContainerWindow(content_parent_window, this));
}
}
}
DCHECK(container_window_ != NULL && container_window_->IsWindow());
return container_window_->m_hWnd;
}
void InfobarManager::OnWindowClose(InfobarType type) {
// This callback is called from CF callback so we should not destroy the
// infobar window right away as it may result on deleting the object that
// started this callback. So instead we post ourtselves the message.
if (container_window_ != NULL)
container_window_->PostMessage(TM_DELAYED_CLOSE_INFOBAR,
static_cast<WPARAM>(type), 0);
}
void InfobarManager::OnContainerWindowNcCalcSize(RECT* rect) {
if (rect == NULL)
return;
for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
if (infobars_[index] != NULL)
infobars_[index]->ReserveSpace(rect);
}
}
void InfobarManager::OnContainerWindowUpdatePosition() {
for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
if (infobars_[index] != NULL)
infobars_[index]->UpdatePosition();
}
}
void InfobarManager::OnContainerWindowDelayedCloseInfobar(InfobarType type) {
// Hide the infobar window. Parameter validation is handled in Hide().
Hide(type);
}
void InfobarManager::OnContainerWindowDestroy() {
for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
if (infobars_[index] != NULL)
infobars_[index]->Reset();
}
}
} // namespace infobar_api
|