15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/bundle_installer.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_view.h" 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/toolbar_view.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/bubble/bubble_delegate.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/image_button.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/image_view.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/grid_layout.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/layout_constants.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::BundleInstaller; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using views::GridLayout; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The ID of the column set for the bubble. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kColumnSetId = 0; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The width of the left column. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLeftColumnWidth = 325; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BundleInstalledBubble : public views::BubbleDelegateView, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public views::ButtonListener { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BundleInstalledBubble(const BundleInstaller* bundle, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View* anchor_view, 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) views::BubbleBorder::Arrow arrow) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : views::BubbleDelegateView(anchor_view, arrow) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout* layout = GridLayout::CreatePanel(this); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLayoutManager(layout); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) column_set->AddColumn(GridLayout::LEADING, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout::FILL, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // no resizing 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout::USE_PREF, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // no fixed with 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLeftColumnWidth); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) column_set->AddPaddingColumn(0, views::kPanelHorizMargin); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) column_set->AddColumn(GridLayout::LEADING, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout::LEADING, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // no resizing 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout::USE_PREF, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // no fixed width 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); // no min width (only holds close button) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(0, kColumnSetId); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddContent(layout, bundle); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~BundleInstalledBubble() {} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddContent(GridLayout* layout, const BundleInstaller* bundle) { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 installed_heading = bundle->GetHeadingTextFor( 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BundleInstaller::Item::STATE_INSTALLED); 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 failed_heading = bundle->GetHeadingTextFor( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BundleInstaller::Item::STATE_FAILED); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert the list of installed items. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!installed_heading.empty()) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(0, kColumnSetId); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddHeading(layout, installed_heading); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddCloseButton(layout, this); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddItemList(layout, bundle->GetItemsWithState( 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BundleInstaller::Item::STATE_INSTALLED)); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert a line of padding if we're showing both sections. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!failed_heading.empty()) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert the list of failed items. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!failed_heading.empty()) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(0, kColumnSetId); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddHeading(layout, failed_heading); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The close button should be in the second column of the first row, so 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we add it here if there was no installed items section. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installed_heading.empty()) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddCloseButton(layout, this); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddItemList(layout, bundle->GetItemsWithState( 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BundleInstaller::Item::STATE_FAILED)); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) views::BubbleDelegateView::CreateBubble(this)->Show(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddItemList(GridLayout* layout, const BundleInstaller::ItemList& items) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < items.size(); ++i) { 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 extension_name = 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(items[i].localized_name); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::AdjustStringForLocaleDirection(&extension_name); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(0, kColumnSetId); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Label* extension_label = new views::Label( 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PERMISSION_LINE, extension_name)); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_label->SetMultiLine(true); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_label->SizeToFit(kLeftColumnWidth); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(extension_label); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddCloseButton(GridLayout* layout, views::ButtonListener* listener) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::ImageButton* button = new views::ImageButton(listener); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(views::CustomButton::STATE_NORMAL, 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rb.GetImageSkiaNamed(IDR_CLOSE_2)); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(views::CustomButton::STATE_HOVERED, 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rb.GetImageSkiaNamed(IDR_CLOSE_2_H)); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(views::CustomButton::STATE_PRESSED, 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rb.GetImageSkiaNamed(IDR_CLOSE_2_P)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(button); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void AddHeading(GridLayout* layout, const base::string16& heading) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Label* heading_label = new views::Label( 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) heading, rb.GetFontList(ui::ResourceBundle::MediumFont)); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heading_label->SetMultiLine(true); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heading_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heading_label->SizeToFit(kLeftColumnWidth); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(heading_label); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views::ButtonListener implementation: 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ButtonPressed(views::Button* sender, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::Event& event) OVERRIDE { 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetWidget()->Close(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BundleInstalledBubble); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BundleInstaller::ShowInstalledBubble( 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BundleInstaller* bundle, Browser* browser) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* anchor = browser_view->GetToolbarView()->app_menu(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BundleInstalledBubble(bundle, anchor, views::BubbleBorder::TOP_RIGHT); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 159