// 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/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.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& 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::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(); }