Commit edee3faf authored by jianli@chromium.org's avatar jianli@chromium.org

Show "About panel" bubble on Windows.

BUG=none
TEST=panel_browser_view_browsertest
Review URL: http://codereview.chromium.org/7011015

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86712 0039d316-1c4b-4281-b951-d872f2087c98
parent 7fa7b196
......@@ -12496,6 +12496,17 @@ Keep your key file in a safe place. You will need it to create new versions of y
bookmarks_<ph name="DATESTAMP">$1<ex>02_11_11</ex></ph>.html
</message>
<!-- Panels -->
<message name="IDS_ABOUT_PANEL_BUBBLE_EXTENSION_INSTALL_DATE" desc="Text for the label of the about panel bubble to show the extension install date.">
Extension installed: <ph name="DATE">$1<ex>January 1, 2011</ex></ph>
</message>
<message name="IDS_ABOUT_PANEL_BUBBLE_UNINSTALL_EXTENSION" desc="Text for the link shown on the about panel bubble to uninstall the extension.">
Uninstall <ph name="EXTENSION_NAME">$1<ex>Sample Extension</ex></ph>
</message>
<message name="IDS_ABOUT_PANEL_BUBBLE_REPORT_ABUSE" desc="Text for the link shown on the about panel bubble to report the abuse.">
Report abuse
</message>
</messages>
<includes>
<if expr="pp_ifdef('_google_chrome')">
......
......@@ -553,6 +553,15 @@
<message name="IDS_DEFAULT_SEARCH_WIDTH_CHARS" use_name_for_id="true">
82
</message>
<!-- The width and height of the About Panel Information bubble in -->
<!-- characters and lines (See above). -->
<message name="IDS_ABOUTPANELBUBBLE_WIDTH_CHARS" use_name_for_id="true">
56
</message>
<message name="IDS_ABOUTPANELBUBBLE_HEIGHT_LINES" use_name_for_id="true">
8
</message>
</messages>
</release>
</grit>
// Copyright (c) 2011 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/panels/about_panel_bubble.h"
#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/extensions/extension.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/controls/link.h"
#include "views/controls/textfield/textfield.h"
#include "views/window/window.h"
namespace {
// Extra padding to put around content over what the InfoBubble provides.
const int kBubblePadding = 4;
// Horizontal spacing between the icon and the contents.
const int kIconHorizontalSpacing = 4;
// Vertical spacing between two controls.
const int kControlVerticalSpacing = 10;
// Horizontal spacing between the text and the left/right of a description.
const int kDescriptionHorizontalSpacing = 6;
// Vertical spacing between the text and the top/bottom of a description.
const int kDescriptionVertialSpacing = 4;
// Horizontal spacing between two links.
const int kLinksHorizontalSpacing = 20;
// Text color of a description.
const SkColor kDescriptionTextColor = SK_ColorBLACK;
// Background color of a description.
const SkColor kDescriptionBackgroundColor = 0xFFE8E8EE;
}
// AboutPanelBubbleView --------------------------------------------------------
AboutPanelBubble::AboutPanelBubbleView::AboutPanelBubbleView(
SkBitmap icon, Browser* browser, const Extension* extension)
: icon_(NULL),
title_(NULL),
install_date_(NULL),
description_(NULL),
uninstall_link_(NULL),
report_abuse_link_(NULL) {
const gfx::Font& font =
ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont);
icon_ = new views::ImageView();
icon_->SetImage(icon);
AddChildView(icon_);
title_ = new views::Label(UTF8ToWide(extension->name()));
title_->SetFont(font.DeriveFont(0, gfx::Font::BOLD));
title_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
AddChildView(title_);
base::Time install_time = browser->GetProfile()->GetExtensionService()->
extension_prefs()->GetInstallTime(extension->id());
install_date_ = new views::Label(UTF16ToWide(
l10n_util::GetStringFUTF16(
IDS_ABOUT_PANEL_BUBBLE_EXTENSION_INSTALL_DATE,
base::TimeFormatFriendlyDate(install_time))));
install_date_->SetMultiLine(true);
install_date_->SetFont(font);
install_date_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
install_date_->SizeToFit(GetPreferredSize().width() - kBubblePadding * 2);
AddChildView(install_date_);
description_ = new views::Textfield(views::Textfield::STYLE_MULTILINE);
description_->SetText(UTF8ToUTF16(extension->description()));
description_->SetHeightInLines(2);
description_->SetHorizontalMargins(kDescriptionHorizontalSpacing,
kDescriptionHorizontalSpacing);
description_->SetVerticalMargins(kDescriptionVertialSpacing,
kDescriptionVertialSpacing);
description_->SetFont(font);
description_->SetTextColor(kDescriptionTextColor);
description_->SetBackgroundColor(kDescriptionBackgroundColor);
description_->RemoveBorder();
description_->SetReadOnly(true);
AddChildView(description_);
uninstall_link_ = new views::Link(UTF16ToWide(
l10n_util::GetStringFUTF16(IDS_ABOUT_PANEL_BUBBLE_UNINSTALL_EXTENSION,
UTF8ToUTF16(extension->name()))));
AddChildView(uninstall_link_);
report_abuse_link_ = new views::Link(UTF16ToWide(
l10n_util::GetStringUTF16(IDS_ABOUT_PANEL_BUBBLE_REPORT_ABUSE)));
AddChildView(report_abuse_link_);
}
void AboutPanelBubble::AboutPanelBubbleView::Layout() {
gfx::Size icon_size = icon_->GetPreferredSize();
icon_->SetBounds(kBubblePadding,
kBubblePadding,
icon_size.width(),
icon_size.height());
gfx::Size canvas = GetPreferredSize();
int content_left_margin =
kBubblePadding + icon_size.width() + kIconHorizontalSpacing;
int content_width = canvas.width() - kBubblePadding - content_left_margin;
gfx::Size pref_size = title_->GetPreferredSize();
title_->SetBounds(content_left_margin,
kBubblePadding,
content_width,
pref_size.height());
int next_y = title_->bounds().bottom() + kControlVerticalSpacing;
pref_size = install_date_->GetPreferredSize();
install_date_->SetBounds(content_left_margin,
next_y,
content_width,
pref_size.height());
next_y = install_date_->bounds().bottom() + kControlVerticalSpacing;
pref_size = description_->GetPreferredSize();
description_->SetBounds(
content_left_margin,
next_y,
content_width,
pref_size.height() + kDescriptionVertialSpacing * 2);
next_y = description_->bounds().bottom() + kControlVerticalSpacing;
pref_size = uninstall_link_->GetPreferredSize();
uninstall_link_->SetBounds(content_left_margin,
next_y,
pref_size.width(),
pref_size.height());
pref_size = report_abuse_link_->GetPreferredSize();
report_abuse_link_->SetBounds(
content_left_margin + uninstall_link_->width() + kLinksHorizontalSpacing,
next_y,
pref_size.width(),
pref_size.height());
}
gfx::Size AboutPanelBubble::AboutPanelBubbleView::GetPreferredSize() {
return views::Window::GetLocalizedContentsSize(
IDS_ABOUTPANELBUBBLE_WIDTH_CHARS,
IDS_ABOUTPANELBUBBLE_HEIGHT_LINES);
}
void AboutPanelBubble::AboutPanelBubbleView::LinkClicked(views::Link* source,
int event_flags) {
NOTIMPLEMENTED();
}
// AboutPanelBubble ------------------------------------------------------------
// static
AboutPanelBubble* AboutPanelBubble::Show(
views::Widget* parent,
const gfx::Rect& position_relative_to,
BubbleBorder::ArrowLocation arrow_location,
SkBitmap icon,
Browser* browser) {
// Find the extension. When we create a panel from an extension, the extension
// ID is passed as the app name to the Browser.
ExtensionService* extension_service =
browser->GetProfile()->GetExtensionService();
const Extension* extension = extension_service->GetExtensionById(
web_app::GetExtensionIdFromApplicationName(browser->app_name()), false);
if (!extension)
return NULL;
AboutPanelBubble* bubble = new AboutPanelBubble();
AboutPanelBubbleView* view = new AboutPanelBubbleView(
icon, browser, extension);
bubble->InitBubble(
parent, position_relative_to, arrow_location, view, bubble);
return bubble;
}
AboutPanelBubble::AboutPanelBubble() {
}
bool AboutPanelBubble::CloseOnEscape() {
return true;
}
bool AboutPanelBubble::FadeInOnShow() {
return false;
}
std::wstring AboutPanelBubble::accessible_name() {
return L"AboutPanelBubble";
}
// Copyright (c) 2011 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.
#ifndef CHROME_BROWSER_UI_PANELS_ABOUT_PANEL_BUBBLE_H_
#define CHROME_BROWSER_UI_PANELS_ABOUT_PANEL_BUBBLE_H_
#pragma once
#include "base/gtest_prod_util.h"
#include "chrome/browser/ui/views/bubble/bubble.h"
#include "views/controls/link_listener.h"
class Browser;
class Extension;
namespace views {
class ImageView;
class Label;
class Link;
class Textfield;
}
class AboutPanelBubble : public Bubble,
public BubbleDelegate {
public:
// Returns NULL if no extension can be found for |browser|.
static AboutPanelBubble* Show(views::Widget* parent,
const gfx::Rect& position_relative_to,
BubbleBorder::ArrowLocation arrow_location,
SkBitmap icon,
Browser* browser);
private:
friend class PanelBrowserViewTest;
FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, AboutPanelBubble);
class AboutPanelBubbleView : public views::View,
public views::LinkListener {
public:
AboutPanelBubbleView(SkBitmap icon,
Browser* browser,
const Extension* extension);
private:
friend class PanelBrowserViewTest;
FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, AboutPanelBubble);
virtual ~AboutPanelBubbleView() { }
// Overridden from View:
virtual void Layout() OVERRIDE;
virtual gfx::Size GetPreferredSize() OVERRIDE;
// Overridden from LinkListener:
virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
views::ImageView* icon_;
views::Label* title_;
views::Label* install_date_;
views::Textfield* description_;
views::Link* uninstall_link_;
views::Link* report_abuse_link_;
DISALLOW_COPY_AND_ASSIGN(AboutPanelBubbleView);
};
AboutPanelBubble();
virtual ~AboutPanelBubble() { }
// Overridden from BubbleDelegate:
virtual void BubbleClosing(Bubble* info_bubble, bool closed_by_escape)
OVERRIDE {}
virtual bool CloseOnEscape() OVERRIDE;
virtual bool FadeInOnShow() OVERRIDE;
virtual std::wstring accessible_name() OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(AboutPanelBubble);
};
#endif // CHROME_BROWSER_UI_PANELS_ABOUT_PANEL_BUBBLE_H_
......@@ -5,6 +5,7 @@
#include "chrome/browser/ui/panels/panel_browser_frame_view.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/ui/panels/about_panel_bubble.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_browser_view.h"
#include "chrome/browser/ui/panels/panel_manager.h"
......@@ -407,6 +408,16 @@ void PanelBrowserFrameView::ButtonPressed(views::Button* sender,
const views::Event& event) {
if (sender == close_button_)
frame_->Close();
else if (sender == info_button_) {
gfx::Point origin(info_button_->bounds().origin());
views::View::ConvertPointToScreen(this, &origin);
AboutPanelBubble::Show(
GetWidget(),
gfx::Rect(origin, info_button_->bounds().size()),
BubbleBorder::BOTTOM_RIGHT,
GetFaviconForTabIconView(),
browser_view_->browser());
}
}
bool PanelBrowserFrameView::ShouldTabIconViewAnimate() const {
......
......@@ -3,17 +3,27 @@
// found in the LICENSE file.
#include "base/command_line.h"
#include "base/i18n/time_formatting.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/panels/about_panel_bubble.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_browser_frame_view.h"
#include "chrome/browser/ui/panels/panel_browser_view.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/test/in_process_browser_test.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "views/controls/button/image_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/controls/link.h"
#include "views/controls/textfield/textfield.h"
class PanelBrowserViewTest : public InProcessBrowserTest {
public:
......@@ -406,4 +416,95 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, TitleBarMouseEvent) {
EXPECT_FALSE(browser_views[i]->panel());
}
}
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, AboutPanelBubble) {
ExtensionService* extension_service =
browser()->GetProfile()->GetExtensionService();
// Create a testing extension.
#if defined(OS_WIN)
FilePath path(FILE_PATH_LITERAL("c:\\foo"));
#else
FilePath path(FILE_PATH_LITERAL("/foo"));
#endif
DictionaryValue input_value;
input_value.SetString(extension_manifest_keys::kVersion, "1.0.0.0");
input_value.SetString(extension_manifest_keys::kName, "Sample Extension");
input_value.SetString(extension_manifest_keys::kDescription,
"Sample Description");
scoped_refptr<Extension> extension(Extension::Create(path, Extension::INVALID,
input_value, Extension::STRICT_ERROR_CHECKS, NULL));
ASSERT_TRUE(extension.get());
extension_service->AddExtension(extension.get());
// Make sure that async task ExtensionPrefs::OnExtensionInstalled gets a
// chance to be procesed.
MessageLoop::current()->RunAllPending();
extension_service->extension_prefs()->OnExtensionInstalled(
extension, Extension::ENABLED);
// Create a panel with the app name that comes from the extension ID.
PanelBrowserView* browser_view = CreatePanelBrowserView(
web_app::GenerateApplicationNameFromExtensionId(extension->id()));
AboutPanelBubble* bubble = AboutPanelBubble::Show(
browser_view->GetWidget(),
gfx::Rect(),
BubbleBorder::BOTTOM_RIGHT,
SkBitmap(),
browser_view->browser());
AboutPanelBubble::AboutPanelBubbleView* contents =
static_cast<AboutPanelBubble::AboutPanelBubbleView*>(bubble->contents());
// We should have the expected controls.
EXPECT_EQ(6, contents->child_count());
EXPECT_TRUE(contents->Contains(contents->icon_));
EXPECT_TRUE(contents->Contains(contents->title_));
EXPECT_TRUE(contents->Contains(contents->install_date_));
EXPECT_TRUE(contents->Contains(contents->description_));
EXPECT_TRUE(contents->Contains(contents->uninstall_link_));
EXPECT_TRUE(contents->Contains(contents->report_abuse_link_));
// These controls should be visible.
EXPECT_TRUE(contents->icon_->IsVisible());
EXPECT_TRUE(contents->title_->IsVisible());
EXPECT_TRUE(contents->install_date_->IsVisible());
EXPECT_TRUE(contents->description_->IsVisible());
EXPECT_TRUE(contents->uninstall_link_->IsVisible());
EXPECT_TRUE(contents->report_abuse_link_->IsVisible());
// Validate their layouts.
EXPECT_GT(contents->title_->x(), contents->icon_->x());
EXPECT_GT(contents->title_->width(), 0);
EXPECT_GT(contents->title_->height(), 0);
EXPECT_EQ(contents->install_date_->x(), contents->title_->x());
EXPECT_GT(contents->install_date_->y(), contents->title_->y());
EXPECT_GT(contents->install_date_->width(), 0);
EXPECT_GT(contents->install_date_->height(), 0);
EXPECT_EQ(contents->description_->x(), contents->install_date_->x());
EXPECT_GT(contents->description_->y(), contents->install_date_->y());
EXPECT_GT(contents->description_->width(), 0);
EXPECT_GT(contents->description_->height(), 0);
EXPECT_EQ(contents->uninstall_link_->x(), contents->description_->x());
EXPECT_GT(contents->uninstall_link_->y(), contents->description_->y());
EXPECT_GT(contents->uninstall_link_->width(), 0);
EXPECT_GT(contents->uninstall_link_->height(), 0);
EXPECT_GT(contents->report_abuse_link_->x(), contents->uninstall_link_->x());
EXPECT_EQ(contents->report_abuse_link_->y(), contents->uninstall_link_->y());
EXPECT_GT(contents->report_abuse_link_->width(), 0);
EXPECT_GT(contents->report_abuse_link_->height(), 0);
// Validates the texts.
base::Time install_time =
extension_service->extension_prefs()->GetInstallTime(extension->id());
string16 time_text = l10n_util::GetStringFUTF16(
IDS_ABOUT_PANEL_BUBBLE_EXTENSION_INSTALL_DATE,
base::TimeFormatFriendlyDate(
extension_service->extension_prefs()->GetInstallTime(
extension->id())));
EXPECT_STREQ(UTF16ToUTF8(time_text).c_str(),
WideToUTF8(contents->install_date_->GetText()).c_str());
EXPECT_STREQ(extension->description().c_str(),
UTF16ToUTF8(contents->description_->text()).c_str());
}
#endif
......@@ -130,6 +130,10 @@ class Bubble
virtual void AnimationEnded(const ui::Animation* animation);
virtual void AnimationProgressed(const ui::Animation* animation);
#ifdef UNIT_TEST
views::View* contents() const { return contents_; }
#endif
static const SkColor kBackgroundColor;
protected:
......
......@@ -475,6 +475,13 @@ std::string GenerateApplicationNameFromExtensionId(const std::string& id) {
return t;
}
std::string GetExtensionIdFromApplicationName(const std::string& app_name) {
std::string prefix(kCrxAppPrefix);
if (app_name.substr(0, prefix.length()) != prefix)
return std::string();
return app_name.substr(prefix.length());
}
void CreateShortcut(
const FilePath& data_dir,
const ShellIntegration::ShortcutInfo& shortcut_info,
......
......@@ -30,6 +30,9 @@ std::string GenerateApplicationNameFromURL(const GURL& url);
// Compute a deterministic name based on an extension/apps's id.
std::string GenerateApplicationNameFromExtensionId(const std::string& id);
// Extracts the extension id from the app name.
std::string GetExtensionIdFromApplicationName(const std::string& app_name);
// Callback after user dismisses CreateShortcutView. "true" indicates
// shortcut is created successfully. Otherwise, it is false.
typedef Callback1<bool>::Type CreateShortcutCallback;
......
......@@ -2843,6 +2843,8 @@
'browser/ui/omnibox/omnibox_view.h',
'browser/ui/options/options_util.cc',
'browser/ui/options/options_util.h',
'browser/ui/panels/about_panel_bubble.cc',
'browser/ui/panels/about_panel_bubble.h',
'browser/ui/panels/panel.cc',
'browser/ui/panels/panel.h',
'browser/ui/panels/panel_browser_frame_view.cc',
......@@ -3716,6 +3718,8 @@
'browser/power_save_blocker_stub.cc',
'browser/ui/browser_list_stub.cc',
'browser/ui/crypto_module_password_dialog_nss.cc',
'browser/ui/panels/about_panel_bubble.cc',
'browser/ui/panels/about_panel_bubble.h',
'browser/ui/panels/panel_browser_frame_view.cc',
'browser/ui/panels/panel_browser_frame_view.h',
'browser/ui/panels/panel_browser_view.cc',
......@@ -4296,6 +4300,8 @@
['include', '^browser/printing/print_dialog_gtk.h'],
['exclude', '^browser/bookmarks/bookmark_drop_info.cc'],
['exclude', '^browser/ui/browser_list_stub.cc'],
['exclude', '^browser/ui/panels/about_panel_bubble.cc'],
['exclude', '^browser/ui/panels/about_panel_bubble.h'],
['exclude', '^browser/ui/panels/panel_browser_frame_view.cc'],
['exclude', '^browser/ui/panels/panel_browser_frame_view.h'],
['exclude', '^browser/ui/panels/panel_browser_view.cc'],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment