Index: chrome/browser/ui/views/extensions/extension_installed_bubble.cc |
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble.cc |
deleted file mode 100644 |
index e64e261ef6624ff214a72f531f65650e0987243b..0000000000000000000000000000000000000000 |
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble.cc |
+++ /dev/null |
@@ -1,686 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/ui/views/extensions/extension_installed_bubble.h" |
- |
-#include <algorithm> |
-#include <string> |
- |
-#include "base/bind.h" |
-#include "base/i18n/rtl.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "chrome/browser/chrome_notification_types.h" |
-#include "chrome/browser/extensions/api/commands/command_service.h" |
-#include "chrome/browser/extensions/extension_action.h" |
-#include "chrome/browser/extensions/extension_action_manager.h" |
-#include "chrome/browser/extensions/extension_install_ui.h" |
-#include "chrome/browser/profiles/profile.h" |
-#include "chrome/browser/signin/signin_promo.h" |
-#include "chrome/browser/ui/browser.h" |
-#include "chrome/browser/ui/browser_window.h" |
-#include "chrome/browser/ui/singleton_tabs.h" |
-#include "chrome/browser/ui/sync/sync_promo_ui.h" |
-#include "chrome/browser/ui/views/browser_action_view.h" |
-#include "chrome/browser/ui/views/browser_actions_container.h" |
-#include "chrome/browser/ui/views/frame/browser_view.h" |
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
-#include "chrome/browser/ui/views/tabs/tab_strip.h" |
-#include "chrome/browser/ui/views/toolbar_view.h" |
-#include "chrome/common/extensions/api/extension_action/action_info.h" |
-#include "chrome/common/extensions/api/omnibox/omnibox_handler.h" |
-#include "chrome/common/extensions/extension.h" |
-#include "chrome/common/extensions/sync_helper.h" |
-#include "chrome/common/url_constants.h" |
-#include "content/public/browser/notification_details.h" |
-#include "content/public/browser/notification_source.h" |
-#include "grit/chromium_strings.h" |
-#include "grit/generated_resources.h" |
-#include "grit/ui_resources.h" |
-#include "ui/base/l10n/l10n_util.h" |
-#include "ui/base/resource/resource_bundle.h" |
-#include "ui/base/text/text_elider.h" |
-#include "ui/gfx/render_text.h" |
-#include "ui/views/controls/button/image_button.h" |
-#include "ui/views/controls/image_view.h" |
-#include "ui/views/controls/label.h" |
-#include "ui/views/controls/link.h" |
-#include "ui/views/controls/link_listener.h" |
-#include "ui/views/layout/fill_layout.h" |
-#include "ui/views/layout/layout_constants.h" |
- |
-using extensions::Extension; |
- |
-namespace { |
- |
-const int kIconSize = 43; |
- |
-const int kRightColumnWidth = 285; |
- |
-// The Bubble uses a BubbleBorder which adds about 6 pixels of whitespace |
-// around the content view. We compensate by reducing our outer borders by this |
-// amount + 4px. |
-const int kOuterMarginInset = 10; |
-const int kHorizOuterMargin = views::kPanelHorizMargin - kOuterMarginInset; |
-const int kVertOuterMargin = views::kPanelVertMargin - kOuterMarginInset; |
- |
-// Interior vertical margin is 8px smaller than standard |
-const int kVertInnerMargin = views::kPanelVertMargin - 8; |
- |
-// We want to shift the right column (which contains the header and text) up |
-// 4px to align with icon. |
-const int kRightcolumnVerticalShift = -4; |
- |
-// How long to wait for browser action animations to complete before retrying. |
-const int kAnimationWaitTime = 50; |
- |
-// How often we retry when waiting for browser action animation to end. |
-const int kAnimationWaitMaxRetry = 10; |
- |
-} // namespace |
- |
-namespace chrome { |
- |
-void ShowExtensionInstalledBubble(const Extension* extension, |
- Browser* browser, |
- const SkBitmap& icon) { |
- ExtensionInstalledBubble::Show(extension, browser, icon); |
-} |
- |
-} // namespace chrome |
- |
-// InstalledBubbleContent is the content view which is placed in the |
-// ExtensionInstalledBubble. It displays the install icon and explanatory |
-// text about the installed extension. |
-class InstalledBubbleContent : public views::View, |
- public views::ButtonListener, |
- public views::LinkListener { |
- public: |
- InstalledBubbleContent(Browser* browser, |
- const Extension* extension, |
- ExtensionInstalledBubble::BubbleType type, |
- SkBitmap* icon, |
- ExtensionInstalledBubble* bubble) |
- : browser_(browser), |
- extension_id_(extension->id()), |
- bubble_(bubble), |
- type_(type), |
- flavors_(NONE), |
- height_of_signin_promo_(0u), |
- how_to_use_(NULL), |
- sign_in_link_(NULL), |
- manage_(NULL), |
- manage_shortcut_(NULL) { |
- // The Extension Installed bubble takes on various forms, depending on the |
- // type of extension installed. In general, though, they are all similar: |
- // |
- // ------------------------- |
- // | | Heading [X] | |
- // | Icon | Info | |
- // | | Extra info | |
- // ------------------------- |
- // |
- // Icon and Heading are always shown (as well as the close button). |
- // Info is shown for browser actions, page actions and Omnibox keyword |
- // extensions and might list keyboard shorcut for the former two types. |
- // Extra info is... |
- // ... for other types, either a description of how to manage the extension |
- // or a link to configure the keybinding shortcut (if one exists). |
- // Extra info can include a promo for signing into sync. |
- |
- // First figure out the keybinding situation. |
- extensions::Command command; |
- bool has_keybinding = GetKeybinding(&command); |
- string16 key; // Keyboard shortcut or keyword to display in the bubble. |
- |
- if (extensions::sync_helper::IsSyncableExtension(extension) && |
- SyncPromoUI::ShouldShowSyncPromo(browser->profile())) |
- flavors_ |= SIGN_IN_PROMO; |
- |
- // Determine the bubble flavor we want, based on the extension type. |
- switch (type_) { |
- case ExtensionInstalledBubble::BROWSER_ACTION: |
- case ExtensionInstalledBubble::PAGE_ACTION: { |
- flavors_ |= HOW_TO_USE; |
- if (has_keybinding) { |
- flavors_ |= SHOW_KEYBINDING; |
- key = command.accelerator().GetShortcutText(); |
- } else { |
- // The How-To-Use text makes the bubble seem a little crowded when the |
- // extension has a keybinding, so the How-To-Manage text is not shown |
- // in those cases. |
- flavors_ |= HOW_TO_MANAGE; |
- } |
- break; |
- } |
- case ExtensionInstalledBubble::OMNIBOX_KEYWORD: { |
- flavors_ |= HOW_TO_USE | HOW_TO_MANAGE; |
- key = UTF8ToUTF16(extensions::OmniboxInfo::GetKeyword(extension)); |
- break; |
- } |
- case ExtensionInstalledBubble::GENERIC: { |
- break; |
- } |
- default: { |
- // When adding a new bubble type, the flavor needs to be set. |
- COMPILE_ASSERT(ExtensionInstalledBubble::GENERIC == 3, |
- kBubbleTypeEnumHasChangedButNotThisSwitchStatement); |
- break; |
- } |
- } |
- |
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
- const gfx::Font& font = rb.GetFont(ui::ResourceBundle::BaseFont); |
- |
- // Add the icon (for all flavors). |
- // Scale down to 43x43, but allow smaller icons (don't scale up). |
- gfx::Size size(icon->width(), icon->height()); |
- if (size.width() > kIconSize || size.height() > kIconSize) |
- size = gfx::Size(kIconSize, kIconSize); |
- icon_ = new views::ImageView(); |
- icon_->SetImageSize(size); |
- icon_->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(*icon)); |
- AddChildView(icon_); |
- |
- // Add the heading (for all flavors). |
- string16 extension_name = UTF8ToUTF16(extension->name()); |
- base::i18n::AdjustStringForLocaleDirection(&extension_name); |
- heading_ = new views::Label(l10n_util::GetStringFUTF16( |
- IDS_EXTENSION_INSTALLED_HEADING, extension_name)); |
- heading_->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont)); |
- heading_->SetMultiLine(true); |
- heading_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- AddChildView(heading_); |
- |
- if (flavors_ & HOW_TO_USE) { |
- how_to_use_ = new views::Label(GetHowToUseDescription(key)); |
- how_to_use_->SetFont(font); |
- how_to_use_->SetMultiLine(true); |
- how_to_use_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- AddChildView(how_to_use_); |
- } |
- |
- if (flavors_ & SHOW_KEYBINDING) { |
- manage_shortcut_ = new views::Link( |
- l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_SHORTCUTS)); |
- manage_shortcut_->set_listener(this); |
- AddChildView(manage_shortcut_); |
- } |
- |
- if (flavors_ & HOW_TO_MANAGE) { |
- manage_ = new views::Label(l10n_util::GetStringUTF16( |
-#if defined(OS_CHROMEOS) |
- IDS_EXTENSION_INSTALLED_MANAGE_INFO_CHROMEOS)); |
-#else |
- IDS_EXTENSION_INSTALLED_MANAGE_INFO)); |
-#endif |
- manage_->SetFont(font); |
- manage_->SetMultiLine(true); |
- manage_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- AddChildView(manage_); |
- } |
- |
- if (flavors_ & SIGN_IN_PROMO) { |
- signin_promo_text_ = |
- l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_SIGNIN_PROMO); |
- |
- signin_promo_link_text_ = |
- l10n_util::GetStringFUTF16( |
- IDS_EXTENSION_INSTALLED_SIGNIN_PROMO_LINK, |
- l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); |
- sign_in_link_ = new views::Link(signin_promo_link_text_); |
- sign_in_link_->SetFont(font); |
- sign_in_link_->set_listener(this); |
- AddChildView(sign_in_link_); |
- } |
- |
- // Add the Close button (for all flavors). |
- close_button_ = new views::ImageButton(this); |
- close_button_->SetImage(views::CustomButton::STATE_NORMAL, |
- rb.GetImageSkiaNamed(IDR_CLOSE_2)); |
- close_button_->SetImage(views::CustomButton::STATE_HOVERED, |
- rb.GetImageSkiaNamed(IDR_CLOSE_2_H)); |
- close_button_->SetImage(views::CustomButton::STATE_PRESSED, |
- rb.GetImageSkiaNamed(IDR_CLOSE_2_P)); |
- AddChildView(close_button_); |
- } |
- |
- virtual void ButtonPressed(views::Button* sender, |
- const ui::Event& event) OVERRIDE { |
- if (sender == close_button_) |
- bubble_->StartFade(false); |
- else |
- NOTREACHED() << "Unknown view"; |
- } |
- |
- // Implements the views::LinkListener interface. |
- virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE { |
- GetWidget()->Close(); |
- std::string configure_url; |
- if (source == manage_shortcut_) { |
- configure_url = chrome::kChromeUIExtensionsURL; |
- configure_url += chrome::kExtensionConfigureCommandsSubPage; |
- } else if (source == sign_in_link_) { |
- configure_url = signin::GetPromoURL( |
- signin::SOURCE_EXTENSION_INSTALL_BUBBLE, false).spec(); |
- } else { |
- NOTREACHED(); |
- return; |
- } |
- chrome::NavigateParams params( |
- chrome::GetSingletonTabNavigateParams( |
- browser_, GURL(configure_url.c_str()))); |
- chrome::Navigate(¶ms); |
- } |
- |
- private: |
- enum Flavors { |
- NONE = 0, |
- HOW_TO_USE = 1 << 0, |
- HOW_TO_MANAGE = 1 << 1, |
- SHOW_KEYBINDING = 1 << 2, |
- SIGN_IN_PROMO = 1 << 3, |
- }; |
- |
- bool GetKeybinding(extensions::Command* command) { |
- extensions::CommandService* command_service = |
- extensions::CommandService::Get(browser_->profile()); |
- if (type_ == ExtensionInstalledBubble::BROWSER_ACTION) { |
- return command_service->GetBrowserActionCommand( |
- extension_id_, |
- extensions::CommandService::ACTIVE_ONLY, |
- command, |
- NULL); |
- } else if (type_ == ExtensionInstalledBubble::PAGE_ACTION) { |
- return command_service->GetPageActionCommand( |
- extension_id_, |
- extensions::CommandService::ACTIVE_ONLY, |
- command, |
- NULL); |
- } else { |
- return false; |
- } |
- } |
- |
- string16 GetHowToUseDescription(const string16& key) { |
- switch (type_) { |
- case ExtensionInstalledBubble::BROWSER_ACTION: |
- if (!key.empty()) { |
- return l10n_util::GetStringFUTF16( |
- IDS_EXTENSION_INSTALLED_BROWSER_ACTION_INFO_WITH_SHORTCUT, key); |
- } else { |
- return l10n_util::GetStringUTF16( |
- IDS_EXTENSION_INSTALLED_BROWSER_ACTION_INFO); |
- } |
- break; |
- case ExtensionInstalledBubble::PAGE_ACTION: |
- if (!key.empty()) { |
- return l10n_util::GetStringFUTF16( |
- IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO_WITH_SHORTCUT, key); |
- } else { |
- return l10n_util::GetStringUTF16( |
- IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO); |
- } |
- break; |
- case ExtensionInstalledBubble::OMNIBOX_KEYWORD: |
- return l10n_util::GetStringFUTF16( |
- IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO, key); |
- break; |
- default: |
- NOTREACHED(); |
- break; |
- } |
- return string16(); |
- } |
- |
- // Layout the signin promo at coordinates |offset_x| and |offset_y|. Returns |
- // the height (in pixels) of the promo UI. |
- int LayoutSigninPromo(int offset_x, int offset_y) { |
- sign_in_promo_lines_.clear(); |
- int height = 0; |
- gfx::Rect contents_area = GetContentsBounds(); |
- if (contents_area.IsEmpty()) |
- return height; |
- contents_area.set_width(kRightColumnWidth); |
- |
- string16 full_text = signin_promo_link_text_ + signin_promo_text_; |
- |
- // The link is the first item in the text. |
- const gfx::Size link_size = sign_in_link_->GetPreferredSize(); |
- sign_in_link_->SetBounds( |
- offset_x, offset_y, link_size.width(), link_size.height()); |
- |
- // Word-wrap the full label text. |
- const gfx::Font font; |
- std::vector<string16> lines; |
- ui::ElideRectangleText(full_text, font, contents_area.width(), |
- contents_area.height(), ui::ELIDE_LONG_WORDS, |
- &lines); |
- |
- gfx::Point position = gfx::Point( |
- contents_area.origin().x() + offset_x, |
- contents_area.origin().y() + offset_y + 1); |
- if (base::i18n::IsRTL()) { |
- position -= gfx::Vector2d( |
- 2 * views::kPanelHorizMargin + kHorizOuterMargin, 0); |
- } |
- |
- // Loop through the lines, creating a renderer for each. |
- for (std::vector<string16>::const_iterator it = lines.begin(); |
- it != lines.end(); ++it) { |
- gfx::RenderText* line = gfx::RenderText::CreateInstance(); |
- line->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_UI); |
- line->SetText(*it); |
- const gfx::Size size(contents_area.width(), |
- line->GetStringSize().height()); |
- line->SetDisplayRect(gfx::Rect(position, size)); |
- position.set_y(position.y() + size.height()); |
- sign_in_promo_lines_.push_back(line); |
- height += size.height(); |
- } |
- |
- // The link is drawn separately; make it transparent here to only draw once. |
- // The link always leads other text and is assumed to fit on the first line. |
- sign_in_promo_lines_.front()->ApplyColor(SK_ColorTRANSPARENT, |
- ui::Range(0, signin_promo_link_text_.size())); |
- |
- return height; |
- } |
- |
- virtual gfx::Size GetPreferredSize() OVERRIDE { |
- int width = kHorizOuterMargin; |
- width += kIconSize; |
- width += views::kPanelHorizMargin; |
- width += kRightColumnWidth; |
- width += 2 * views::kPanelHorizMargin; |
- width += kHorizOuterMargin; |
- |
- int height = kVertOuterMargin; |
- height += heading_->GetHeightForWidth(kRightColumnWidth); |
- height += kVertInnerMargin; |
- |
- if (flavors_ & HOW_TO_USE) { |
- height += how_to_use_->GetHeightForWidth(kRightColumnWidth); |
- height += kVertInnerMargin; |
- } |
- |
- if (flavors_ & HOW_TO_MANAGE) { |
- height += manage_->GetHeightForWidth(kRightColumnWidth); |
- height += kVertInnerMargin; |
- } |
- |
- if (flavors_ & SIGN_IN_PROMO && height_of_signin_promo_ > 0u) { |
- height += height_of_signin_promo_; |
- height += kVertInnerMargin; |
- } |
- |
- if (flavors_ & SHOW_KEYBINDING) { |
- height += manage_shortcut_->GetHeightForWidth(kRightColumnWidth); |
- height += kVertInnerMargin; |
- } |
- |
- return gfx::Size(width, std::max(height, kIconSize + 2 * kVertOuterMargin)); |
- } |
- |
- virtual void Layout() OVERRIDE { |
- int x = kHorizOuterMargin; |
- int y = kVertOuterMargin; |
- |
- icon_->SetBounds(x, y, kIconSize, kIconSize); |
- x += kIconSize; |
- x += views::kPanelHorizMargin; |
- |
- y += kRightcolumnVerticalShift; |
- heading_->SizeToFit(kRightColumnWidth); |
- heading_->SetX(x); |
- heading_->SetY(y); |
- y += heading_->height(); |
- y += kVertInnerMargin; |
- |
- if (flavors_ & HOW_TO_USE) { |
- how_to_use_->SizeToFit(kRightColumnWidth); |
- how_to_use_->SetX(x); |
- how_to_use_->SetY(y); |
- y += how_to_use_->height(); |
- y += kVertInnerMargin; |
- } |
- |
- if (flavors_ & HOW_TO_MANAGE) { |
- manage_->SizeToFit(kRightColumnWidth); |
- manage_->SetX(x); |
- manage_->SetY(y); |
- y += manage_->height(); |
- y += kVertInnerMargin; |
- } |
- |
- if (flavors_ & SIGN_IN_PROMO) { |
- height_of_signin_promo_ = LayoutSigninPromo(x, y); |
- y += height_of_signin_promo_; |
- y += kVertInnerMargin; |
- } |
- |
- if (flavors_ & SHOW_KEYBINDING) { |
- gfx::Size sz = manage_shortcut_->GetPreferredSize(); |
- manage_shortcut_->SetBounds(width() - 2 * kHorizOuterMargin - sz.width(), |
- y, |
- sz.width(), |
- sz.height()); |
- y += manage_shortcut_->height(); |
- y += kVertInnerMargin; |
- } |
- |
- gfx::Size sz; |
- x += kRightColumnWidth + 2 * views::kPanelHorizMargin + kHorizOuterMargin - |
- close_button_->GetPreferredSize().width(); |
- y = kVertOuterMargin; |
- sz = close_button_->GetPreferredSize(); |
- // x-1 & y-1 is just slop to get the close button visually aligned with the |
- // title text and bubble arrow. |
- close_button_->SetBounds(x - 1, y - 1, sz.width(), sz.height()); |
- } |
- |
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { |
- for (ScopedVector<gfx::RenderText>::const_iterator it = |
- sign_in_promo_lines_.begin(); |
- it != sign_in_promo_lines_.end(); ++it) |
- (*it)->Draw(canvas); |
- |
- views::View::OnPaint(canvas); |
- } |
- |
- // The browser we're associated with. |
- Browser* browser_; |
- |
- // The id of the extension just installed. |
- const std::string extension_id_; |
- |
- // The ExtensionInstalledBubble showing us. |
- ExtensionInstalledBubble* bubble_; |
- |
- // The string that contains the link text at the beginning of the sign-in |
- // promo text. |
- string16 signin_promo_link_text_; |
- // The remaining text of the sign-in promo text. |
- string16 signin_promo_text_; |
- |
- // A vector of RenderText objects representing the full sign-in promo |
- // paragraph as layed out within the bubble, but has the text of the link |
- // whited out so the link can be drawn in its place. |
- ScopedVector<gfx::RenderText> sign_in_promo_lines_; |
- |
- // The type of the bubble to show (Browser Action, Omnibox keyword, etc). |
- ExtensionInstalledBubble::BubbleType type_; |
- |
- // A bitmask containing the various flavors of bubble sections to show. |
- int flavors_; |
- |
- // The height, in pixels, of the sign-in promo. |
- size_t height_of_signin_promo_; |
- |
- views::ImageView* icon_; |
- views::Label* heading_; |
- views::Label* how_to_use_; |
- views::Link* sign_in_link_; |
- views::Label* manage_; |
- views::Link* manage_shortcut_; |
- views::ImageButton* close_button_; |
- |
- DISALLOW_COPY_AND_ASSIGN(InstalledBubbleContent); |
-}; |
- |
-void ExtensionInstalledBubble::Show(const Extension* extension, |
- Browser *browser, |
- const SkBitmap& icon) { |
- new ExtensionInstalledBubble(extension, browser, icon); |
-} |
- |
-ExtensionInstalledBubble::ExtensionInstalledBubble(const Extension* extension, |
- Browser *browser, |
- const SkBitmap& icon) |
- : extension_(extension), |
- browser_(browser), |
- icon_(icon), |
- animation_wait_retries_(0), |
- weak_factory_(this) { |
- if (!extensions::OmniboxInfo::GetKeyword(extension).empty()) |
- type_ = OMNIBOX_KEYWORD; |
- else if (extensions::ActionInfo::GetBrowserActionInfo(extension)) |
- type_ = BROWSER_ACTION; |
- else if (extensions::ActionInfo::GetPageActionInfo(extension) && |
- extensions::ActionInfo::IsVerboseInstallMessage(extension)) |
- type_ = PAGE_ACTION; |
- else |
- type_ = GENERIC; |
- |
- // |extension| has been initialized but not loaded at this point. We need |
- // to wait on showing the Bubble until not only the EXTENSION_LOADED gets |
- // fired, but all of the EXTENSION_LOADED Observers have run. Only then can we |
- // be sure that a BrowserAction or PageAction has had views created which we |
- // can inspect for the purpose of previewing of pointing to them. |
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
- content::Source<Profile>(browser->profile())); |
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
- content::Source<Profile>(browser->profile())); |
- registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSING, |
- content::Source<Browser>(browser)); |
-} |
- |
-ExtensionInstalledBubble::~ExtensionInstalledBubble() {} |
- |
-void ExtensionInstalledBubble::Observe( |
- int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) { |
- if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { |
- const Extension* extension = |
- content::Details<const Extension>(details).ptr(); |
- if (extension == extension_) { |
- animation_wait_retries_ = 0; |
- // PostTask to ourself to allow all EXTENSION_LOADED Observers to run. |
- base::MessageLoopForUI::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&ExtensionInstalledBubble::ShowInternal, |
- weak_factory_.GetWeakPtr())); |
- } |
- } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { |
- const Extension* extension = |
- content::Details<extensions::UnloadedExtensionInfo>(details)->extension; |
- if (extension == extension_) { |
- // Extension is going away, make sure ShowInternal won't be called. |
- weak_factory_.InvalidateWeakPtrs(); |
- extension_ = NULL; |
- } |
- } else if (type == chrome::NOTIFICATION_BROWSER_CLOSING) { |
- delete this; |
- } else { |
- NOTREACHED() << L"Received unexpected notification"; |
- } |
-} |
- |
-void ExtensionInstalledBubble::ShowInternal() { |
- BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); |
- extensions::ExtensionActionManager* extension_action_manager = |
- extensions::ExtensionActionManager::Get(browser_->profile()); |
- |
- views::View* reference_view = NULL; |
- if (type_ == BROWSER_ACTION) { |
- BrowserActionsContainer* container = |
- browser_view->GetToolbarView()->browser_actions(); |
- if (container->animating() && |
- animation_wait_retries_++ < kAnimationWaitMaxRetry) { |
- // We don't know where the view will be until the container has stopped |
- // animating, so check back in a little while. |
- base::MessageLoopForUI::current()->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&ExtensionInstalledBubble::ShowInternal, |
- weak_factory_.GetWeakPtr()), |
- base::TimeDelta::FromMilliseconds(kAnimationWaitTime)); |
- return; |
- } |
- reference_view = container->GetBrowserActionView( |
- extension_action_manager->GetBrowserAction(*extension_)); |
- // If the view is not visible then it is in the chevron, so point the |
- // install bubble to the chevron instead. If this is an incognito window, |
- // both could be invisible. |
- if (!reference_view || !reference_view->visible()) { |
- reference_view = container->chevron(); |
- if (!reference_view || !reference_view->visible()) |
- reference_view = NULL; // fall back to app menu below. |
- } |
- } else if (type_ == PAGE_ACTION) { |
- LocationBarView* location_bar_view = browser_view->GetLocationBarView(); |
- ExtensionAction* page_action = |
- extension_action_manager->GetPageAction(*extension_); |
- location_bar_view->SetPreviewEnabledPageAction(page_action, |
- true); // preview_enabled |
- reference_view = location_bar_view->GetPageActionView(page_action); |
- DCHECK(reference_view); |
- } else if (type_ == OMNIBOX_KEYWORD) { |
- LocationBarView* location_bar_view = browser_view->GetLocationBarView(); |
- reference_view = location_bar_view; |
- DCHECK(reference_view); |
- } |
- |
- // Default case. |
- if (reference_view == NULL) |
- reference_view = browser_view->GetToolbarView()->app_menu(); |
- set_anchor_view(reference_view); |
- |
- set_arrow(type_ == OMNIBOX_KEYWORD ? views::BubbleBorder::TOP_LEFT : |
- views::BubbleBorder::TOP_RIGHT); |
- SetLayoutManager(new views::FillLayout()); |
- AddChildView( |
- new InstalledBubbleContent(browser_, extension_, type_, &icon_, this)); |
- |
- views::BubbleDelegateView::CreateBubble(this); |
- |
- // The bubble widget is now the parent and owner of |this| and takes care of |
- // deletion when the bubble or browser go away. |
- registrar_.Remove(this, chrome::NOTIFICATION_BROWSER_CLOSING, |
- content::Source<Browser>(browser_)); |
- |
- StartFade(true); |
-} |
- |
-gfx::Rect ExtensionInstalledBubble::GetAnchorRect() { |
- // For omnibox keyword bubbles, move the arrow to point to the left edge |
- // of the omnibox, just to the right of the icon. |
- if (type_ == OMNIBOX_KEYWORD) { |
- LocationBarView* location_bar_view = |
- BrowserView::GetBrowserViewForBrowser(browser_)->GetLocationBarView(); |
- return gfx::Rect(location_bar_view->GetLocationEntryOrigin(), |
- gfx::Size(0, location_bar_view->location_entry_view()->height())); |
- } |
- return views::BubbleDelegateView::GetAnchorRect(); |
-} |
- |
-void ExtensionInstalledBubble::WindowClosing() { |
- if (extension_ && type_ == PAGE_ACTION) { |
- BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); |
- browser_view->GetLocationBarView()->SetPreviewEnabledPageAction( |
- extensions::ExtensionActionManager::Get(browser_->profile())-> |
- GetPageAction(*extension_), |
- false); // preview_enabled |
- } |
-} |