OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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/views/infobars/extension_infobar.h" | 5 #include "chrome/browser/views/infobars/extension_infobar.h" |
6 | 6 |
7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
8 #include "app/slide_animation.h" | 8 #include "app/slide_animation.h" |
9 #include "chrome/browser/extensions/extension_context_menu_model.h" | 9 #include "chrome/browser/extensions/extension_context_menu_model.h" |
10 #include "chrome/browser/extensions/extension_infobar_delegate.h" | 10 #include "chrome/browser/extensions/extension_infobar_delegate.h" |
(...skipping 14 matching lines...) Expand all Loading... | |
25 | 25 |
26 // The amount of space to the right of the Extension (HTML) view (to avoid | 26 // The amount of space to the right of the Extension (HTML) view (to avoid |
27 // overlapping the close button for the InfoBar). | 27 // overlapping the close button for the InfoBar). |
28 static const int kFarRightMargin = 30; | 28 static const int kFarRightMargin = 30; |
29 | 29 |
30 // The margin between the extension icon and the drop-down arrow bitmap. | 30 // The margin between the extension icon and the drop-down arrow bitmap. |
31 static const int kDropArrowLeftMargin = 3; | 31 static const int kDropArrowLeftMargin = 3; |
32 | 32 |
33 ExtensionInfoBar::ExtensionInfoBar(ExtensionInfoBarDelegate* delegate) | 33 ExtensionInfoBar::ExtensionInfoBar(ExtensionInfoBarDelegate* delegate) |
34 : InfoBar(delegate), | 34 : InfoBar(delegate), |
35 delegate_(delegate), | |
36 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { | 35 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { |
37 delegate_->set_observer(this); | |
38 | |
39 ExtensionHost* extension_host = delegate_->extension_host(); | |
40 | |
41 // We set the target height for the InfoBar to be the height of the | 36 // We set the target height for the InfoBar to be the height of the |
42 // ExtensionView it contains (plus 1 because the view should not overlap the | 37 // ExtensionView it contains (plus 1 because the view should not overlap the |
43 // separator line at the bottom). When the InfoBar is first created, however, | 38 // separator line at the bottom). When the InfoBar is first created, however, |
44 // this value is 0 but becomes positive after the InfoBar has been shown. See | 39 // this value is 0 but becomes positive after the InfoBar has been shown. See |
45 // function: OnExtensionPreferredSizeChanged. | 40 // function: OnExtensionPreferredSizeChanged. |
46 gfx::Size sz = extension_host->view()->GetPreferredSize(); | 41 ExtensionView* extension_view = delegate->extension_host()->view(); |
47 if (sz.height() > 0) | 42 gfx::Size sz = extension_view->GetPreferredSize(); |
48 sz.set_height(sz.height() + 1); | 43 set_target_height((sz.height() > 0) ? (sz.height() + 1) : sz.height()); |
49 set_target_height(sz.height()); | |
50 | 44 |
51 // Setup the extension icon and its associated drop down menu. | 45 // Setup the extension icon and its associated drop down menu. |
52 SetupIconAndMenu(); | 46 SetupIconAndMenu(); |
53 | 47 |
54 // Get notified of resize events for the ExtensionView. | 48 // Get notified of resize events for the ExtensionView. |
55 extension_host->view()->SetContainer(this); | 49 extension_view->SetContainer(this); |
56 // We show the ExtensionView, but we don't want it deleted when we get | 50 // We show the ExtensionView, but we don't want it deleted when we get |
57 // destroyed, which happens on tab switching (for example). | 51 // destroyed, which happens on tab switching (for example). |
58 extension_host->view()->set_parent_owned(false); | 52 extension_view->set_parent_owned(false); |
59 AddChildView(extension_host->view()); | 53 AddChildView(extension_view); |
60 } | 54 } |
61 | 55 |
62 ExtensionInfoBar::~ExtensionInfoBar() { | 56 ExtensionInfoBar::~ExtensionInfoBar() { |
63 if (delegate_) { | 57 if (delegate()) { |
64 delegate_->extension_host()->view()->SetContainer(NULL); | 58 delegate()->AsExtensionInfoBarDelegate()->extension_host()->view()-> |
65 delegate_->set_observer(NULL); | 59 SetContainer(NULL); |
66 } | 60 } |
67 } | 61 } |
68 | 62 |
69 void ExtensionInfoBar::OnExtensionPreferredSizeChanged(ExtensionView* view) { | 63 void ExtensionInfoBar::OnExtensionPreferredSizeChanged(ExtensionView* view) { |
70 DCHECK(view == delegate_->extension_host()->view()); | 64 DCHECK(delegate()); |
Finnur
2010/11/15 23:08:41
nit: This is redundant and just adds cruft to the
| |
65 ExtensionView* extension_view = | |
66 delegate()->AsExtensionInfoBarDelegate()->extension_host()->view(); | |
67 DCHECK_EQ(extension_view, view); | |
71 | 68 |
72 // When the infobar is closed, it animates to 0 vertical height. We'll | 69 extension_view->SetVisible(true); |
73 // continue to get size changed notifications from the ExtensionView, but we | |
74 // need to ignore them otherwise we'll try to re-animate open (and leak the | |
75 // infobar view). | |
76 if (delegate_->closing()) | |
77 return; | |
Finnur
2010/11/15 23:08:41
So, given the new model, there is no chance of it
| |
78 | |
79 delegate_->extension_host()->view()->SetVisible(true); | |
80 | |
81 gfx::Size sz = view->GetPreferredSize(); | |
82 // Clamp height to a min and a max size of between 1 and 2 InfoBars. | |
83 int default_height = static_cast<int>(InfoBar::kDefaultTargetHeight); | |
84 sz.set_height(std::max(default_height, sz.height())); | |
85 sz.set_height(std::min(2 * default_height, sz.height())); | |
86 | 70 |
87 if (height() == 0) | 71 if (height() == 0) |
88 animation()->Reset(0.0); | 72 animation()->Reset(0.0); |
89 set_target_height(sz.height()); | 73 |
74 // Clamp height to a min and a max size of between 1 and 2 InfoBars. | |
75 gfx::Size sz = view->GetPreferredSize(); | |
76 int default_height = static_cast<int>(InfoBar::kDefaultTargetHeight); | |
77 set_target_height( | |
78 std::min(2 * default_height, std::max(default_height, sz.height()))); | |
79 | |
90 animation()->Show(); | 80 animation()->Show(); |
91 } | 81 } |
92 | 82 |
93 void ExtensionInfoBar::Layout() { | 83 void ExtensionInfoBar::Layout() { |
94 // Layout the close button and the background. | 84 // Layout the close button and the background. |
95 InfoBar::Layout(); | 85 InfoBar::Layout(); |
96 | 86 |
97 // Layout the extension icon + drop down menu. | 87 // Layout the extension icon + drop down menu. |
98 int x = 0; | 88 int x = 0; |
99 gfx::Size sz = menu_->GetPreferredSize(); | 89 gfx::Size sz = menu_->GetPreferredSize(); |
100 menu_->SetBounds(x, | 90 menu_->SetBounds(x, (height() - sz.height()) / 2, sz.width(), sz.height()); |
101 (height() - sz.height()) / 2, | |
102 sz.width(), sz.height()); | |
103 x += sz.width() + kMenuHorizontalMargin; | 91 x += sz.width() + kMenuHorizontalMargin; |
104 | 92 |
105 // Layout the ExtensionView, showing the HTML InfoBar. | 93 // Layout the ExtensionView, showing the HTML InfoBar. The delegate owns the |
106 ExtensionView* view = delegate_->extension_host()->view(); | 94 // view, so if the delegate is destroyed, the view will have been destroyed as |
107 view->SetBounds(x, 0, width() - x - kFarRightMargin - 1, height() - 1); | 95 // well (which also removes it as a child view). |
96 if (delegate()) { | |
97 delegate()->AsExtensionInfoBarDelegate()->extension_host()->view()-> | |
98 SetBounds(x, 0, width() - x - kFarRightMargin - 1, height() - 1); | |
99 } | |
108 } | 100 } |
109 | 101 |
110 void ExtensionInfoBar::OnImageLoaded( | 102 void ExtensionInfoBar::OnImageLoaded(SkBitmap* image, |
111 SkBitmap* image, ExtensionResource resource, int index) { | 103 ExtensionResource resource, |
112 if (!delegate_) | 104 int index) { |
113 return; // The delegate can go away while we asynchronously load images. | |
Finnur
2010/11/15 23:08:41
This should be OK I guess given that it is guarant
| |
114 | |
115 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 105 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
116 | 106 |
117 // We fall back on the default extension icon on failure. | 107 // We fall back on the default extension icon on failure. |
118 SkBitmap* icon; | 108 SkBitmap* icon; |
119 if (!image || image->empty()) | 109 if (!image || image->empty()) |
120 icon = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); | 110 icon = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); |
121 else | 111 else |
122 icon = image; | 112 icon = image; |
123 | 113 |
124 SkBitmap* drop_image = rb.GetBitmapNamed(IDR_APP_DROPARROW); | 114 SkBitmap* drop_image = rb.GetBitmapNamed(IDR_APP_DROPARROW); |
125 | 115 |
126 int image_size = Extension::EXTENSION_ICON_BITTY; | 116 int image_size = Extension::EXTENSION_ICON_BITTY; |
127 scoped_ptr<gfx::CanvasSkia> canvas( | 117 scoped_ptr<gfx::CanvasSkia> canvas( |
128 new gfx::CanvasSkia( | 118 new gfx::CanvasSkia( |
129 image_size + kDropArrowLeftMargin + drop_image->width(), | 119 image_size + kDropArrowLeftMargin + drop_image->width(), |
130 image_size, false)); | 120 image_size, false)); |
131 canvas->DrawBitmapInt(*icon, | 121 canvas->DrawBitmapInt(*icon, |
132 0, 0, icon->width(), icon->height(), | 122 0, 0, icon->width(), icon->height(), |
133 0, 0, image_size, image_size, | 123 0, 0, image_size, image_size, |
134 false); | 124 false); |
135 canvas->DrawBitmapInt(*drop_image, | 125 canvas->DrawBitmapInt(*drop_image, |
136 image_size + kDropArrowLeftMargin, | 126 image_size + kDropArrowLeftMargin, |
137 image_size / 2); | 127 image_size / 2); |
138 menu_->SetIcon(canvas->ExtractBitmap()); | 128 menu_->SetIcon(canvas->ExtractBitmap()); |
139 menu_->SetVisible(true); | 129 menu_->SetVisible(true); |
140 | 130 |
141 Layout(); | 131 Layout(); |
142 } | 132 } |
143 | 133 |
144 void ExtensionInfoBar::OnDelegateDeleted() { | |
145 delegate_->extension_host()->view()->SetContainer(NULL); | |
146 delegate_ = NULL; | |
147 } | |
148 | |
149 void ExtensionInfoBar::RunMenu(View* source, const gfx::Point& pt) { | 134 void ExtensionInfoBar::RunMenu(View* source, const gfx::Point& pt) { |
135 DCHECK(delegate()); | |
150 if (!options_menu_contents_.get()) { | 136 if (!options_menu_contents_.get()) { |
151 Browser* browser = BrowserView::GetBrowserViewForNativeWindow( | 137 Browser* browser = BrowserView::GetBrowserViewForNativeWindow( |
152 platform_util::GetTopLevel(source->GetWidget()->GetNativeView()))-> | 138 platform_util::GetTopLevel(source->GetWidget()->GetNativeView()))-> |
153 browser(); | 139 browser(); |
154 options_menu_contents_ = new ExtensionContextMenuModel( | 140 options_menu_contents_ = new ExtensionContextMenuModel( |
155 delegate_->extension_host()->extension(), browser, NULL); | 141 delegate()->AsExtensionInfoBarDelegate()->extension_host()->extension(), |
142 browser, NULL); | |
156 } | 143 } |
157 | 144 |
158 options_menu_menu_.reset(new views::Menu2(options_menu_contents_.get())); | 145 options_menu_menu_.reset(new views::Menu2(options_menu_contents_.get())); |
159 options_menu_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPLEFT); | 146 options_menu_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPLEFT); |
160 } | 147 } |
161 | 148 |
162 void ExtensionInfoBar::SetupIconAndMenu() { | 149 void ExtensionInfoBar::SetupIconAndMenu() { |
150 DCHECK(delegate()); | |
Finnur
2010/11/15 23:08:41
Same here, redundant.
| |
163 menu_ = new views::MenuButton(NULL, std::wstring(), this, false); | 151 menu_ = new views::MenuButton(NULL, std::wstring(), this, false); |
164 menu_->SetVisible(false); | 152 menu_->SetVisible(false); |
165 AddChildView(menu_); | 153 AddChildView(menu_); |
166 | 154 |
167 const Extension* extension = delegate_->extension_host()->extension(); | 155 const Extension* extension = |
156 delegate()->AsExtensionInfoBarDelegate()->extension_host()->extension(); | |
168 ExtensionResource icon_resource = extension->GetIconResource( | 157 ExtensionResource icon_resource = extension->GetIconResource( |
169 Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_EXACTLY); | 158 Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_EXACTLY); |
170 if (!icon_resource.relative_path().empty()) { | 159 if (!icon_resource.relative_path().empty()) { |
171 // Create a tracker to load the image. It will report back on OnImageLoaded. | 160 // Create a tracker to load the image. It will report back on OnImageLoaded. |
172 tracker_.LoadImage(extension, icon_resource, | 161 tracker_.LoadImage(extension, icon_resource, |
173 gfx::Size(Extension::EXTENSION_ICON_BITTY, | 162 gfx::Size(Extension::EXTENSION_ICON_BITTY, |
174 Extension::EXTENSION_ICON_BITTY), | 163 Extension::EXTENSION_ICON_BITTY), |
175 ImageLoadingTracker::DONT_CACHE); | 164 ImageLoadingTracker::DONT_CACHE); |
176 } else { | 165 } else { |
177 OnImageLoaded(NULL, icon_resource, 0); // |image|, |index|. | 166 OnImageLoaded(NULL, icon_resource, 0); // |image|, |index|. |
178 } | 167 } |
179 } | 168 } |
180 | 169 |
181 InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() { | 170 InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() { |
182 return new ExtensionInfoBar(this); | 171 return new ExtensionInfoBar(this); |
183 } | 172 } |
OLD | NEW |