OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/external_tab_container.h" | 5 #include "chrome/browser/external_tab_container.h" |
6 | 6 |
7 #include "app/win_util.h" | 7 #include "app/win_util.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/win_util.h" | 9 #include "base/win_util.h" |
10 #include "chrome/browser/automation/automation_provider.h" | 10 #include "chrome/browser/automation/automation_provider.h" |
11 #include "chrome/browser/browser.h" | 11 #include "chrome/browser/browser.h" |
12 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 12 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
13 #include "chrome/browser/load_notification_details.h" | 13 #include "chrome/browser/load_notification_details.h" |
14 #include "chrome/browser/profile.h" | 14 #include "chrome/browser/profile.h" |
15 #include "chrome/browser/tab_contents/provisional_load_details.h" | 15 #include "chrome/browser/tab_contents/provisional_load_details.h" |
16 #include "chrome/browser/tab_contents/tab_contents.h" | 16 #include "chrome/browser/tab_contents/tab_contents.h" |
17 #include "chrome/browser/views/tab_contents/tab_contents_container.h" | 17 #include "chrome/browser/views/tab_contents/tab_contents_container.h" |
18 #include "chrome/common/chrome_constants.h" | 18 #include "chrome/common/chrome_constants.h" |
19 #include "chrome/common/notification_service.h" | 19 #include "chrome/common/notification_service.h" |
20 #include "chrome/test/automation/automation_messages.h" | 20 #include "chrome/test/automation/automation_messages.h" |
21 // Included for SetRootViewForHWND. | |
22 #include "views/widget/widget_win.h" | |
23 | 21 |
24 static const wchar_t kWindowObjectKey[] = L"ChromeWindowObject"; | 22 static const wchar_t kWindowObjectKey[] = L"ChromeWindowObject"; |
25 | 23 |
26 // TODO(sanjeevr): The external_accel_table_ and external_accel_entry_count_ | 24 // TODO(sanjeevr): The external_accel_table_ and external_accel_entry_count_ |
27 // member variables are now obsolete and we don't use them. | 25 // member variables are now obsolete and we don't use them. |
28 // We need to remove them. | 26 // We need to remove them. |
29 ExternalTabContainer::ExternalTabContainer( | 27 ExternalTabContainer::ExternalTabContainer( |
30 AutomationProvider* automation) | 28 AutomationProvider* automation) |
31 : automation_(automation), | 29 : automation_(automation), |
32 root_view_(this), | |
33 tab_contents_(NULL), | 30 tab_contents_(NULL), |
34 external_accel_table_(NULL), | 31 external_accel_table_(NULL), |
35 external_accel_entry_count_(0), | 32 external_accel_entry_count_(0), |
36 tab_contents_container_(NULL), | 33 tab_contents_container_(NULL), |
37 tab_handle_(0), | 34 tab_handle_(0), |
38 ignore_next_load_notification_(false) { | 35 ignore_next_load_notification_(false) { |
39 } | 36 } |
40 | 37 |
41 ExternalTabContainer::~ExternalTabContainer() { | 38 ExternalTabContainer::~ExternalTabContainer() { |
42 Uninitialize(m_hWnd); | 39 Uninitialize(GetNativeView()); |
43 } | 40 } |
44 | 41 |
45 bool ExternalTabContainer::Init(Profile* profile, HWND parent, | 42 bool ExternalTabContainer::Init(Profile* profile, |
46 const gfx::Rect& dimensions, | 43 HWND parent, |
47 unsigned int style) { | 44 const gfx::Rect& bounds, |
45 DWORD style) { | |
48 if (IsWindow()) { | 46 if (IsWindow()) { |
49 NOTREACHED(); | 47 NOTREACHED(); |
50 return false; | 48 return false; |
51 } | 49 } |
52 | 50 |
53 // First create the container window | 51 set_window_style(WS_POPUP); |
54 if (!Create(NULL, dimensions.ToRECT())) { | 52 views::WidgetWin::Init(parent, bounds, true); |
tommi (sloooow) - chröme
2009/05/27 20:50:29
this changes the semantics from before where NULL
| |
55 NOTREACHED(); | |
56 return false; | |
57 } | |
58 | 53 |
59 // We don't ever remove the prop because the lifetime of this object | 54 // We don't ever remove the prop because the lifetime of this object |
60 // is the same as the lifetime of the window | 55 // is the same as the lifetime of the window |
61 SetProp(*this, kWindowObjectKey, this); | 56 SetProp(GetNativeView(), kWindowObjectKey, this); |
62 | 57 |
63 views::SetRootViewForHWND(m_hWnd, &root_view_); | |
64 // CreateFocusManager will subclass this window and delete the FocusManager | |
65 // instance when this window goes away. | |
66 views::FocusManager* focus_manager = | 58 views::FocusManager* focus_manager = |
67 views::FocusManager::CreateFocusManager(m_hWnd, GetRootView()); | 59 views::FocusManager::GetFocusManager(GetNativeView()); |
68 | |
69 DCHECK(focus_manager); | |
70 focus_manager->AddKeystrokeListener(this); | 60 focus_manager->AddKeystrokeListener(this); |
71 | 61 |
72 tab_contents_ = new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL); | 62 tab_contents_ = new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL); |
73 tab_contents_->set_delegate(this); | 63 tab_contents_->set_delegate(this); |
74 tab_contents_->render_view_host()->AllowExternalHostBindings(); | 64 tab_contents_->render_view_host()->AllowExternalHostBindings(); |
75 | 65 |
76 // Create a TabContentsContainer to handle focus cycling using Tab and | 66 // Create a TabContentsContainer to handle focus cycling using Tab and |
77 // Shift-Tab. | 67 // Shift-Tab. |
78 tab_contents_container_ = new TabContentsContainer; | 68 tab_contents_container_ = new TabContentsContainer; |
79 root_view_.AddChildView(tab_contents_container_); | 69 SetContentsView(tab_contents_container_); |
70 | |
80 // Note that SetTabContents must be called after AddChildView is called | 71 // Note that SetTabContents must be called after AddChildView is called |
81 tab_contents_container_->ChangeTabContents(tab_contents_); | 72 tab_contents_container_->ChangeTabContents(tab_contents_); |
82 | 73 |
83 NavigationController* controller = &tab_contents_->controller(); | 74 NavigationController* controller = &tab_contents_->controller(); |
84 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, | 75 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, |
85 Source<NavigationController>(controller)); | 76 Source<NavigationController>(controller)); |
86 registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR, | 77 registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR, |
87 Source<NavigationController>(controller)); | 78 Source<NavigationController>(controller)); |
88 registrar_.Add(this, NotificationType::LOAD_STOP, | 79 registrar_.Add(this, NotificationType::LOAD_STOP, |
89 Source<NavigationController>(controller)); | 80 Source<NavigationController>(controller)); |
90 NotificationService::current()->Notify( | 81 NotificationService::current()->Notify( |
91 NotificationType::EXTERNAL_TAB_CREATED, | 82 NotificationType::EXTERNAL_TAB_CREATED, |
92 Source<NavigationController>(controller), | 83 Source<NavigationController>(controller), |
93 NotificationService::NoDetails()); | 84 NotificationService::NoDetails()); |
94 | 85 |
95 // We need WS_POPUP to be on the window during initialization, but | 86 // We need WS_POPUP to be on the window during initialization, but |
96 // once initialized we apply the requested style which may or may not | 87 // once initialized we apply the requested style which may or may not |
97 // include the popup bit. | 88 // include the popup bit. |
98 // Note that it's important to do this before we call SetParent since | 89 // Note that it's important to do this before we call SetParent since |
99 // during the SetParent call we will otherwise get a WA_ACTIVATE call | 90 // during the SetParent call we will otherwise get a WA_ACTIVATE call |
100 // that causes us to steal the current focus. | 91 // that causes us to steal the current focus. |
101 ModifyStyle(WS_POPUP, style, 0); | 92 SetWindowLong(GWL_STYLE, (GetWindowLong(GWL_STYLE) & ~WS_POPUP) | style); |
ananta
2009/05/27 13:46:24
Should this be GetWindowLong(GWL_STYLE) | WS_POPUP
tommi (sloooow) - chröme
2009/05/27 20:50:29
I think this is how it should be. We want to remo
| |
102 | 93 |
103 // Now apply the parenting and style | 94 // Now apply the parenting and style |
104 if (parent) | 95 if (parent) |
105 SetParent(parent); | 96 SetParent(GetNativeView(), parent); |
106 | 97 |
107 ::ShowWindow(tab_contents_->GetNativeView(), SW_SHOWNA); | 98 ::ShowWindow(tab_contents_->GetNativeView(), SW_SHOWNA); |
108 return true; | 99 return true; |
109 } | 100 } |
110 | 101 |
111 bool ExternalTabContainer::Uninitialize(HWND window) { | 102 void ExternalTabContainer::SetAccelerators(HACCEL accel_table, |
112 if (::IsWindow(window)) { | 103 int accel_table_entry_count) { |
113 views::FocusManager* focus_manager = | 104 external_accel_table_ = accel_table; |
114 views::FocusManager::GetFocusManager(window); | 105 external_accel_entry_count_ = accel_table_entry_count; |
115 if (focus_manager) { | |
116 focus_manager->RemoveKeystrokeListener(this); | |
117 } | |
118 } | |
119 | |
120 root_view_.RemoveAllChildViews(true); | |
121 if (tab_contents_) { | |
122 NotificationService::current()->Notify( | |
123 NotificationType::EXTERNAL_TAB_CLOSED, | |
124 Source<NavigationController>(&tab_contents_->controller()), | |
125 Details<ExternalTabContainer>(this)); | |
126 | |
127 delete tab_contents_; | |
128 tab_contents_ = NULL; | |
129 } | |
130 | |
131 return true; | |
132 } | 106 } |
133 | 107 |
134 void ExternalTabContainer::OnFinalMessage(HWND window) { | 108 void ExternalTabContainer::ProcessUnhandledAccelerator(const MSG& msg) { |
135 delete this; | 109 // We just received an accelerator key that we had sent to external host |
110 // back. Since the external host was not interested in handling this, we | |
111 // need to dispatch this message as if we had just peeked this out. (we | |
112 // also need to call TranslateMessage to generate a WM_CHAR if needed). | |
113 TranslateMessage(&msg); | |
114 DispatchMessage(&msg); | |
136 } | 115 } |
137 | 116 |
138 LRESULT ExternalTabContainer::OnSize(UINT, WPARAM, LPARAM, BOOL& handled) { | 117 void ExternalTabContainer::SetInitialFocus(bool reverse) { |
118 DCHECK(tab_contents_); | |
139 if (tab_contents_) { | 119 if (tab_contents_) { |
140 RECT client_rect = {0}; | 120 static_cast<TabContents*>(tab_contents_)->Focus(); |
141 GetClientRect(&client_rect); | 121 static_cast<TabContents*>(tab_contents_)->SetInitialFocus(reverse); |
142 ::SetWindowPos(tab_contents_->GetNativeView(), NULL, client_rect.left, | |
143 client_rect.top, client_rect.right - client_rect.left, | |
144 client_rect.bottom - client_rect.top, SWP_NOZORDER); | |
145 } | 122 } |
146 return 0; | |
147 } | 123 } |
148 | 124 |
149 LRESULT ExternalTabContainer::OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) { | 125 // static |
150 Uninitialize(m_hWnd); | 126 bool ExternalTabContainer::IsExternalTabContainer(HWND window) { |
151 return 0; | 127 std::wstring class_name = win_util::GetClassName(window); |
128 return _wcsicmp(class_name.c_str(), chrome::kExternalTabWindowClass) == 0; | |
tommi (sloooow) - chröme
2009/05/27 20:50:29
maybe
return class_name.compare(chrome::kExternalT
| |
152 } | 129 } |
153 | 130 |
131 // static | |
132 ExternalTabContainer* ExternalTabContainer::GetContainerForTab( | |
133 HWND tab_window) { | |
134 HWND parent_window = ::GetParent(tab_window); | |
135 if (!::IsWindow(parent_window)) { | |
136 return NULL; | |
137 } | |
138 if (!IsExternalTabContainer(parent_window)) { | |
139 return NULL; | |
140 } | |
141 ExternalTabContainer* container = reinterpret_cast<ExternalTabContainer*>( | |
142 GetProp(parent_window, kWindowObjectKey)); | |
143 return container; | |
144 } | |
145 | |
146 //////////////////////////////////////////////////////////////////////////////// | |
147 // ExternalTabContainer, TabContentsDelegate implementation: | |
148 | |
154 void ExternalTabContainer::OpenURLFromTab(TabContents* source, | 149 void ExternalTabContainer::OpenURLFromTab(TabContents* source, |
155 const GURL& url, | 150 const GURL& url, |
156 const GURL& referrer, | 151 const GURL& referrer, |
157 WindowOpenDisposition disposition, | 152 WindowOpenDisposition disposition, |
158 PageTransition::Type transition) { | 153 PageTransition::Type transition) { |
159 switch (disposition) { | 154 switch (disposition) { |
160 case CURRENT_TAB: | 155 case CURRENT_TAB: |
161 case SINGLETON_TAB: | 156 case SINGLETON_TAB: |
162 case NEW_FOREGROUND_TAB: | 157 case NEW_FOREGROUND_TAB: |
163 case NEW_BACKGROUND_TAB: | 158 case NEW_BACKGROUND_TAB: |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 void ExternalTabContainer::ForwardMessageToExternalHost( | 229 void ExternalTabContainer::ForwardMessageToExternalHost( |
235 const std::string& message, const std::string& origin, | 230 const std::string& message, const std::string& origin, |
236 const std::string& target) { | 231 const std::string& target) { |
237 if(automation_) { | 232 if(automation_) { |
238 automation_->Send( | 233 automation_->Send( |
239 new AutomationMsg_ForwardMessageToExternalHost(0, tab_handle_, | 234 new AutomationMsg_ForwardMessageToExternalHost(0, tab_handle_, |
240 message, origin, target)); | 235 message, origin, target)); |
241 } | 236 } |
242 } | 237 } |
243 | 238 |
239 ExtensionFunctionDispatcher* ExternalTabContainer:: | |
240 CreateExtensionFunctionDispatcher(RenderViewHost* render_view_host, | |
241 const std::string& extension_id) { | |
242 return new ExtensionFunctionDispatcher(render_view_host, NULL, extension_id); | |
243 } | |
244 | |
244 bool ExternalTabContainer::TakeFocus(bool reverse) { | 245 bool ExternalTabContainer::TakeFocus(bool reverse) { |
245 if (automation_) { | 246 if (automation_) { |
246 views::FocusManager* focus_manager = | 247 views::FocusManager* focus_manager = |
247 views::FocusManager::GetFocusManager(GetNativeView()); | 248 views::FocusManager::GetFocusManager(GetNativeView()); |
248 DCHECK(focus_manager); | 249 DCHECK(focus_manager); |
249 if (focus_manager) { | 250 if (focus_manager) { |
250 focus_manager->ClearFocus(); | 251 focus_manager->ClearFocus(); |
251 automation_->Send(new AutomationMsg_TabbedOut(0, tab_handle_, | 252 automation_->Send(new AutomationMsg_TabbedOut(0, tab_handle_, |
252 win_util::IsShiftPressed())); | 253 win_util::IsShiftPressed())); |
253 } | 254 } |
254 } | 255 } |
255 | 256 |
256 return true; | 257 return true; |
257 } | 258 } |
258 | 259 |
260 //////////////////////////////////////////////////////////////////////////////// | |
261 // ExternalTabContainer, NotificationObserver implementation: | |
262 | |
259 void ExternalTabContainer::Observe(NotificationType type, | 263 void ExternalTabContainer::Observe(NotificationType type, |
260 const NotificationSource& source, | 264 const NotificationSource& source, |
261 const NotificationDetails& details) { | 265 const NotificationDetails& details) { |
262 if (!automation_) | 266 if (!automation_) |
263 return; | 267 return; |
264 | 268 |
265 static const int kHttpClientErrorStart = 400; | 269 static const int kHttpClientErrorStart = 400; |
266 static const int kHttpServerErrorEnd = 510; | 270 static const int kHttpServerErrorEnd = 510; |
267 | 271 |
268 switch (type.value) { | 272 switch (type.value) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
309 0, tab_handle_, load_details->error_code(), load_details->url())); | 313 0, tab_handle_, load_details->error_code(), load_details->url())); |
310 | 314 |
311 ignore_next_load_notification_ = true; | 315 ignore_next_load_notification_ = true; |
312 break; | 316 break; |
313 } | 317 } |
314 default: | 318 default: |
315 NOTREACHED(); | 319 NOTREACHED(); |
316 } | 320 } |
317 } | 321 } |
318 | 322 |
319 void ExternalTabContainer::GetBounds(gfx::Rect* out, | 323 //////////////////////////////////////////////////////////////////////////////// |
320 bool including_frame) const { | 324 // ExternalTabContainer, views::WidgetWin overrides: |
321 CRect crect; | 325 |
322 GetWindowRect(&crect); | 326 void ExternalTabContainer::OnDestroy() { |
323 *out = gfx::Rect(crect); | 327 Uninitialize(GetNativeView()); |
328 WidgetWin::OnDestroy(); | |
324 } | 329 } |
325 | 330 |
326 void ExternalTabContainer::SetBounds(const gfx::Rect& bounds) { | 331 //////////////////////////////////////////////////////////////////////////////// |
327 SetBounds(bounds, NULL); | 332 // ExternalTabContainer, views::KeystrokeListener implementation: |
328 } | |
329 | |
330 void ExternalTabContainer::SetBounds(const gfx::Rect& bounds, | |
331 gfx::NativeView other_window) { | |
332 NOTIMPLEMENTED(); | |
333 } | |
334 | |
335 void ExternalTabContainer::Close() { | |
336 NOTIMPLEMENTED(); | |
337 } | |
338 | |
339 void ExternalTabContainer::CloseNow() { | |
340 NOTIMPLEMENTED(); | |
341 } | |
342 | |
343 void ExternalTabContainer::Show() { | |
344 NOTIMPLEMENTED(); | |
345 } | |
346 | |
347 void ExternalTabContainer::Hide() { | |
348 NOTIMPLEMENTED(); | |
349 } | |
350 | |
351 gfx::NativeView ExternalTabContainer::GetNativeView() const { | |
352 return m_hWnd; | |
353 } | |
354 | |
355 void ExternalTabContainer::PaintNow(const gfx::Rect& update_rect) { | |
356 RECT native_update_rect = update_rect.ToRECT(); | |
357 RedrawWindow(&native_update_rect, | |
358 NULL, | |
359 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_NOERASE); | |
360 } | |
361 | |
362 void ExternalTabContainer::SetOpacity(unsigned char opacity) { | |
363 NOTIMPLEMENTED(); | |
364 } | |
365 | |
366 views::RootView* ExternalTabContainer::GetRootView() { | |
367 return const_cast<views::RootView*>(&root_view_); | |
368 } | |
369 | |
370 bool ExternalTabContainer::IsVisible() const { | |
371 return !!::IsWindowVisible(*this); | |
372 } | |
373 | |
374 bool ExternalTabContainer::IsActive() const { | |
375 return win_util::IsWindowActive(*this); | |
376 } | |
377 | 333 |
378 bool ExternalTabContainer::ProcessKeyStroke(HWND window, UINT message, | 334 bool ExternalTabContainer::ProcessKeyStroke(HWND window, UINT message, |
379 WPARAM wparam, LPARAM lparam) { | 335 WPARAM wparam, LPARAM lparam) { |
380 if (!automation_) { | 336 if (!automation_) { |
381 return false; | 337 return false; |
382 } | 338 } |
383 if ((wparam == VK_TAB) && !win_util::IsCtrlPressed()) { | 339 if ((wparam == VK_TAB) && !win_util::IsCtrlPressed()) { |
384 // Tabs are handled separately (except if this is Ctrl-Tab or | 340 // Tabs are handled separately (except if this is Ctrl-Tab or |
385 // Ctrl-Shift-Tab) | 341 // Ctrl-Shift-Tab) |
386 return false; | 342 return false; |
(...skipping 18 matching lines...) Expand all Loading... | |
405 msg.message = message; | 361 msg.message = message; |
406 msg.wParam = wparam; | 362 msg.wParam = wparam; |
407 msg.lParam = lparam; | 363 msg.lParam = lparam; |
408 automation_->Send(new AutomationMsg_HandleAccelerator(0, tab_handle_, msg)); | 364 automation_->Send(new AutomationMsg_HandleAccelerator(0, tab_handle_, msg)); |
409 return true; | 365 return true; |
410 } | 366 } |
411 | 367 |
412 return false; | 368 return false; |
413 } | 369 } |
414 | 370 |
415 void ExternalTabContainer::SetAccelerators(HACCEL accel_table, | 371 //////////////////////////////////////////////////////////////////////////////// |
416 int accel_table_entry_count) { | 372 // ExternalTabContainer, private: |
417 external_accel_table_ = accel_table; | |
418 external_accel_entry_count_ = accel_table_entry_count; | |
419 } | |
420 | 373 |
421 void ExternalTabContainer::ProcessUnhandledAccelerator(const MSG& msg) { | 374 void ExternalTabContainer::Uninitialize(HWND window) { |
422 // We just received an accelerator key that we had sent to external host | 375 if (::IsWindow(window)) { |
423 // back. Since the external host was not interested in handling this, we | 376 views::FocusManager* focus_manager = |
424 // need to dispatch this message as if we had just peeked this out. (we | 377 views::FocusManager::GetFocusManager(window); |
425 // also need to call TranslateMessage to generate a WM_CHAR if needed). | 378 if (focus_manager) |
426 TranslateMessage(&msg); | 379 focus_manager->RemoveKeystrokeListener(this); |
427 DispatchMessage(&msg); | 380 } |
428 } | |
429 | 381 |
430 void ExternalTabContainer::SetInitialFocus(bool reverse) { | |
431 DCHECK(tab_contents_); | |
432 if (tab_contents_) { | 382 if (tab_contents_) { |
433 static_cast<TabContents*>(tab_contents_)->Focus(); | 383 NotificationService::current()->Notify( |
434 static_cast<TabContents*>(tab_contents_)->SetInitialFocus(reverse); | 384 NotificationType::EXTERNAL_TAB_CLOSED, |
385 Source<NavigationController>(&tab_contents_->controller()), | |
386 Details<ExternalTabContainer>(this)); | |
387 | |
388 delete tab_contents_; | |
389 tab_contents_ = NULL; | |
435 } | 390 } |
436 } | 391 } |
437 | 392 |
438 // static | |
439 bool ExternalTabContainer::IsExternalTabContainer(HWND window) { | |
440 std::wstring class_name = win_util::GetClassName(window); | |
441 return _wcsicmp(class_name.c_str(), chrome::kExternalTabWindowClass) == 0; | |
442 } | |
443 | |
444 ExtensionFunctionDispatcher* ExternalTabContainer:: | |
445 CreateExtensionFunctionDispatcher(RenderViewHost* render_view_host, | |
446 const std::string& extension_id) { | |
447 return new ExtensionFunctionDispatcher(render_view_host, NULL, extension_id); | |
448 } | |
449 | |
450 // static | |
451 ExternalTabContainer* ExternalTabContainer::GetContainerForTab( | |
452 HWND tab_window) { | |
453 HWND parent_window = ::GetParent(tab_window); | |
454 if (!::IsWindow(parent_window)) { | |
455 return NULL; | |
456 } | |
457 if (!IsExternalTabContainer(parent_window)) { | |
458 return NULL; | |
459 } | |
460 ExternalTabContainer* container = reinterpret_cast<ExternalTabContainer*>( | |
461 GetProp(parent_window, kWindowObjectKey)); | |
462 return container; | |
463 } | |
OLD | NEW |