| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_installed_bubble_view.h" | |
| 6 | |
| 7 #include <algorithm> | 5 #include <algorithm> |
| 8 #include <string> | 6 #include <string> |
| 9 | 7 |
| 10 #include "base/macros.h" | 8 #include "base/macros.h" |
| 11 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 12 #include "base/metrics/user_metrics_action.h" | 10 #include "base/metrics/user_metrics_action.h" |
| 13 #include "chrome/browser/extensions/extension_action_manager.h" | 11 #include "chrome/browser/extensions/extension_action_manager.h" |
| 14 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/browser/ui/browser.h" | 13 #include "chrome/browser/ui/browser.h" |
| 16 #include "chrome/browser/ui/browser_window.h" | 14 #include "chrome/browser/ui/browser_window.h" |
| 17 #include "chrome/browser/ui/chrome_pages.h" | 15 #include "chrome/browser/ui/chrome_pages.h" |
| 16 #include "chrome/browser/ui/extensions/extension_installed_bubble.h" |
| 18 #include "chrome/browser/ui/singleton_tabs.h" | 17 #include "chrome/browser/ui/singleton_tabs.h" |
| 18 #include "chrome/browser/ui/sync/bubble_sync_promo_delegate.h" |
| 19 #include "chrome/browser/ui/views/frame/browser_view.h" | 19 #include "chrome/browser/ui/views/frame/browser_view.h" |
| 20 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | 20 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
| 21 #include "chrome/browser/ui/views/location_bar/location_icon_view.h" |
| 21 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h" | 22 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h" |
| 22 #include "chrome/browser/ui/views/sync/bubble_sync_promo_view.h" | 23 #include "chrome/browser/ui/views/sync/bubble_sync_promo_view.h" |
| 23 #include "chrome/browser/ui/views/toolbar/app_menu_button.h" | 24 #include "chrome/browser/ui/views/toolbar/app_menu_button.h" |
| 24 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" | 25 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" |
| 25 #include "chrome/browser/ui/views/toolbar/toolbar_view.h" | 26 #include "chrome/browser/ui/views/toolbar/toolbar_view.h" |
| 26 #include "chrome/common/url_constants.h" | 27 #include "chrome/common/url_constants.h" |
| 27 #include "chrome/grit/chromium_strings.h" | 28 #include "chrome/grit/chromium_strings.h" |
| 28 #include "chrome/grit/generated_resources.h" | 29 #include "chrome/grit/generated_resources.h" |
| 29 #include "components/bubble/bubble_controller.h" | 30 #include "components/bubble/bubble_controller.h" |
| 30 #include "components/bubble/bubble_ui.h" | 31 #include "components/bubble/bubble_ui.h" |
| 31 #include "content/public/browser/user_metrics.h" | 32 #include "content/public/browser/user_metrics.h" |
| 32 #include "extensions/common/extension.h" | 33 #include "extensions/common/extension.h" |
| 33 #include "ui/base/l10n/l10n_util.h" | 34 #include "ui/base/l10n/l10n_util.h" |
| 34 #include "ui/base/resource/resource_bundle.h" | 35 #include "ui/base/resource/resource_bundle.h" |
| 35 #include "ui/gfx/render_text.h" | 36 #include "ui/gfx/render_text.h" |
| 36 #include "ui/gfx/text_elider.h" | 37 #include "ui/gfx/text_elider.h" |
| 37 #include "ui/resources/grit/ui_resources.h" | 38 #include "ui/resources/grit/ui_resources.h" |
| 39 #include "ui/views/bubble/bubble_dialog_delegate.h" |
| 38 #include "ui/views/bubble/bubble_frame_view.h" | 40 #include "ui/views/bubble/bubble_frame_view.h" |
| 41 #include "ui/views/controls/button/button.h" |
| 39 #include "ui/views/controls/button/image_button.h" | 42 #include "ui/views/controls/button/image_button.h" |
| 40 #include "ui/views/controls/image_view.h" | 43 #include "ui/views/controls/image_view.h" |
| 41 #include "ui/views/controls/label.h" | 44 #include "ui/views/controls/label.h" |
| 42 #include "ui/views/controls/link.h" | 45 #include "ui/views/controls/link.h" |
| 43 #include "ui/views/controls/link_listener.h" | 46 #include "ui/views/controls/link_listener.h" |
| 44 #include "ui/views/layout/box_layout.h" | 47 #include "ui/views/layout/box_layout.h" |
| 45 #include "ui/views/layout/fill_layout.h" | |
| 46 #include "ui/views/layout/grid_layout.h" | 48 #include "ui/views/layout/grid_layout.h" |
| 47 #include "ui/views/layout/layout_constants.h" | 49 #include "ui/views/layout/layout_constants.h" |
| 48 | 50 |
| 49 using extensions::Extension; | 51 using extensions::Extension; |
| 50 | 52 |
| 51 namespace { | 53 namespace { |
| 52 | 54 |
| 53 const int kIconSize = 43; | 55 const int kIconSize = 43; |
| 54 | 56 |
| 55 const int kRightColumnWidth = 285; | 57 const int kRightColumnWidth = 285; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 close_size.height()); | 106 close_size.height()); |
| 105 } | 107 } |
| 106 | 108 |
| 107 private: | 109 private: |
| 108 views::Label* heading_; | 110 views::Label* heading_; |
| 109 views::LabelButton* close_; | 111 views::LabelButton* close_; |
| 110 | 112 |
| 111 DISALLOW_COPY_AND_ASSIGN(HeadingAndCloseButtonView); | 113 DISALLOW_COPY_AND_ASSIGN(HeadingAndCloseButtonView); |
| 112 }; | 114 }; |
| 113 | 115 |
| 114 } // namespace | 116 // Provides feedback to the user upon successful installation of an |
| 117 // extension. Depending on the type of extension, the Bubble will |
| 118 // point to: |
| 119 // OMNIBOX_KEYWORD-> The omnibox. |
| 120 // BROWSER_ACTION -> The browserAction icon in the toolbar. |
| 121 // PAGE_ACTION -> A preview of the pageAction icon in the location |
| 122 // bar which is shown while the Bubble is shown. |
| 123 // GENERIC -> The app menu. This case includes pageActions that don't |
| 124 // specify a default icon. |
| 125 class ExtensionInstalledBubbleView : public BubbleSyncPromoDelegate, |
| 126 public views::BubbleDialogDelegateView, |
| 127 public views::ButtonListener, |
| 128 public views::LinkListener { |
| 129 public: |
| 130 explicit ExtensionInstalledBubbleView(ExtensionInstalledBubble* bubble); |
| 131 ~ExtensionInstalledBubbleView() override; |
| 132 |
| 133 // Recalculate the anchor position for this bubble. |
| 134 void UpdateAnchorView(); |
| 135 |
| 136 void CloseBubble(); |
| 137 |
| 138 private: |
| 139 Browser* browser() { return controller_->browser(); } |
| 140 |
| 141 // views::BubbleDialogDelegateView: |
| 142 void Init() override; |
| 143 View* CreateFootnoteView() override; |
| 144 int GetDialogButtons() const override; |
| 145 |
| 146 // BubbleSyncPromoDelegate: |
| 147 void OnSignInLinkClicked() override; |
| 148 |
| 149 // views::LinkListener: |
| 150 void LinkClicked(views::Link* source, int event_flags) override; |
| 151 |
| 152 // views::ButtonListener: |
| 153 void ButtonPressed(views::Button* sender, const ui::Event& event) override; |
| 154 |
| 155 ExtensionInstalledBubble* controller_; |
| 156 ExtensionInstalledBubble::BubbleType type_; |
| 157 ExtensionInstalledBubble::AnchorPosition anchor_position_; |
| 158 |
| 159 // The button to close the bubble. |
| 160 views::LabelButton* close_; |
| 161 |
| 162 // The shortcut to open the manage shortcuts page. |
| 163 views::Link* manage_shortcut_; |
| 164 |
| 165 DISALLOW_COPY_AND_ASSIGN(ExtensionInstalledBubbleView); |
| 166 }; |
| 115 | 167 |
| 116 ExtensionInstalledBubbleView::ExtensionInstalledBubbleView( | 168 ExtensionInstalledBubbleView::ExtensionInstalledBubbleView( |
| 117 ExtensionInstalledBubble* bubble, | 169 ExtensionInstalledBubble* controller) |
| 118 BubbleReference bubble_reference) | 170 : BubbleDialogDelegateView(nullptr, |
| 119 : bubble_(bubble), | 171 controller->anchor_position() == |
| 120 bubble_reference_(bubble_reference), | 172 ExtensionInstalledBubble::ANCHOR_OMNIBOX |
| 121 extension_(bubble->extension()), | 173 ? views::BubbleBorder::TOP_LEFT |
| 122 browser_(bubble->browser()), | 174 : views::BubbleBorder::TOP_RIGHT), |
| 123 type_(bubble->type()), | 175 controller_(controller), |
| 124 anchor_position_(bubble->anchor_position()), | |
| 125 close_(nullptr), | 176 close_(nullptr), |
| 126 manage_shortcut_(nullptr) {} | 177 manage_shortcut_(nullptr) {} |
| 127 | 178 |
| 128 ExtensionInstalledBubbleView::~ExtensionInstalledBubbleView() {} | 179 ExtensionInstalledBubbleView::~ExtensionInstalledBubbleView() {} |
| 129 | 180 |
| 130 void ExtensionInstalledBubbleView::UpdateAnchorView() { | 181 void ExtensionInstalledBubbleView::UpdateAnchorView() { |
| 131 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); | 182 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); |
| 132 | 183 |
| 133 views::View* reference_view = nullptr; | 184 views::View* reference_view = nullptr; |
| 134 switch (anchor_position_) { | 185 switch (controller_->anchor_position()) { |
| 135 case ExtensionInstalledBubble::ANCHOR_BROWSER_ACTION: { | 186 case ExtensionInstalledBubble::ANCHOR_BROWSER_ACTION: { |
| 136 BrowserActionsContainer* container = | 187 BrowserActionsContainer* container = |
| 137 browser_view->GetToolbarView()->browser_actions(); | 188 browser_view->GetToolbarView()->browser_actions(); |
| 138 // Hitting this DCHECK means |ShouldShow| failed. | 189 // Hitting this DCHECK means |ShouldShow| failed. |
| 139 DCHECK(!container->animating()); | 190 DCHECK(!container->animating()); |
| 140 | 191 |
| 141 reference_view = container->GetViewForId(extension_->id()); | 192 reference_view = container->GetViewForId(controller_->extension()->id()); |
| 142 // If the view is not visible then it is in the chevron, so point the | 193 // If the view is not visible then it is in the chevron, so point the |
| 143 // install bubble to the chevron instead. If this is an incognito window, | 194 // install bubble to the chevron instead. If this is an incognito window, |
| 144 // both could be invisible. | 195 // both could be invisible. |
| 145 if (!reference_view || !reference_view->visible()) { | 196 if (!reference_view || !reference_view->visible()) { |
| 146 reference_view = container->chevron(); | 197 reference_view = container->chevron(); |
| 147 if (!reference_view || !reference_view->visible()) | 198 if (!reference_view || !reference_view->visible()) |
| 148 reference_view = nullptr; // fall back to app menu below. | 199 reference_view = nullptr; // fall back to app menu below. |
| 149 } | 200 } |
| 150 break; | 201 break; |
| 151 } | 202 } |
| 152 case ExtensionInstalledBubble::ANCHOR_PAGE_ACTION: { | 203 case ExtensionInstalledBubble::ANCHOR_PAGE_ACTION: { |
| 153 LocationBarView* location_bar_view = browser_view->GetLocationBarView(); | 204 LocationBarView* location_bar_view = browser_view->GetLocationBarView(); |
| 154 ExtensionAction* page_action = | 205 ExtensionAction* page_action = |
| 155 extensions::ExtensionActionManager::Get(browser_->profile()) | 206 extensions::ExtensionActionManager::Get(browser()->profile()) |
| 156 ->GetPageAction(*extension_); | 207 ->GetPageAction(*controller_->extension()); |
| 157 location_bar_view->SetPreviewEnabledPageAction(page_action, | 208 location_bar_view->SetPreviewEnabledPageAction(page_action, |
| 158 true); // preview_enabled | 209 true); // preview_enabled |
| 159 reference_view = location_bar_view->GetPageActionView(page_action); | 210 reference_view = location_bar_view->GetPageActionView(page_action); |
| 160 DCHECK(reference_view); | 211 DCHECK(reference_view); |
| 161 break; | 212 break; |
| 162 } | 213 } |
| 163 case ExtensionInstalledBubble::ANCHOR_OMNIBOX: { | 214 case ExtensionInstalledBubble::ANCHOR_OMNIBOX: { |
| 164 LocationBarView* location_bar_view = browser_view->GetLocationBarView(); | 215 reference_view = browser_view->GetLocationBarView()->location_icon_view(); |
| 165 reference_view = location_bar_view; | |
| 166 DCHECK(reference_view); | |
| 167 break; | 216 break; |
| 168 } | 217 } |
| 169 case ExtensionInstalledBubble::ANCHOR_APP_MENU: | 218 case ExtensionInstalledBubble::ANCHOR_APP_MENU: |
| 170 // Will be caught below. | 219 // Will be caught below. |
| 171 break; | 220 break; |
| 172 } | 221 } |
| 173 | 222 |
| 174 // Default case. | 223 // Default case. |
| 175 if (!reference_view) | 224 if (!reference_view) |
| 176 reference_view = browser_view->GetToolbarView()->app_menu_button(); | 225 reference_view = browser_view->GetToolbarView()->app_menu_button(); |
| 177 SetAnchorView(reference_view); | 226 SetAnchorView(reference_view); |
| 178 } | 227 } |
| 179 | 228 |
| 229 void ExtensionInstalledBubbleView::CloseBubble() { |
| 230 if (controller_ && controller_->anchor_position() == |
| 231 ExtensionInstalledBubble::ANCHOR_PAGE_ACTION) { |
| 232 BrowserView* browser_view = |
| 233 BrowserView::GetBrowserViewForBrowser(browser()); |
| 234 browser_view->GetLocationBarView()->SetPreviewEnabledPageAction( |
| 235 extensions::ExtensionActionManager::Get(browser()->profile()) |
| 236 ->GetPageAction(*controller_->extension()), |
| 237 false); // preview_enabled |
| 238 } |
| 239 controller_ = nullptr; |
| 240 GetWidget()->Close(); |
| 241 } |
| 242 |
| 180 views::View* ExtensionInstalledBubbleView::CreateFootnoteView() { | 243 views::View* ExtensionInstalledBubbleView::CreateFootnoteView() { |
| 181 if (!(bubble_->options() & ExtensionInstalledBubble::SIGN_IN_PROMO)) | 244 if (!(controller_->options() & ExtensionInstalledBubble::SIGN_IN_PROMO)) |
| 182 return nullptr; | 245 return nullptr; |
| 183 | 246 |
| 184 return new BubbleSyncPromoView(this, | 247 return new BubbleSyncPromoView(this, |
| 185 IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW, | 248 IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW, |
| 186 IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW); | 249 IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW); |
| 187 } | 250 } |
| 188 | 251 |
| 189 void ExtensionInstalledBubbleView::WindowClosing() { | 252 int ExtensionInstalledBubbleView::GetDialogButtons() const { |
| 190 if (anchor_position_ == ExtensionInstalledBubble::ANCHOR_PAGE_ACTION) { | 253 return ui::DIALOG_BUTTON_NONE; |
| 191 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); | |
| 192 browser_view->GetLocationBarView()->SetPreviewEnabledPageAction( | |
| 193 extensions::ExtensionActionManager::Get(browser_->profile()) | |
| 194 ->GetPageAction(*extension_), | |
| 195 false); // preview_enabled | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 gfx::Rect ExtensionInstalledBubbleView::GetAnchorRect() const { | |
| 200 // For omnibox keyword bubbles, move the arrow to point to the left edge | |
| 201 // of the omnibox, just to the right of the icon. | |
| 202 if (type_ == ExtensionInstalledBubble::OMNIBOX_KEYWORD) { | |
| 203 const LocationBarView* location_bar_view = | |
| 204 BrowserView::GetBrowserViewForBrowser(browser_)->GetLocationBarView(); | |
| 205 return gfx::Rect(location_bar_view->GetOmniboxViewOrigin(), | |
| 206 gfx::Size(0, location_bar_view->omnibox_view()->height())); | |
| 207 } | |
| 208 return views::BubbleDelegateView::GetAnchorRect(); | |
| 209 } | |
| 210 | |
| 211 void ExtensionInstalledBubbleView::OnWidgetClosing(views::Widget* widget) { | |
| 212 if (bubble_reference_) { | |
| 213 DCHECK_EQ(widget, GetWidget()); | |
| 214 // A more specific close reason should already be recorded. | |
| 215 // This is the catch-all close reason for this bubble. | |
| 216 bubble_reference_->CloseBubble(BUBBLE_CLOSE_FOCUS_LOST); | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 void ExtensionInstalledBubbleView::OnWidgetActivationChanged( | |
| 221 views::Widget* widget, | |
| 222 bool active) { | |
| 223 if (!active && bubble_reference_ && widget == GetWidget()) | |
| 224 bubble_reference_->CloseBubble(BUBBLE_CLOSE_FOCUS_LOST); | |
| 225 } | |
| 226 | |
| 227 bool ExtensionInstalledBubbleView::AcceleratorPressed( | |
| 228 const ui::Accelerator& accelerator) { | |
| 229 if (!close_on_esc() || accelerator.key_code() != ui::VKEY_ESCAPE) | |
| 230 return false; | |
| 231 DCHECK(bubble_reference_); | |
| 232 bool did_close = bubble_reference_->CloseBubble(BUBBLE_CLOSE_USER_DISMISSED); | |
| 233 DCHECK(did_close); | |
| 234 return true; | |
| 235 } | 254 } |
| 236 | 255 |
| 237 void ExtensionInstalledBubbleView::OnSignInLinkClicked() { | 256 void ExtensionInstalledBubbleView::OnSignInLinkClicked() { |
| 238 GetWidget()->Close(); | |
| 239 chrome::ShowBrowserSignin( | 257 chrome::ShowBrowserSignin( |
| 240 browser_, | 258 browser(), |
| 241 signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE); | 259 signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE); |
| 260 CloseBubble(); |
| 242 } | 261 } |
| 243 | 262 |
| 244 void ExtensionInstalledBubbleView::ButtonPressed(views::Button* sender, | 263 void ExtensionInstalledBubbleView::ButtonPressed(views::Button* sender, |
| 245 const ui::Event& event) { | 264 const ui::Event& event) { |
| 246 DCHECK_EQ(sender, close_); | 265 DCHECK_EQ(sender, close_); |
| 247 GetWidget()->Close(); | 266 CloseBubble(); |
| 248 } | 267 } |
| 249 | 268 |
| 250 void ExtensionInstalledBubbleView::LinkClicked(views::Link* source, | 269 void ExtensionInstalledBubbleView::LinkClicked(views::Link* source, |
| 251 int event_flags) { | 270 int event_flags) { |
| 252 DCHECK_EQ(manage_shortcut_, source); | 271 DCHECK_EQ(manage_shortcut_, source); |
| 253 GetWidget()->Close(); | 272 CloseBubble(); |
| 254 | 273 |
| 255 std::string configure_url = chrome::kChromeUIExtensionsURL; | 274 std::string configure_url = chrome::kChromeUIExtensionsURL; |
| 256 configure_url += chrome::kExtensionConfigureCommandsSubPage; | 275 configure_url += chrome::kExtensionConfigureCommandsSubPage; |
| 257 chrome::NavigateParams params( | 276 chrome::NavigateParams params( |
| 258 chrome::GetSingletonTabNavigateParams(browser_, GURL(configure_url))); | 277 chrome::GetSingletonTabNavigateParams(browser(), GURL(configure_url))); |
| 259 chrome::Navigate(¶ms); | 278 chrome::Navigate(¶ms); |
| 260 } | 279 } |
| 261 | 280 |
| 262 void ExtensionInstalledBubbleView::InitLayout() { | 281 void ExtensionInstalledBubbleView::Init() { |
| 282 UpdateAnchorView(); |
| 283 |
| 263 // The Extension Installed bubble takes on various forms, depending on the | 284 // The Extension Installed bubble takes on various forms, depending on the |
| 264 // type of extension installed. In general, though, they are all similar: | 285 // type of extension installed. In general, though, they are all similar: |
| 265 // | 286 // |
| 266 // ------------------------- | 287 // ------------------------- |
| 267 // | | Heading [X] | | 288 // | | Heading [X] | |
| 268 // | Icon | Info | | 289 // | Icon | Info | |
| 269 // | | Extra info | | 290 // | | Extra info | |
| 270 // ------------------------- | 291 // ------------------------- |
| 271 // | 292 // |
| 272 // Icon and Heading are always shown (as well as the close button). | 293 // Icon and Heading are always shown (as well as the close button). |
| 273 // Info is shown for browser actions, page actions and Omnibox keyword | 294 // Info is shown for browser actions, page actions and Omnibox keyword |
| 274 // extensions and might list keyboard shorcut for the former two types. | 295 // extensions and might list keyboard shorcut for the former two types. |
| 275 // Extra info is... | 296 // Extra info is... |
| 276 // ... for other types, either a description of how to manage the extension | 297 // ... for other types, either a description of how to manage the extension |
| 277 // or a link to configure the keybinding shortcut (if one exists). | 298 // or a link to configure the keybinding shortcut (if one exists). |
| 278 // Extra info can include a promo for signing into sync. | 299 // Extra info can include a promo for signing into sync. |
| 279 | 300 |
| 280 const ExtensionInstalledBubble& bubble = *bubble_; | |
| 281 // The number of rows in the content section of the bubble. | 301 // The number of rows in the content section of the bubble. |
| 282 int main_content_row_count = 1; | 302 int main_content_row_count = 1; |
| 283 if (bubble.options() & ExtensionInstalledBubble::HOW_TO_USE) | 303 if (controller_->options() & ExtensionInstalledBubble::HOW_TO_USE) |
| 284 ++main_content_row_count; | 304 ++main_content_row_count; |
| 285 if (bubble.options() & ExtensionInstalledBubble::SHOW_KEYBINDING) | 305 if (controller_->options() & ExtensionInstalledBubble::SHOW_KEYBINDING) |
| 286 ++main_content_row_count; | 306 ++main_content_row_count; |
| 287 if (bubble.options() & ExtensionInstalledBubble::HOW_TO_MANAGE) | 307 if (controller_->options() & ExtensionInstalledBubble::HOW_TO_MANAGE) |
| 288 ++main_content_row_count; | 308 ++main_content_row_count; |
| 289 | 309 |
| 290 views::GridLayout* layout = new views::GridLayout(this); | 310 views::GridLayout* layout = new views::GridLayout(this); |
| 291 SetLayoutManager(layout); | 311 SetLayoutManager(layout); |
| 292 | 312 |
| 293 const int cs_id = 0; | 313 const int cs_id = 0; |
| 294 | 314 |
| 295 views::ColumnSet* main_cs = layout->AddColumnSet(cs_id); | 315 views::ColumnSet* main_cs = layout->AddColumnSet(cs_id); |
| 296 // Icon column. | 316 // Icon column. |
| 297 main_cs->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, 0, | 317 main_cs->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, 0, |
| 298 views::GridLayout::USE_PREF, 0, 0); | 318 views::GridLayout::USE_PREF, 0, 0); |
| 299 main_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing); | 319 main_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing); |
| 300 // Heading column. | 320 // Heading column. |
| 301 main_cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0, | 321 main_cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0, |
| 302 views::GridLayout::FIXED, kRightColumnWidth, 0); | 322 views::GridLayout::FIXED, kRightColumnWidth, 0); |
| 303 | 323 |
| 304 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 324 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 305 const gfx::FontList& font_list = rb.GetFontList(ui::ResourceBundle::BaseFont); | 325 const gfx::FontList& font_list = rb.GetFontList(ui::ResourceBundle::BaseFont); |
| 306 | 326 |
| 307 const SkBitmap& bitmap = bubble.icon(); | 327 const SkBitmap& bitmap = controller_->icon(); |
| 308 // Add the icon (for all options). | 328 // Add the icon (for all options). |
| 309 // Scale down to 43x43, but allow smaller icons (don't scale up). | 329 // Scale down to 43x43, but allow smaller icons (don't scale up). |
| 310 gfx::Size size(bitmap.width(), bitmap.height()); | 330 gfx::Size size(bitmap.width(), bitmap.height()); |
| 311 if (size.width() > kIconSize || size.height() > kIconSize) | 331 if (size.width() > kIconSize || size.height() > kIconSize) |
| 312 size = gfx::Size(kIconSize, kIconSize); | 332 size = gfx::Size(kIconSize, kIconSize); |
| 313 views::ImageView* icon = new views::ImageView(); | 333 views::ImageView* icon = new views::ImageView(); |
| 314 icon->SetImageSize(size); | 334 icon->SetImageSize(size); |
| 315 icon->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(bitmap)); | 335 icon->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(bitmap)); |
| 316 | 336 |
| 317 layout->StartRow(0, cs_id); | 337 layout->StartRow(0, cs_id); |
| 318 layout->AddView(icon, 1, main_content_row_count); | 338 layout->AddView(icon, 1, main_content_row_count); |
| 319 | 339 |
| 320 // Add the heading (for all options). | 340 // Add the heading (for all options). |
| 321 base::string16 extension_name = base::UTF8ToUTF16(extension_->name()); | 341 base::string16 extension_name = |
| 342 base::UTF8ToUTF16(controller_->extension()->name()); |
| 322 base::i18n::AdjustStringForLocaleDirection(&extension_name); | 343 base::i18n::AdjustStringForLocaleDirection(&extension_name); |
| 323 views::Label* heading = | 344 views::Label* heading = |
| 324 CreateLabel(l10n_util::GetStringFUTF16(IDS_EXTENSION_INSTALLED_HEADING, | 345 CreateLabel(l10n_util::GetStringFUTF16(IDS_EXTENSION_INSTALLED_HEADING, |
| 325 extension_name), | 346 extension_name), |
| 326 rb.GetFontList(ui::ResourceBundle::MediumFont)); | 347 rb.GetFontList(ui::ResourceBundle::MediumFont)); |
| 327 | 348 |
| 328 close_ = views::BubbleFrameView::CreateCloseButton(this); | 349 close_ = views::BubbleFrameView::CreateCloseButton(this); |
| 329 | 350 |
| 330 HeadingAndCloseButtonView* heading_and_close = | 351 HeadingAndCloseButtonView* heading_and_close = |
| 331 new HeadingAndCloseButtonView(heading, close_); | 352 new HeadingAndCloseButtonView(heading, close_); |
| 332 | 353 |
| 333 layout->AddView(heading_and_close); | 354 layout->AddView(heading_and_close); |
| 334 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | 355 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 335 | 356 |
| 336 auto add_content_view = [&layout, &cs_id](views::View* view) { | 357 auto add_content_view = [&layout, &cs_id](views::View* view) { |
| 337 layout->StartRow(0, cs_id); | 358 layout->StartRow(0, cs_id); |
| 338 // Skip the icon column. | 359 // Skip the icon column. |
| 339 layout->SkipColumns(1); | 360 layout->SkipColumns(1); |
| 340 layout->AddView(view); | 361 layout->AddView(view); |
| 341 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | 362 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 342 }; | 363 }; |
| 343 | 364 |
| 344 if (bubble.options() & ExtensionInstalledBubble::HOW_TO_USE) { | 365 if (controller_->options() & ExtensionInstalledBubble::HOW_TO_USE) { |
| 345 add_content_view(CreateLabel(bubble.GetHowToUseDescription(), font_list)); | 366 add_content_view( |
| 367 CreateLabel(controller_->GetHowToUseDescription(), font_list)); |
| 346 } | 368 } |
| 347 | 369 |
| 348 if (bubble.options() & ExtensionInstalledBubble::SHOW_KEYBINDING) { | 370 if (controller_->options() & ExtensionInstalledBubble::SHOW_KEYBINDING) { |
| 349 manage_shortcut_ = new views::Link( | 371 manage_shortcut_ = new views::Link( |
| 350 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_SHORTCUTS)); | 372 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_SHORTCUTS)); |
| 351 manage_shortcut_->set_listener(this); | 373 manage_shortcut_->set_listener(this); |
| 352 manage_shortcut_->SetUnderline(false); | 374 manage_shortcut_->SetUnderline(false); |
| 353 add_content_view(manage_shortcut_); | 375 add_content_view(manage_shortcut_); |
| 354 } | 376 } |
| 355 | 377 |
| 356 if (bubble.options() & ExtensionInstalledBubble::HOW_TO_MANAGE) { | 378 if (controller_->options() & ExtensionInstalledBubble::HOW_TO_MANAGE) { |
| 357 add_content_view(CreateLabel( | 379 add_content_view(CreateLabel( |
| 358 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_INFO), | 380 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_INFO), |
| 359 font_list)); | 381 font_list)); |
| 360 } | 382 } |
| 361 } | 383 } |
| 362 | 384 |
| 385 // NB: This bubble is using the temporarily-deprecated bubble manager interface |
| 386 // BubbleUi. Do not copy this pattern. |
| 387 class ExtensionInstalledBubbleUi : public BubbleUi, |
| 388 public views::WidgetObserver { |
| 389 public: |
| 390 explicit ExtensionInstalledBubbleUi(ExtensionInstalledBubble* bubble); |
| 391 ~ExtensionInstalledBubbleUi() override; |
| 392 |
| 393 // BubbleUi: |
| 394 void Show(BubbleReference bubble_reference) override; |
| 395 void Close() override; |
| 396 void UpdateAnchorPosition() override; |
| 397 |
| 398 // WidgetObserver: |
| 399 void OnWidgetClosing(views::Widget* widget) override; |
| 400 |
| 401 private: |
| 402 ExtensionInstalledBubble* bubble_; |
| 403 ExtensionInstalledBubbleView* bubble_view_; |
| 404 |
| 405 DISALLOW_COPY_AND_ASSIGN(ExtensionInstalledBubbleUi); |
| 406 }; |
| 407 |
| 408 ExtensionInstalledBubbleUi::ExtensionInstalledBubbleUi( |
| 409 ExtensionInstalledBubble* bubble) |
| 410 : bubble_(bubble), bubble_view_(nullptr) { |
| 411 DCHECK(bubble_); |
| 412 } |
| 413 |
| 414 ExtensionInstalledBubbleUi::~ExtensionInstalledBubbleUi() { |
| 415 if (bubble_view_) |
| 416 bubble_view_->GetWidget()->RemoveObserver(this); |
| 417 } |
| 418 |
| 419 void ExtensionInstalledBubbleUi::Show(BubbleReference /*bubble_reference*/) { |
| 420 bubble_view_ = new ExtensionInstalledBubbleView(bubble_); |
| 421 |
| 422 views::BubbleDialogDelegateView::CreateBubble(bubble_view_)->Show(); |
| 423 bubble_view_->GetWidget()->AddObserver(this); |
| 424 content::RecordAction( |
| 425 base::UserMetricsAction("Signin_Impression_FromExtensionInstallBubble")); |
| 426 } |
| 427 |
| 428 void ExtensionInstalledBubbleUi::Close() { |
| 429 if (bubble_view_) |
| 430 bubble_view_->CloseBubble(); |
| 431 } |
| 432 |
| 433 void ExtensionInstalledBubbleUi::UpdateAnchorPosition() { |
| 434 DCHECK(bubble_view_); |
| 435 bubble_view_->UpdateAnchorView(); |
| 436 } |
| 437 |
| 438 void ExtensionInstalledBubbleUi::OnWidgetClosing(views::Widget* widget) { |
| 439 widget->RemoveObserver(this); |
| 440 bubble_view_ = nullptr; |
| 441 } |
| 442 |
| 443 } // namespace |
| 444 |
| 363 // Views specific implementation. | 445 // Views specific implementation. |
| 364 bool ExtensionInstalledBubble::ShouldShow() { | 446 bool ExtensionInstalledBubble::ShouldShow() { |
| 365 if (anchor_position() == ANCHOR_BROWSER_ACTION) { | 447 if (anchor_position() == ANCHOR_BROWSER_ACTION) { |
| 366 BrowserActionsContainer* container = | 448 BrowserActionsContainer* container = |
| 367 BrowserView::GetBrowserViewForBrowser(browser()) | 449 BrowserView::GetBrowserViewForBrowser(browser()) |
| 368 ->GetToolbarView() | 450 ->GetToolbarView() |
| 369 ->browser_actions(); | 451 ->browser_actions(); |
| 370 return !container->animating(); | 452 return !container->animating(); |
| 371 } | 453 } |
| 372 return true; | 454 return true; |
| 373 } | 455 } |
| 374 | 456 |
| 375 class ExtensionInstalledBubbleUi : public BubbleUi { | |
| 376 public: | |
| 377 explicit ExtensionInstalledBubbleUi(ExtensionInstalledBubble* bubble); | |
| 378 ~ExtensionInstalledBubbleUi() override; | |
| 379 | |
| 380 private: | |
| 381 // BubbleUi: | |
| 382 void Show(BubbleReference bubble_reference) override; | |
| 383 void Close() override; | |
| 384 void UpdateAnchorPosition() override; | |
| 385 | |
| 386 ExtensionInstalledBubble* bubble_; | |
| 387 ExtensionInstalledBubbleView* delegate_view_; | |
| 388 | |
| 389 DISALLOW_COPY_AND_ASSIGN(ExtensionInstalledBubbleUi); | |
| 390 }; | |
| 391 | |
| 392 // Implemented here to create the platform specific instance of the BubbleUi. | 457 // Implemented here to create the platform specific instance of the BubbleUi. |
| 393 std::unique_ptr<BubbleUi> ExtensionInstalledBubble::BuildBubbleUi() { | 458 std::unique_ptr<BubbleUi> ExtensionInstalledBubble::BuildBubbleUi() { |
| 394 return base::WrapUnique(new ExtensionInstalledBubbleUi(this)); | 459 return base::WrapUnique(new ExtensionInstalledBubbleUi(this)); |
| 395 } | 460 } |
| 396 | |
| 397 ExtensionInstalledBubbleUi::ExtensionInstalledBubbleUi( | |
| 398 ExtensionInstalledBubble* bubble) | |
| 399 : bubble_(bubble), delegate_view_(nullptr) { | |
| 400 DCHECK(bubble_); | |
| 401 } | |
| 402 | |
| 403 ExtensionInstalledBubbleUi::~ExtensionInstalledBubbleUi() {} | |
| 404 | |
| 405 void ExtensionInstalledBubbleUi::Show(BubbleReference bubble_reference) { | |
| 406 // Owned by widget. | |
| 407 delegate_view_ = new ExtensionInstalledBubbleView(bubble_, bubble_reference); | |
| 408 delegate_view_->UpdateAnchorView(); | |
| 409 | |
| 410 delegate_view_->set_arrow(bubble_->type() == bubble_->OMNIBOX_KEYWORD | |
| 411 ? views::BubbleBorder::TOP_LEFT | |
| 412 : views::BubbleBorder::TOP_RIGHT); | |
| 413 | |
| 414 delegate_view_->InitLayout(); | |
| 415 | |
| 416 views::BubbleDelegateView::CreateBubble(delegate_view_)->Show(); | |
| 417 content::RecordAction( | |
| 418 base::UserMetricsAction("Signin_Impression_FromExtensionInstallBubble")); | |
| 419 } | |
| 420 | |
| 421 void ExtensionInstalledBubbleUi::Close() { | |
| 422 if (delegate_view_) { | |
| 423 delegate_view_->GetWidget()->Close(); | |
| 424 delegate_view_ = nullptr; | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 void ExtensionInstalledBubbleUi::UpdateAnchorPosition() { | |
| 429 DCHECK(delegate_view_); | |
| 430 delegate_view_->UpdateAnchorView(); | |
| 431 } | |
| OLD | NEW |