Fix Win8 metro startup crash from window switcher button
[chromium-blink-merge.git] / chrome_frame / infobars / internal / host_window_manager.cc
blob34bcf9097e5a2ac9b9ca3cb4c239c2b31d393326
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.
5 #include "chrome_frame/infobars/internal/host_window_manager.h"
7 #include "chrome_frame/infobars/internal/displaced_window_manager.h"
9 namespace {
11 const wchar_t kIeTabContentParentWindowClass[] = L"Shell DocObject View";
13 } // namespace
15 // Receives notification when the displaced window is destroyed, and forwards
16 // displaced window dimensions on to HostWindowManager::Delegate.
17 class HostWindowManager::DisplacedWindowDelegate
18 : public DisplacedWindowManager::Delegate {
19 public:
20 explicit DisplacedWindowDelegate(HostWindowManager* manager);
21 virtual ~DisplacedWindowDelegate();
23 // DisplacedWindowManager::Delegate implementation
24 virtual void AdjustDisplacedWindowDimensions(RECT* rect);
26 private:
27 HostWindowManager* manager_; // Not owned by this instance
28 DISALLOW_COPY_AND_ASSIGN(DisplacedWindowDelegate);
29 }; // class HostWindowManager::DisplacedWindowDelegate
31 HostWindowManager::DisplacedWindowDelegate::DisplacedWindowDelegate(
32 HostWindowManager* manager) : manager_(manager) {
35 // Called when the displaced window is destroyed. Try to find a new displaced
36 // window.
37 HostWindowManager::DisplacedWindowDelegate::~DisplacedWindowDelegate() {
38 HWND old_window = *manager_->displaced_window_manager_;
39 // Will be deleted in its OnFinalMessage
40 manager_->displaced_window_manager_ = NULL;
42 // Check to see if a new window has already been created.
43 if (manager_->FindDisplacedWindow(old_window))
44 manager_->UpdateLayout();
47 // Forward this on to our delegate
48 void HostWindowManager::DisplacedWindowDelegate::
49 AdjustDisplacedWindowDimensions(RECT* rect) {
50 manager_->delegate()->AdjustDisplacedWindowDimensions(rect);
53 // Callback function for EnumChildWindows (looks for a window with class
54 // kIeTabContentParentWindowClass).
56 // lparam must point to an HWND that is either NULL or the HWND of the displaced
57 // window that is being destroyed. We will ignore that window if we come across
58 // it, and update lparam to point to the new displaced window if it is found.
59 static BOOL CALLBACK FindDisplacedWindowProc(HWND hwnd, LPARAM lparam) {
60 DCHECK(lparam != NULL);
61 HWND* window_handle = reinterpret_cast<HWND*>(lparam);
63 if (hwnd == *window_handle)
64 return TRUE; // Skip this, it's the old displaced window.
66 // Variable to hold the class name. The size does not matter as long as it
67 // is at least can hold kIeTabContentParentWindowClass.
68 wchar_t class_name[100];
69 if (::GetClassName(hwnd, class_name, arraysize(class_name)) &&
70 lstrcmpi(kIeTabContentParentWindowClass, class_name) == 0) {
71 // We found the window. Return its handle and stop enumeration.
72 *window_handle = hwnd;
73 return FALSE;
75 return TRUE;
78 HostWindowManager::HostWindowManager() : displaced_window_manager_(NULL) {
81 HostWindowManager::~HostWindowManager() {
82 // If we are holding a displaced_window_manager_, it means that
83 // OnDisplacedWindowManagerDestroyed has not been called yet, and therefore
84 // our DisplacedWindowDelegate might still be around, ready to invoke us.
85 // Fail fast to prevent a call into lala-land.
86 CHECK(displaced_window_manager_ == NULL);
89 void HostWindowManager::UpdateLayout() {
90 if (FindDisplacedWindow(NULL))
91 displaced_window_manager_->UpdateLayout();
94 bool HostWindowManager::FindDisplacedWindow(HWND old_window) {
95 if (displaced_window_manager_ == NULL ||
96 *displaced_window_manager_ == old_window) {
97 // Find the window which is the container for the HTML view (parent of
98 // the content). When the displaced window is destroyed, the new one might
99 // already exist, so we say "find a displaced window that is not this
100 // (old) one".
101 HWND displaced_window = old_window;
102 ::EnumChildWindows(*this, FindDisplacedWindowProc,
103 reinterpret_cast<LPARAM>(&displaced_window));
105 if (displaced_window == old_window) {
106 LOG(ERROR) << "Failed to locate IE renderer HWND to displace for "
107 << "Infobar installation.";
108 } else {
109 scoped_ptr<DisplacedWindowManager> displaced_window_manager(
110 new DisplacedWindowManager());
111 if (displaced_window_manager->Initialize(
112 displaced_window, new DisplacedWindowDelegate(this))) {
113 displaced_window_manager_ = displaced_window_manager.release();
118 return displaced_window_manager_ != NULL;