OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/ui/views/extensions/extension_popup.h" | 5 #include "chrome/browser/ui/views/extensions/extension_popup.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "chrome/browser/debugger/devtools_window.h" | 9 #include "chrome/browser/debugger/devtools_window.h" |
10 #include "chrome/browser/extensions/extension_process_manager.h" | 10 #include "chrome/browser/extensions/extension_process_manager.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 ExtensionHost* host, | 32 ExtensionHost* host, |
33 views::View* anchor_view, | 33 views::View* anchor_view, |
34 views::BubbleBorder::ArrowLocation arrow_location, | 34 views::BubbleBorder::ArrowLocation arrow_location, |
35 bool inspect_with_devtools) | 35 bool inspect_with_devtools) |
36 : BubbleDelegateView(anchor_view, arrow_location), | 36 : BubbleDelegateView(anchor_view, arrow_location), |
37 extension_host_(host), | 37 extension_host_(host), |
38 inspect_with_devtools_(inspect_with_devtools) { | 38 inspect_with_devtools_(inspect_with_devtools) { |
39 SetLayoutManager(new views::FillLayout()); | 39 SetLayoutManager(new views::FillLayout()); |
40 AddChildView(host->view()); | 40 AddChildView(host->view()); |
41 host->view()->SetContainer(this); | 41 host->view()->SetContainer(this); |
| 42 #if defined(OS_WIN) && !defined(USE_AURA) |
| 43 // Use OnNativeFocusChange to check for child window activation on deactivate. |
| 44 set_close_on_deactivate(false); |
| 45 #else |
42 set_close_on_deactivate(!inspect_with_devtools); | 46 set_close_on_deactivate(!inspect_with_devtools); |
| 47 #endif |
43 | 48 |
44 // We wait to show the popup until the contained host finishes loading. | 49 // We wait to show the popup until the contained host finishes loading. |
45 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, | 50 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
46 content::Source<Profile>(host->profile())); | 51 content::Source<Profile>(host->profile())); |
47 | 52 |
48 // Listen for the containing view calling window.close(); | 53 // Listen for the containing view calling window.close(); |
49 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 54 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
50 content::Source<Profile>(host->profile())); | 55 content::Source<Profile>(host->profile())); |
| 56 |
| 57 views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this); |
51 } | 58 } |
52 | 59 |
53 ExtensionPopup::~ExtensionPopup() { | 60 ExtensionPopup::~ExtensionPopup() { |
| 61 views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this); |
54 } | 62 } |
55 | 63 |
56 void ExtensionPopup::Observe(int type, | 64 void ExtensionPopup::Observe(int type, |
57 const content::NotificationSource& source, | 65 const content::NotificationSource& source, |
58 const content::NotificationDetails& details) { | 66 const content::NotificationDetails& details) { |
59 switch (type) { | 67 switch (type) { |
60 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: | 68 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: |
61 // Once we receive did stop loading, the content will be complete and | 69 // Once we receive did stop loading, the content will be complete and |
62 // the width will have been computed. Now it's safe to show. | 70 // the width will have been computed. Now it's safe to show. |
63 if (host() == content::Details<ExtensionHost>(details).ptr()) { | 71 if (host() == content::Details<ExtensionHost>(details).ptr()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 } | 104 } |
97 | 105 |
98 gfx::Size ExtensionPopup::GetPreferredSize() { | 106 gfx::Size ExtensionPopup::GetPreferredSize() { |
99 // Constrain the size to popup min/max. | 107 // Constrain the size to popup min/max. |
100 gfx::Size sz = views::View::GetPreferredSize(); | 108 gfx::Size sz = views::View::GetPreferredSize(); |
101 sz.set_width(std::max(kMinWidth, std::min(kMaxWidth, sz.width()))); | 109 sz.set_width(std::max(kMinWidth, std::min(kMaxWidth, sz.width()))); |
102 sz.set_height(std::max(kMinHeight, std::min(kMaxHeight, sz.height()))); | 110 sz.set_height(std::max(kMinHeight, std::min(kMaxHeight, sz.height()))); |
103 return sz; | 111 return sz; |
104 } | 112 } |
105 | 113 |
| 114 void ExtensionPopup::OnNativeFocusChange(gfx::NativeView focused_before, |
| 115 gfx::NativeView focused_now) { |
| 116 // TODO(msw): Implement something equivalent for Aura. See crbug.com/106958 |
| 117 #if defined(OS_WIN) && !defined(USE_AURA) |
| 118 // Don't close if a child of this window is activated (only needed on Win). |
| 119 // ExtensionPopups can create Javascipt dialogs; see crbug.com/106723. |
| 120 gfx::NativeView this_window = GetWidget()->GetNativeView(); |
| 121 if (!inspect_with_devtools_ && focused_before == this_window) { |
| 122 DCHECK_NE(focused_now, this_window); |
| 123 if (::GetWindow(focused_now, GW_OWNER) == this_window) |
| 124 return; |
| 125 gfx::NativeView focused_parent = focused_now; |
| 126 while (focused_parent = ::GetParent(focused_parent)) { |
| 127 if (this_window == focused_parent) |
| 128 return; |
| 129 } |
| 130 GetWidget()->Close(); |
| 131 } |
| 132 #endif |
| 133 } |
| 134 |
106 // static | 135 // static |
107 ExtensionPopup* ExtensionPopup::ShowPopup( | 136 ExtensionPopup* ExtensionPopup::ShowPopup( |
108 const GURL& url, | 137 const GURL& url, |
109 Browser* browser, | 138 Browser* browser, |
110 views::View* anchor_view, | 139 views::View* anchor_view, |
111 views::BubbleBorder::ArrowLocation arrow_location, | 140 views::BubbleBorder::ArrowLocation arrow_location, |
112 bool inspect_with_devtools) { | 141 bool inspect_with_devtools) { |
113 ExtensionProcessManager* manager = | 142 ExtensionProcessManager* manager = |
114 browser->profile()->GetExtensionProcessManager(); | 143 browser->profile()->GetExtensionProcessManager(); |
115 ExtensionHost* host = manager->CreatePopupHost(url, browser); | 144 ExtensionHost* host = manager->CreatePopupHost(url, browser); |
116 ExtensionPopup* popup = new ExtensionPopup(browser, host, anchor_view, | 145 ExtensionPopup* popup = new ExtensionPopup(browser, host, anchor_view, |
117 arrow_location, inspect_with_devtools); | 146 arrow_location, inspect_with_devtools); |
118 browser::CreateViewsBubble(popup); | 147 browser::CreateViewsBubble(popup); |
119 | 148 |
120 // TODO(msw): Use half the corner radius as contents margins so that contents | 149 // TODO(msw): Use half the corner radius as contents margins so that contents |
121 // fit better in the bubble. See http://crbug.com/80416. | 150 // fit better in the bubble. See http://crbug.com/80416. |
122 | 151 |
123 // If the host had somehow finished loading, then we'd miss the notification | 152 // If the host had somehow finished loading, then we'd miss the notification |
124 // and not show. This seems to happen in single-process mode. | 153 // and not show. This seems to happen in single-process mode. |
125 if (host->did_stop_loading()) { | 154 if (host->did_stop_loading()) { |
126 popup->Show(); | 155 popup->Show(); |
127 // Focus on the host contents when the bubble is first shown. | 156 // Focus on the host contents when the bubble is first shown. |
128 host->host_contents()->Focus(); | 157 host->host_contents()->Focus(); |
129 } | 158 } |
130 | 159 |
131 return popup; | 160 return popup; |
132 } | 161 } |
OLD | NEW |