| // 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/script_bubble_view.h" |
| |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/extension_system.h" |
| #include "chrome/browser/extensions/image_loader.h" |
| #include "chrome/browser/extensions/script_bubble_controller.h" |
| #include "chrome/browser/extensions/tab_helper.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/manifest_handlers/icons_handler.h" |
| #include "chrome/common/url_constants.h" |
| #include "content/public/browser/page_navigator.h" |
| #include "content/public/browser/web_contents.h" |
| #include "extensions/common/extension_resource.h" |
| #include "grit/generated_resources.h" |
| #include "grit/locale_settings.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/views/controls/image_view.h" |
| #include "ui/views/controls/label.h" |
| #include "ui/views/controls/link.h" |
| #include "ui/views/layout/grid_layout.h" |
| #include "ui/views/widget/widget.h" |
| |
| using content::OpenURLParams; |
| using content::Referrer; |
| using content::WebContents; |
| using extensions::Extension; |
| using extensions::ExtensionSystem; |
| using extensions::ScriptBubbleController; |
| |
| namespace { |
| |
| // Layout constants. |
| const int kInsetTop = 7; |
| const int kInsetLeft = 14; |
| const int kInsetBottom = 11; |
| const int kPaddingBelowHeadline = 12; |
| const int kPaddingRightOfIcon = 8; |
| const int kPaddingBetweenRows = 13; |
| |
| } // namespace |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // ScriptBubbleView |
| |
| ScriptBubbleView::ScriptEntry::ScriptEntry() |
| : extension_imageview(NULL) {} |
| |
| ScriptBubbleView::ScriptBubbleView(views::View* anchor_view, |
| WebContents* web_contents) |
| : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT), |
| height_(0), |
| web_contents_(web_contents) { |
| // Compensate for built-in vertical padding in the anchor view's image. |
| set_anchor_view_insets(gfx::Insets(5, 0, 5, 0)); |
| |
| extensions::ScriptBubbleController* script_bubble_controller = |
| GetScriptBubbleController(); |
| const std::set<std::string>& extensions_running_scripts = |
| script_bubble_controller->extensions_running_scripts(); |
| Profile* profile = Profile::FromBrowserContext( |
| web_contents_->GetBrowserContext()); |
| ExtensionService* extension_service = |
| ExtensionSystem::Get(profile)->extension_service(); |
| |
| size_t i = 0; |
| for (std::set<std::string>::const_iterator iter = |
| extensions_running_scripts.begin(); |
| iter != extensions_running_scripts.end(); ++iter, ++i) { |
| // We specify |true| to get disabled extensions as well, since content |
| // scripts survive their extensions being disabled. |
| const Extension* extension = |
| extension_service->GetExtensionById(*iter, true); |
| ScriptEntry entry; |
| entry.extension_id = *iter; |
| entry.extension_name = UTF8ToUTF16(extension->name()); |
| entries_.push_back(entry); |
| |
| int size = extension_misc::EXTENSION_ICON_BITTY; |
| extensions::ExtensionResource image = |
| extensions::IconsInfo::GetIconResource(extension, |
| size, |
| ExtensionIconSet::MATCH_BIGGER); |
| extensions::ImageLoader::Get(profile)->LoadImageAsync( |
| extension, image, gfx::Size(size, size), |
| base::Bind(&ScriptBubbleView::OnImageLoaded, AsWeakPtr(), i)); |
| } |
| } |
| |
| ScriptBubbleView::~ScriptBubbleView() { |
| } |
| |
| gfx::Size ScriptBubbleView::GetPreferredSize() { |
| gfx::Size size(views::Widget::GetLocalizedContentsSize( |
| IDS_SCRIPTBUBBLE_WIDTH_CHARS, |
| IDS_SCRIPTBUBBLE_HEIGHT_LINES)); |
| size.set_height(std::max(size.height(), height_)); |
| return size; |
| } |
| |
| void ScriptBubbleView::LinkClicked(views::Link* source, int event_flags) { |
| std::string link(chrome::kChromeUIExtensionsURL); |
| link += std::string("?id=") + |
| entries_[source->id()].extension_id; |
| web_contents_->OpenURL(OpenURLParams(GURL(link), |
| Referrer(), |
| NEW_FOREGROUND_TAB, |
| content::PAGE_TRANSITION_LINK, |
| false)); |
| } |
| |
| void ScriptBubbleView::Init() { |
| height_ = 0; |
| |
| views::GridLayout* layout = new views::GridLayout(this); |
| SetLayoutManager(layout); |
| layout->SetInsets(kInsetTop, kInsetLeft, 0, 0); |
| height_ = kInsetTop + kInsetBottom; |
| |
| // Add a column for the heading (one large text column). |
| views::ColumnSet* columns = layout->AddColumnSet(0); |
| columns->AddColumn(views::GridLayout::LEADING, // Horizontal resize. |
| views::GridLayout::FILL, // Vertical resize. |
| 1, // Resize weight. |
| views::GridLayout::USE_PREF, // Size type. |
| 0, // Ignored for USE_PREF. |
| 0); // Minimum size. |
| |
| // Add a column set for the extension image plus name. |
| columns = layout->AddColumnSet(1); |
| columns->AddColumn(views::GridLayout::LEADING, // Horizontal resize. |
| views::GridLayout::FILL, // Vertical resize. |
| 0, // Resize weight. |
| views::GridLayout::USE_PREF, // Size type. |
| 0, // Ignored for USE_PREF. |
| 0); // Minimum size. |
| |
| columns->AddPaddingColumn(0, // resize_percent. |
| kPaddingRightOfIcon); // width. |
| |
| columns->AddColumn(views::GridLayout::LEADING, // Horizontal resize. |
| views::GridLayout::FILL, // Vertical resize. |
| 1, // Resize weight. |
| views::GridLayout::USE_PREF, // Size type. |
| 0, // Ignored for USE_PREF. |
| 0); // Minimum size. |
| |
| layout->StartRow(0, 0); |
| views::Label* heading = new views::Label( |
| l10n_util::GetStringUTF16(IDS_SCRIPT_BUBBLE_HEADLINE)); |
| layout->AddView(heading); |
| height_ += heading->GetPreferredSize().height(); |
| |
| layout->AddPaddingRow(0, kPaddingBelowHeadline); |
| height_ += kPaddingBelowHeadline; |
| |
| for (size_t i = 0; i < entries_.size(); ++i) { |
| layout->StartRow(0, 1); |
| |
| views::ImageView* image_view = new views::ImageView(); |
| entries_[i].extension_imageview = image_view; |
| image_view->SetImageSize(gfx::Size(16, 16)); |
| image_view->SetImage( |
| extensions::IconsInfo::GetDefaultExtensionIcon()); |
| layout->AddView(image_view); |
| |
| views::Link* link = new views::Link(entries_[i].extension_name); |
| link->set_id(i); |
| link->set_listener(this); |
| layout->AddView(link); |
| |
| height_ += std::max(image_view->GetPreferredSize().height(), |
| link->GetPreferredSize().height()); |
| |
| if (i + 1 < entries_.size()) { |
| layout->AddPaddingRow(0, kPaddingBetweenRows); |
| height_ += kPaddingBetweenRows; |
| } |
| } |
| |
| layout->Layout(this); |
| } |
| |
| void ScriptBubbleView::OnImageLoaded(size_t index, |
| const gfx::Image& image) { |
| if (!image.IsEmpty()) { |
| const gfx::ImageSkia* image_skia = image.ToImageSkia(); |
| entries_[index].extension_imageview->SetImage(image_skia); |
| } |
| } |
| |
| ScriptBubbleController* ScriptBubbleView::GetScriptBubbleController() { |
| extensions::TabHelper* extensions_tab_helper = |
| extensions::TabHelper::FromWebContents(web_contents_); |
| return extensions_tab_helper->script_bubble_controller(); |
| } |