| Index: chrome/browser/ui/views/web_intent_picker_views.cc
|
| diff --git a/chrome/browser/ui/views/web_intent_picker_views.cc b/chrome/browser/ui/views/web_intent_picker_views.cc
|
| deleted file mode 100644
|
| index a1e555e1c21cf993a0d21ad4c16249215a7db677..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/views/web_intent_picker_views.cc
|
| +++ /dev/null
|
| @@ -1,1601 +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 <algorithm>
|
| -#include <vector>
|
| -
|
| -#include "base/memory/scoped_vector.h"
|
| -#include "base/time.h"
|
| -#include "base/timer.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "chrome/browser/download/download_util.h"
|
| -#include "chrome/browser/tab_contents/tab_util.h"
|
| -#include "chrome/browser/ui/browser_finder.h"
|
| -#include "chrome/browser/ui/browser_navigator.h"
|
| -#include "chrome/browser/ui/chrome_style.h"
|
| -#include "chrome/browser/ui/intents/web_intent_inline_disposition_delegate.h"
|
| -#include "chrome/browser/ui/intents/web_intent_picker.h"
|
| -#include "chrome/browser/ui/intents/web_intent_picker_delegate.h"
|
| -#include "chrome/browser/ui/intents/web_intent_picker_model.h"
|
| -#include "chrome/browser/ui/intents/web_intent_picker_model_observer.h"
|
| -#include "chrome/browser/ui/views/constrained_window_views.h"
|
| -#include "chrome/browser/ui/views/frame/browser_view.h"
|
| -#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
|
| -#include "chrome/browser/ui/views/toolbar_view.h"
|
| -#include "chrome/common/extensions/extension_constants.h"
|
| -#include "content/public/browser/web_contents.h"
|
| -#include "content/public/browser/web_contents_view.h"
|
| -#include "grit/chromium_strings.h"
|
| -#include "grit/generated_resources.h"
|
| -#include "grit/google_chrome_strings.h"
|
| -#include "grit/theme_resources.h"
|
| -#include "grit/ui_resources.h"
|
| -#include "ipc/ipc_message.h"
|
| -#include "third_party/skia/include/core/SkColor.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/canvas.h"
|
| -#include "ui/gfx/image/image.h"
|
| -#include "ui/gfx/image/image_skia_operations.h"
|
| -#include "ui/views/border.h"
|
| -#include "ui/views/controls/button/image_button.h"
|
| -#include "ui/views/controls/button/text_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/controls/separator.h"
|
| -#include "ui/views/controls/throbber.h"
|
| -#include "ui/views/controls/webview/webview.h"
|
| -#include "ui/views/layout/box_layout.h"
|
| -#include "ui/views/layout/fill_layout.h"
|
| -#include "ui/views/layout/grid_layout.h"
|
| -#include "ui/views/layout/layout_constants.h"
|
| -#include "ui/views/view.h"
|
| -#include "ui/views/widget/widget.h"
|
| -#include "ui/views/window/dialog_delegate.h"
|
| -#include "ui/views/window/non_client_view.h"
|
| -
|
| -using content::WebContents;
|
| -using views::GridLayout;
|
| -
|
| -namespace {
|
| -
|
| -// The color used to dim disabled elements.
|
| -const SkColor kHalfOpacityWhite = SkColorSetARGB(128, 255, 255, 255);
|
| -
|
| -// The color used to display an enabled label.
|
| -const SkColor kEnabledLabelColor = SkColorSetRGB(51, 51, 51);
|
| -
|
| -// The color used to display an enabled link.
|
| -const SkColor kEnabledLinkColor = SkColorSetRGB(17, 85, 204);
|
| -
|
| -// The color used to display a disabled link.
|
| -const SkColor kDisabledLinkColor = SkColorSetRGB(128, 128, 128);
|
| -
|
| -// The time between successive throbber frames in milliseconds.
|
| -const int kThrobberFrameTimeMs = 50;
|
| -
|
| -// Width of IntentView action button in pixels
|
| -const int kButtonWidth = 130;
|
| -
|
| -// Minimum number of action buttons - fill up with suggestions as needed.
|
| -const int kMinRowCount = 4;
|
| -
|
| -// Maximum number of action buttons - do not add suggestions to reach.
|
| -const int kMaxRowCount = 8;
|
| -
|
| -// The vertical padding around the UI elements in the waiting view.
|
| -const int kWaitingViewVerticalPadding = 40;
|
| -
|
| -// Enables or disables all child views of |view|.
|
| -void EnableChildViews(views::View* view, bool enabled) {
|
| - for (int i = 0; i < view->child_count(); ++i) {
|
| - views::View* child = view->child_at(i);
|
| - child->SetEnabled(enabled);
|
| - }
|
| -}
|
| -
|
| -// Create a "close" button.
|
| -views::ImageButton* CreateCloseButton(views::ButtonListener* listener) {
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - views::ImageButton* close_button = new views::ImageButton(listener);
|
| - close_button->SetImage(views::CustomButton::STATE_NORMAL,
|
| - rb.GetImageSkiaNamed(IDR_CLOSE_DIALOG));
|
| - close_button->SetImage(views::CustomButton::STATE_HOVERED,
|
| - rb.GetImageSkiaNamed(IDR_CLOSE_DIALOG_H));
|
| - close_button->SetImage(views::CustomButton::STATE_PRESSED,
|
| - rb.GetImageSkiaNamed(IDR_CLOSE_DIALOG_P));
|
| - return close_button;
|
| -}
|
| -
|
| -// Creates a label.
|
| -views::Label* CreateLabel() {
|
| - views::Label* label = new views::Label();
|
| - label->SetEnabledColor(kEnabledLabelColor);
|
| - label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| - return label;
|
| -}
|
| -
|
| -// Creates a title-style label.
|
| -views::Label* CreateTitleLabel() {
|
| - views::Label* label = CreateLabel();
|
| - label->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
|
| - ui::ResourceBundle::MediumFont));
|
| - const int kLabelBuiltinTopPadding = 5;
|
| - label->set_border(views::Border::CreateEmptyBorder(
|
| - WebIntentPicker::kContentAreaBorder -
|
| - chrome_style::kCloseButtonPadding -
|
| - kLabelBuiltinTopPadding,
|
| - 0, 0, 0));
|
| - return label;
|
| -}
|
| -
|
| -// Creates a link.
|
| -views::Link* CreateLink() {
|
| - views::Link* link = new views::Link();
|
| - link->SetEnabledColor(kEnabledLinkColor);
|
| - link->SetDisabledColor(kDisabledLinkColor);
|
| - link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| - return link;
|
| -}
|
| -
|
| -// Creates a header for the inline disposition dialog.
|
| -views::View* CreateInlineDispositionHeader(
|
| - views::ImageView* app_icon,
|
| - views::Label* app_title,
|
| - views::Link* use_another_service_link) {
|
| - views::View* header = new views::View();
|
| - views::GridLayout* grid_layout = new views::GridLayout(header);
|
| - const int kIconBuiltinTopPadding = 6;
|
| - grid_layout->SetInsets(
|
| - WebIntentPicker::kContentAreaBorder -
|
| - chrome_style::kCloseButtonPadding -
|
| - kIconBuiltinTopPadding,
|
| - 0, 0, 0);
|
| - header->SetLayoutManager(grid_layout);
|
| - views::ColumnSet* header_cs = grid_layout->AddColumnSet(0);
|
| - header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // App icon.
|
| - header_cs->AddPaddingColumn(0, WebIntentPicker::kIconTextPadding);
|
| - header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // App title.
|
| - header_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
|
| - header_cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Use another app link.
|
| - grid_layout->StartRow(0, 0);
|
| - grid_layout->AddView(app_icon);
|
| - grid_layout->AddView(app_title);
|
| - grid_layout->AddView(use_another_service_link);
|
| - header->Layout();
|
| - return header;
|
| -}
|
| -
|
| -// Checks whether the inline disposition dialog should show the link for using
|
| -// another service.
|
| -bool IsUseAnotherServiceVisible(WebIntentPickerModel* model) {
|
| - DCHECK(model);
|
| - return model->show_use_another_service() &&
|
| - (model->GetInstalledServiceCount() > 1 ||
|
| - model->GetSuggestedExtensionCount());
|
| -}
|
| -
|
| -
|
| -// StarsView -------------------------------------------------------------------
|
| -
|
| -// A view that displays 5 stars: empty, full or half full, given a rating in
|
| -// the range [0,5].
|
| -class StarsView : public views::View {
|
| - public:
|
| - explicit StarsView(double rating);
|
| - virtual ~StarsView();
|
| -
|
| - private:
|
| - // The star rating to display, in the range [0,5].
|
| - double rating_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(StarsView);
|
| -};
|
| -
|
| -StarsView::StarsView(double rating)
|
| - : rating_(rating) {
|
| - const int kSpacing = 1; // Spacing between stars in pixels.
|
| -
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - SetLayoutManager(
|
| - new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, kSpacing));
|
| -
|
| - for (int i = 0; i < 5; ++i) {
|
| - views::ImageView* image = new views::ImageView();
|
| - image->SetImage(rb.GetImageSkiaNamed(
|
| - WebIntentPicker::GetNthStarImageIdFromCWSRating(rating, i)));
|
| - AddChildView(image);
|
| - }
|
| -
|
| - // TODO(binji): Add tooltip with text rating
|
| - // "Average Rating: X.XX stars (YYYYY)"
|
| - // Y = "1: Hated it, 2: Disliked it, 3: It was okay, 4: Liked it,
|
| - // 5: Loved it"
|
| - // Choose Y based on rounded X.
|
| -}
|
| -
|
| -StarsView::~StarsView() {
|
| -}
|
| -
|
| -
|
| -// ThrobberNativeTextButton ----------------------------------------------------
|
| -
|
| -// A native text button that can display a throbber in place of its icon. Much
|
| -// of the logic of this class is copied from ui/views/controls/throbber.h.
|
| -class ThrobberNativeTextButton : public views::NativeTextButton {
|
| - public:
|
| - ThrobberNativeTextButton(views::ButtonListener* listener,
|
| - const string16& text);
|
| - virtual ~ThrobberNativeTextButton();
|
| -
|
| - // Start or stop the throbber.
|
| - void StartThrobber();
|
| - void StopThrobber();
|
| -
|
| - // Set the throbber bitmap to use. IDR_THROBBER is used by default.
|
| - void SetFrames(const gfx::ImageSkia* frames);
|
| -
|
| - // Provide a preferred size, accomodating buttons wider than their text.
|
| - virtual gfx::Size GetPreferredSize() OVERRIDE;
|
| -
|
| - // Set the width desired for this button.
|
| - void set_preferred_width(int width) { preferred_width_ = width; }
|
| -
|
| - protected:
|
| - virtual const gfx::ImageSkia& GetImageToPaint() const OVERRIDE;
|
| -
|
| - private:
|
| - // The timer callback to schedule painting this view.
|
| - void Run();
|
| -
|
| - // Image that contains the throbber frames.
|
| - const gfx::ImageSkia* frames_;
|
| -
|
| - // The currently displayed frame, given to GetImageToPaint.
|
| - mutable gfx::ImageSkia this_frame_;
|
| -
|
| - // How long one frame is displayed.
|
| - base::TimeDelta frame_time_;
|
| -
|
| - // Used to schedule Run calls.
|
| - base::RepeatingTimer<ThrobberNativeTextButton> timer_;
|
| -
|
| - // How many frames we have.
|
| - int frame_count_;
|
| -
|
| - // Time when StartThrobber was called.
|
| - base::TimeTicks start_time_;
|
| -
|
| - // Whether the throbber is shown an animating.
|
| - bool running_;
|
| -
|
| - // The width this button should assume.
|
| - int preferred_width_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ThrobberNativeTextButton);
|
| -};
|
| -
|
| -ThrobberNativeTextButton::ThrobberNativeTextButton(
|
| - views::ButtonListener* listener, const string16& text)
|
| - : NativeTextButton(listener, text),
|
| - frame_time_(base::TimeDelta::FromMilliseconds(kThrobberFrameTimeMs)),
|
| - frame_count_(0),
|
| - running_(false),
|
| - preferred_width_(0) {
|
| - SetFrames(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
|
| - IDR_THROBBER).ToImageSkia());
|
| -}
|
| -
|
| -ThrobberNativeTextButton::~ThrobberNativeTextButton() {
|
| - StopThrobber();
|
| -}
|
| -
|
| -void ThrobberNativeTextButton::StartThrobber() {
|
| - if (running_)
|
| - return;
|
| -
|
| - start_time_ = base::TimeTicks::Now();
|
| - timer_.Start(FROM_HERE, frame_time_, this, &ThrobberNativeTextButton::Run);
|
| - running_ = true;
|
| -
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void ThrobberNativeTextButton::StopThrobber() {
|
| - if (!running_)
|
| - return;
|
| -
|
| - timer_.Stop();
|
| - running_ = false;
|
| -}
|
| -
|
| -void ThrobberNativeTextButton::SetFrames(const gfx::ImageSkia* frames) {
|
| - frames_ = frames;
|
| - DCHECK(frames_->width() > 0 && frames_->height() > 0);
|
| - DCHECK(frames_->width() % frames_->height() == 0);
|
| - frame_count_ = frames_->width() / frames_->height();
|
| - PreferredSizeChanged();
|
| -}
|
| -
|
| -gfx::Size ThrobberNativeTextButton::GetPreferredSize() {
|
| - gfx::Size size = NativeTextButton::GetPreferredSize();
|
| - if (preferred_width_)
|
| - size.set_width(preferred_width_);
|
| - return size;
|
| -}
|
| -
|
| -const gfx::ImageSkia& ThrobberNativeTextButton::GetImageToPaint() const {
|
| - if (!running_)
|
| - return NativeTextButton::GetImageToPaint();
|
| -
|
| - const base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time_;
|
| - const int current_frame =
|
| - static_cast<int>(elapsed_time / frame_time_) % frame_count_;
|
| - const int image_size = frames_->height();
|
| - const int image_offset = current_frame * image_size;
|
| -
|
| - gfx::Rect subset_rect(image_offset, 0, image_size, image_size);
|
| - this_frame_ = gfx::ImageSkiaOperations::ExtractSubset(*frames_, subset_rect);
|
| - return this_frame_;
|
| -}
|
| -
|
| -void ThrobberNativeTextButton::Run() {
|
| - DCHECK(running_);
|
| -
|
| - SchedulePaint();
|
| -}
|
| -
|
| -
|
| -// SpinnerProgressIndicator ----------------------------------------------------
|
| -class SpinnerProgressIndicator : public views::View {
|
| - public:
|
| - SpinnerProgressIndicator();
|
| - virtual ~SpinnerProgressIndicator();
|
| -
|
| - void SetPercentDone(int percent);
|
| - void SetIndeterminate(bool indetereminate);
|
| -
|
| - // Overridden from views::View.
|
| - virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
|
| - virtual gfx::Size GetPreferredSize() OVERRIDE;
|
| -
|
| - private:
|
| - void UpdateTimer();
|
| - int GetProgressAngle();
|
| -
|
| - static const int kTimerIntervalMs = 1000 / 30;
|
| - static const int kSpinRateDegreesPerSecond = 270;
|
| -
|
| - int percent_done_;
|
| - int indeterminate_;
|
| -
|
| - base::TimeTicks start_time_;
|
| - base::RepeatingTimer<SpinnerProgressIndicator> timer_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(SpinnerProgressIndicator);
|
| -};
|
| -
|
| -SpinnerProgressIndicator::SpinnerProgressIndicator()
|
| - : percent_done_(0),
|
| - indeterminate_(true) {}
|
| -
|
| -SpinnerProgressIndicator::~SpinnerProgressIndicator() {
|
| -}
|
| -
|
| -void SpinnerProgressIndicator::SetPercentDone(int percent) {
|
| - percent_done_ = percent;
|
| - SchedulePaint();
|
| - UpdateTimer();
|
| -}
|
| -
|
| -void SpinnerProgressIndicator::SetIndeterminate(bool indetereminate) {
|
| - indeterminate_ = indetereminate;
|
| - SchedulePaint();
|
| - UpdateTimer();
|
| -}
|
| -
|
| -void SpinnerProgressIndicator::Paint(gfx::Canvas* canvas) {
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - gfx::ImageSkia* fg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_FOREGROUND);
|
| - gfx::ImageSkia* bg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_BACKGROUND);
|
| - download_util::PaintCustomDownloadProgress(
|
| - canvas,
|
| - *bg,
|
| - *fg,
|
| - fg->width(),
|
| - bounds(),
|
| - GetProgressAngle(),
|
| - indeterminate_ ? -1 : percent_done_);
|
| -}
|
| -
|
| -gfx::Size SpinnerProgressIndicator::GetPreferredSize() {
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - gfx::ImageSkia* fg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_FOREGROUND);
|
| - return fg->size();
|
| -}
|
| -
|
| -void SpinnerProgressIndicator::UpdateTimer() {
|
| - if (!parent() || !indeterminate_) {
|
| - timer_.Stop();
|
| - return;
|
| - }
|
| -
|
| - if (!timer_.IsRunning()) {
|
| - start_time_ = base::TimeTicks::Now();
|
| - timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTimerIntervalMs),
|
| - this, &SpinnerProgressIndicator::SchedulePaint);
|
| - }
|
| -}
|
| -
|
| -int SpinnerProgressIndicator::GetProgressAngle() {
|
| - if (!indeterminate_)
|
| - return download_util::kStartAngleDegrees;
|
| - base::TimeDelta delta = base::TimeTicks::Now() - start_time_;
|
| - int angle = delta.InSecondsF() * kSpinRateDegreesPerSecond;
|
| - return angle % 360;
|
| -}
|
| -
|
| -
|
| -// WaitingView ----------------------------------------------------------
|
| -class WaitingView : public views::View {
|
| - public:
|
| - WaitingView(views::ButtonListener* listener, bool use_close_button);
|
| - virtual ~WaitingView();
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(WaitingView);
|
| -};
|
| -
|
| -WaitingView::WaitingView(views::ButtonListener* listener,
|
| - bool use_close_button) {
|
| - views::GridLayout* layout = new views::GridLayout(this);
|
| - layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
|
| - const int kMessageBuiltinBottomPadding = 3;
|
| - layout->SetInsets(chrome_style::kCloseButtonPadding,
|
| - 0,
|
| - kWaitingViewVerticalPadding - kMessageBuiltinBottomPadding,
|
| - 0);
|
| - SetLayoutManager(layout);
|
| -
|
| - enum GridLayoutColumnSets {
|
| - HEADER_ROW,
|
| - CONTENT_ROW,
|
| - };
|
| - views::ColumnSet* header_cs = layout->AddColumnSet(HEADER_ROW);
|
| - header_cs->AddPaddingColumn(1, 1);
|
| - header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
|
| - GridLayout::USE_PREF, 0, 0);
|
| - header_cs->AddPaddingColumn(
|
| - 0, chrome_style::kCloseButtonPadding);
|
| -
|
| - views::ColumnSet* content_cs = layout->AddColumnSet(CONTENT_ROW);
|
| - content_cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
|
| - content_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0);
|
| - content_cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
|
| -
|
| - // Close button
|
| - layout->StartRow(0, HEADER_ROW);
|
| - views::ImageButton* close_button = CreateCloseButton(listener);
|
| - layout->AddView(close_button);
|
| - close_button->SetVisible(use_close_button);
|
| -
|
| - // Throbber
|
| - layout->AddPaddingRow(0,
|
| - kWaitingViewVerticalPadding -
|
| - chrome_style::kCloseButtonPadding -
|
| - close_button->GetPreferredSize().height());
|
| - layout->StartRow(0, CONTENT_ROW);
|
| - SpinnerProgressIndicator* throbber = new SpinnerProgressIndicator();
|
| - layout->AddView(throbber);
|
| -
|
| - // Message
|
| - const int kMessageBuiltinTopPadding = 5;
|
| - layout->AddPaddingRow(0,
|
| - chrome_style::kRowPadding -
|
| - kMessageBuiltinTopPadding);
|
| - layout->StartRow(0, CONTENT_ROW);
|
| - views::Label* label = CreateLabel();
|
| - label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
|
| - label->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_WAIT_FOR_CWS));
|
| - layout->AddView(label);
|
| -
|
| - // Start the throbber.
|
| - throbber->SetIndeterminate(true);
|
| -}
|
| -
|
| -WaitingView::~WaitingView() {
|
| -}
|
| -
|
| -
|
| -// IntentRowView --------------------------------------------------
|
| -
|
| -// A view for each row in the IntentsView. It displays information
|
| -// for both installed and suggested intent handlers.
|
| -class IntentRowView : public views::View,
|
| - public views::ButtonListener,
|
| - public views::LinkListener {
|
| - public:
|
| - enum ActionType {
|
| - ACTION_UNKNOWN,
|
| - ACTION_INSTALL,
|
| - ACTION_INVOKE
|
| - };
|
| -
|
| - class Delegate {
|
| - public:
|
| - // Called when the user clicks the "Add to Chrome" button.
|
| - virtual void OnExtensionInstallClicked(const std::string& extension_id) = 0;
|
| -
|
| - // Called when the user clicks the extension title link.
|
| - virtual void OnExtensionLinkClicked(
|
| - const std::string& extension_id,
|
| - WindowOpenDisposition disposition) = 0;
|
| -
|
| - // Called when the action button is clicked. |type| indicates the requested
|
| - // kind of action, and |tag| identifies the service or extension to
|
| - // operate on.
|
| - virtual void OnActionButtonClicked(ActionType type, size_t tag) = 0;
|
| -
|
| - protected:
|
| - virtual ~Delegate() {}
|
| - };
|
| -
|
| - virtual ~IntentRowView();
|
| -
|
| - // Creates a new view for |service| or |extension| depending on which
|
| - // value is not NULL.
|
| - static IntentRowView* CreateHandlerRow(
|
| - const WebIntentPickerModel::InstalledService* service,
|
| - const WebIntentPickerModel::SuggestedExtension* extension,
|
| - int tag,
|
| - IntentRowView::Delegate* delegate,
|
| - int preferred_width);
|
| -
|
| - // ButtonListener implementation.
|
| - virtual void ButtonPressed(views::Button* sender,
|
| - const ui::Event& event) OVERRIDE;
|
| -
|
| - // LinkListener implementation.
|
| - virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
|
| -
|
| - // Start an animating throbber for this row, and hide the star rating and the
|
| - // install button.
|
| - void StartThrobber();
|
| -
|
| - void MarkBusy(const std::string& extension_id);
|
| -
|
| - // Stop the throbber for this row, and show the star rating and the install
|
| - // button.
|
| - void StopThrobber();
|
| -
|
| - protected:
|
| - virtual void OnEnabledChanged() OVERRIDE;
|
| -
|
| - virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
|
| -
|
| - private:
|
| - IntentRowView(ActionType type, size_t tag);
|
| -
|
| - // Gets the proper message string associated with |type_|.
|
| - string16 GetActionButtonMessage();
|
| -
|
| - // Identifier for the suggested extension displayed in this row.
|
| - std::string extension_id_;
|
| -
|
| - // A delegate to respond to button presses and clicked links.
|
| - Delegate* delegate_;
|
| -
|
| - // The icon of the extension.
|
| - views::ImageView* icon_;
|
| -
|
| - // The title of the extension, which links to the CWS detailed description of
|
| - // this extension.
|
| - views::View* title_link_;
|
| -
|
| - // The star rating of this extension.
|
| - StarsView* stars_;
|
| -
|
| - // A button to install the extension.
|
| - ThrobberNativeTextButton* install_button_;
|
| -
|
| - // The type of action that is invoked from the row's button.
|
| - ActionType type_;
|
| -
|
| - // A tag identifying the data associated with this row. For both installed
|
| - // and suggested services, this is an index into the respective collections
|
| - // on the WebIntentPickerModel.
|
| - size_t tag_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(IntentRowView);
|
| -};
|
| -
|
| -IntentRowView::IntentRowView(ActionType type, size_t tag)
|
| - : delegate_(NULL),
|
| - icon_(NULL),
|
| - title_link_(NULL),
|
| - stars_(NULL),
|
| - install_button_(NULL),
|
| - type_(type),
|
| - tag_(tag) {}
|
| -
|
| -IntentRowView* IntentRowView::CreateHandlerRow(
|
| - const WebIntentPickerModel::InstalledService* service,
|
| - const WebIntentPickerModel::SuggestedExtension* extension,
|
| - int tag,
|
| - IntentRowView::Delegate* delegate,
|
| - int preferred_width) {
|
| -
|
| - // one or the other must be set...exclusively
|
| - DCHECK((service != NULL || extension != NULL) &&
|
| - (service == NULL || extension == NULL));
|
| -
|
| -
|
| - const string16& title = (service != NULL)
|
| - ? service->title : extension->title;
|
| -
|
| - // TODO(groby): Once links are properly sized (see SuggestionRowViewLayout
|
| - // refactor notes), can simply SetElideBehavior(views::Label::ELIDE_AT_END).
|
| - // Note: Verify that views links do not treat empty space at the end as
|
| - // part of the link, if this change happens.
|
| - string16 elided_title = ui::ElideText(title, gfx::Font(),
|
| - WebIntentPicker::kTitleLinkMaxWidth,
|
| - ui::ELIDE_AT_END);
|
| -
|
| - const gfx::ImageSkia* icon = NULL;
|
| - StarsView* stars = NULL;
|
| - views::Label* label = NULL;
|
| - IntentRowView* view;
|
| - if (service != NULL) {
|
| - view = new IntentRowView(ACTION_INVOKE, tag);
|
| - icon = service->favicon.ToImageSkia();
|
| - label = CreateLabel();
|
| - label->SetText(elided_title);
|
| - } else {
|
| - view = new IntentRowView(ACTION_INSTALL, tag);
|
| - view->extension_id_ = extension->id;
|
| - icon = extension->icon.ToImageSkia();
|
| - views::Link* link = CreateLink();
|
| - link->SetText(elided_title);
|
| - link->set_listener(view);
|
| - label = link;
|
| - stars = new StarsView(extension->average_rating);
|
| - }
|
| -
|
| - view->delegate_ = delegate;
|
| -
|
| - views::GridLayout* grid_layout = new views::GridLayout(view);
|
| - view->SetLayoutManager(grid_layout);
|
| -
|
| - views::ColumnSet* columns = grid_layout->AddColumnSet(0);
|
| - columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Icon.
|
| - columns->AddPaddingColumn(0, WebIntentPicker::kIconTextPadding);
|
| - columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
|
| - GridLayout::FIXED, WebIntentPicker::kTitleLinkMaxWidth, 0);
|
| - const int kStarRatingHorizontalSpacing = 20;
|
| - columns->AddPaddingColumn(0, kStarRatingHorizontalSpacing);
|
| - if (stars != NULL) {
|
| - columns->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Star rating.
|
| - columns->AddPaddingColumn(0, kStarRatingHorizontalSpacing);
|
| - }
|
| - columns->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
|
| - GridLayout::FIXED, preferred_width, 0); // Button.
|
| -
|
| - grid_layout->StartRow(0, 0);
|
| -
|
| - view->icon_ = new views::ImageView();
|
| - view->icon_->SetImage(icon);
|
| - grid_layout->AddView(view->icon_);
|
| -
|
| - view->title_link_ = label;
|
| - grid_layout->AddView(view->title_link_);
|
| -
|
| - if (stars != NULL) {
|
| - view->stars_ = stars;
|
| - grid_layout->AddView(view->stars_);
|
| - }
|
| -
|
| - view->install_button_ = new ThrobberNativeTextButton(
|
| - view, view->GetActionButtonMessage());
|
| - view->install_button_->set_preferred_width(preferred_width);
|
| - grid_layout->AddView(view->install_button_);
|
| -
|
| - return view;
|
| -}
|
| -
|
| -IntentRowView::~IntentRowView() {}
|
| -
|
| -void IntentRowView::ButtonPressed(views::Button* sender,
|
| - const ui::Event& event) {
|
| - if (type_ == ACTION_INSTALL)
|
| - delegate_->OnExtensionInstallClicked(extension_id_);
|
| - else
|
| - delegate_->OnActionButtonClicked(type_, tag_);
|
| -}
|
| -
|
| -void IntentRowView::LinkClicked(views::Link* source,
|
| - int event_flags) {
|
| - delegate_->OnExtensionLinkClicked(
|
| - extension_id_, ui::DispositionFromEventFlags(event_flags));
|
| -}
|
| -
|
| -void IntentRowView::MarkBusy(const std::string& extension_id) {
|
| - SetEnabled(false);
|
| - if (extension_id == extension_id_)
|
| - StartThrobber();
|
| -}
|
| -
|
| -void IntentRowView::StartThrobber() {
|
| - install_button_->StartThrobber();
|
| - install_button_->SetText(string16());
|
| -}
|
| -
|
| -void IntentRowView::StopThrobber() {
|
| - install_button_->StopThrobber();
|
| - install_button_->SetText(GetActionButtonMessage());
|
| -}
|
| -
|
| -void IntentRowView::OnEnabledChanged() {
|
| - title_link_->SetEnabled(enabled());
|
| - if (stars_)
|
| - stars_->SetEnabled(enabled());
|
| - install_button_->SetEnabled(enabled());
|
| - View::OnEnabledChanged();
|
| - Layout();
|
| -}
|
| -
|
| -void IntentRowView::PaintChildren(gfx::Canvas* canvas) {
|
| - View::PaintChildren(canvas);
|
| - if (!enabled())
|
| - canvas->FillRect(GetLocalBounds(), kHalfOpacityWhite);
|
| -}
|
| -
|
| -string16 IntentRowView::GetActionButtonMessage() {
|
| - int message_id = 0;
|
| -
|
| - if (type_ == ACTION_INVOKE)
|
| - message_id = IDS_INTENT_PICKER_SELECT_INTENT;
|
| - else if (type_ == ACTION_INSTALL)
|
| - message_id = IDS_INTENT_PICKER_INSTALL_EXTENSION;
|
| - else
|
| - NOTREACHED();
|
| -
|
| - return l10n_util::GetStringUTF16(message_id);
|
| -}
|
| -
|
| -
|
| -// IntentsView -----------------------------------------------------
|
| -
|
| -// A view that contains both installed services and suggested extensions
|
| -// from the Chrome Web Store that provide an intent service matching the
|
| -// action/type pair.
|
| -class IntentsView : public views::View {
|
| - public:
|
| - IntentsView(const WebIntentPickerModel* model,
|
| - IntentRowView::Delegate* delegate);
|
| -
|
| - virtual ~IntentsView();
|
| -
|
| - // Update the view to the new model data.
|
| - void Update();
|
| -
|
| - // Show the install throbber for the row containing |extension_id|. This
|
| - // function also hides hides and disables other buttons and links.
|
| - void StartThrobber(const std::string& extension_id);
|
| -
|
| - // Hide the install throbber. This function re-enables all buttons and links.
|
| - void StopThrobber();
|
| -
|
| - // Adjusts a given width to account for language-specific strings.
|
| - int AdjustWidth(int old_width);
|
| -
|
| - protected:
|
| - virtual void OnEnabledChanged() OVERRIDE;
|
| -
|
| - private:
|
| - const WebIntentPickerModel* model_;
|
| - IntentRowView::Delegate* delegate_;
|
| -
|
| - // Width for the action button, adjusted to be wide enough for all possible
|
| - // strings.
|
| - int button_width_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(IntentsView);
|
| -};
|
| -
|
| -IntentsView::IntentsView(
|
| - const WebIntentPickerModel* model,
|
| - IntentRowView::Delegate* delegate)
|
| - : model_(model),
|
| - delegate_(delegate),
|
| - button_width_(0){
|
| - Update();
|
| -}
|
| -
|
| -IntentsView::~IntentsView() {
|
| -}
|
| -
|
| -void IntentsView::Update() {
|
| - RemoveAllChildViews(true);
|
| -
|
| - ThrobberNativeTextButton size_helper(
|
| - NULL, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_INSTALL_EXTENSION));
|
| - size_helper.SetText(
|
| - l10n_util::GetStringUTF16(IDS_INTENT_PICKER_SELECT_INTENT));
|
| - button_width_ = std::max(
|
| - kButtonWidth, size_helper.GetPreferredSize().width());
|
| -
|
| - const int kAppRowVerticalSpacing = 10;
|
| - views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical,
|
| - 0, 0, kAppRowVerticalSpacing);
|
| - SetLayoutManager(layout);
|
| -
|
| - int available_rows = kMaxRowCount;
|
| -
|
| - for (size_t i = 0;
|
| - available_rows > 0 && i < model_->GetInstalledServiceCount();
|
| - ++i, --available_rows) {
|
| - const WebIntentPickerModel::InstalledService& service =
|
| - model_->GetInstalledServiceAt(i);
|
| - AddChildView(IntentRowView::CreateHandlerRow(&service, NULL, i,
|
| - delegate_, button_width_));
|
| - }
|
| -
|
| - // Only fill up with suggestions if we filled less than kMinRowCount rows.
|
| - available_rows -= (kMaxRowCount - kMinRowCount);
|
| -
|
| - for (size_t i = 0;
|
| - available_rows > 0 && i < model_->GetSuggestedExtensionCount();
|
| - ++i, --available_rows) {
|
| - const WebIntentPickerModel::SuggestedExtension& extension =
|
| - model_->GetSuggestedExtensionAt(i);
|
| - AddChildView(IntentRowView::CreateHandlerRow(NULL, &extension, i,
|
| - delegate_, button_width_));
|
| - }
|
| -}
|
| -
|
| -void IntentsView::StartThrobber(const std::string& extension_id) {
|
| - for (int i = 0; i < child_count(); ++i)
|
| - static_cast<IntentRowView*>(child_at(i))->MarkBusy(extension_id);
|
| -}
|
| -
|
| -void IntentsView::StopThrobber() {
|
| - for (int i = 0; i < child_count(); ++i) {
|
| - IntentRowView* row =
|
| - static_cast<IntentRowView*>(child_at(i));
|
| - row->SetEnabled(true);
|
| - row->StopThrobber();
|
| - }
|
| -}
|
| -
|
| -int IntentsView::AdjustWidth(int old_width) {
|
| - return old_width - kButtonWidth + button_width_;
|
| -}
|
| -
|
| -void IntentsView::OnEnabledChanged() {
|
| - EnableChildViews(this, enabled());
|
| - View::OnEnabledChanged();
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -
|
| -// WebIntentPickerViews --------------------------------------------------------
|
| -
|
| -// Views implementation of WebIntentPicker.
|
| -class WebIntentPickerViews : public views::ButtonListener,
|
| - public views::WidgetDelegate,
|
| - public views::LinkListener,
|
| - public WebIntentPicker,
|
| - public WebIntentPickerModelObserver,
|
| - public IntentRowView::Delegate {
|
| - public:
|
| - WebIntentPickerViews(WebContents* web_contents,
|
| - WebIntentPickerDelegate* delegate,
|
| - WebIntentPickerModel* model);
|
| - virtual ~WebIntentPickerViews();
|
| -
|
| - // views::ButtonListener implementation.
|
| - // This method is called when the user cancels the picker dialog.
|
| - virtual void ButtonPressed(views::Button* sender,
|
| - const ui::Event& event) OVERRIDE;
|
| -
|
| - // views::WidgetDelegate implementation.
|
| - virtual void WindowClosing() OVERRIDE;
|
| - virtual void DeleteDelegate() OVERRIDE;
|
| - virtual views::Widget* GetWidget() OVERRIDE;
|
| - virtual const views::Widget* GetWidget() const OVERRIDE;
|
| - virtual views::View* GetContentsView() OVERRIDE;
|
| -
|
| - // LinkListener implementation.
|
| - virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
|
| -
|
| - // WebIntentPicker implementation.
|
| - virtual void Close() OVERRIDE;
|
| - virtual void SetActionString(const string16& action) OVERRIDE;
|
| - virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
|
| - virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE;
|
| - virtual void OnInlineDispositionAutoResize(const gfx::Size& size) OVERRIDE;
|
| - virtual void OnPendingAsyncCompleted() OVERRIDE;
|
| - virtual void InvalidateDelegate() OVERRIDE;
|
| - virtual void OnInlineDispositionWebContentsLoaded(
|
| - content::WebContents* web_contents) OVERRIDE;
|
| -
|
| - // WebIntentPickerModelObserver implementation.
|
| - virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE;
|
| - virtual void OnFaviconChanged(WebIntentPickerModel* model,
|
| - size_t index) OVERRIDE;
|
| - virtual void OnExtensionIconChanged(WebIntentPickerModel* model,
|
| - const std::string& extension_id) OVERRIDE;
|
| - virtual void OnInlineDisposition(const string16& title,
|
| - const GURL& url) OVERRIDE;
|
| -
|
| - // SuggestedExtensionsRowView::Delegate implementation.
|
| - virtual void OnExtensionInstallClicked(
|
| - const std::string& extension_id) OVERRIDE;
|
| - virtual void OnExtensionLinkClicked(
|
| - const std::string& extension_id,
|
| - WindowOpenDisposition disposition) OVERRIDE;
|
| - virtual void OnActionButtonClicked(
|
| - IntentRowView::ActionType type,
|
| - size_t tag) OVERRIDE;
|
| -
|
| - private:
|
| - enum WebIntentPickerViewsState {
|
| - INITIAL,
|
| - WAITING,
|
| - NO_SERVICES,
|
| - LIST_SERVICES,
|
| - INLINE_SERVICE,
|
| - } state_;
|
| -
|
| - // Update picker contents to reflect the current state of the model.
|
| - void UpdateContents();
|
| -
|
| - // Shows a spinner and notifies the user that we are waiting for information
|
| - // from the Chrome Web Store.
|
| - void ShowWaitingForSuggestions();
|
| -
|
| - // Updates the dialog with the list of available services, suggestions,
|
| - // and a nice link to CWS to find more suggestions. This is the "Main"
|
| - // view of the picker.
|
| - void ShowAvailableServices();
|
| -
|
| - // Informs the user that there are no services available to handle
|
| - // the intent, and that there are no suggestions from the Chrome Web Store.
|
| - void ShowNoServicesMessage();
|
| -
|
| - // Restore the contents of the picker to the initial contents.
|
| - void ResetContents();
|
| -
|
| - // Resize the constrained window to the size of its contents.
|
| - void SizeToContents();
|
| -
|
| - // Clear the contents of the picker.
|
| - void ClearContents();
|
| -
|
| - // Returns the service selection question text used in the title
|
| - // of the picker.
|
| - const string16 GetActionTitle();
|
| -
|
| - // Refresh the icon for the inline disposition service that is being
|
| - // displayed.
|
| - void RefreshInlineServiceIcon();
|
| -
|
| - // Refresh the extensions control in the picker.
|
| - void RefreshExtensions();
|
| -
|
| - // A weak pointer to the WebIntentPickerDelegate to notify when the user
|
| - // chooses a service or cancels.
|
| - WebIntentPickerDelegate* delegate_;
|
| -
|
| - // A weak pointer to the picker model.
|
| - WebIntentPickerModel* model_;
|
| -
|
| - // A weak pointer to the action string label.
|
| - // Created locally, owned by Views.
|
| - views::Label* action_label_;
|
| -
|
| - // A weak pointer to the intents view.
|
| - // Created locally, owned by Views view hierarchy.
|
| - IntentsView* extensions_;
|
| -
|
| - // Delegate for inline disposition tab contents.
|
| - scoped_ptr<WebIntentInlineDispositionDelegate> inline_disposition_delegate_;
|
| -
|
| - // A weak pointer to the WebContents this picker is in.
|
| - WebContents* web_contents_;
|
| -
|
| - // A weak pointer to the WebView that hosts the WebContents being displayed.
|
| - // Created locally, owned by Views.
|
| - views::WebView* webview_;
|
| -
|
| - // A weak pointer to the view that contains all other views in the picker.
|
| - // Created locally, owned by Views.
|
| - views::View* contents_;
|
| -
|
| - // A weak pointer to the constrained window.
|
| - // Created locally, owned by Views.
|
| - ConstrainedWindowViews* window_;
|
| -
|
| - // A weak pointer to the more suggestions link.
|
| - // Created locally, owned by Views.
|
| - views::Link* more_suggestions_link_;
|
| -
|
| - // The icon for the inline disposition service.
|
| - views::ImageView* inline_service_icon_;
|
| -
|
| - // A weak pointer to the choose another service link.
|
| - // Created locally, owned by Views.
|
| - views::Link* choose_another_service_link_;
|
| -
|
| - // Weak pointer to "Waiting for CWS" display. Owned by parent view.
|
| - WaitingView* waiting_view_;
|
| -
|
| - // The text for the current action.
|
| - string16 action_text_;
|
| -
|
| - // Ownership of the WebContents we are displaying in the inline disposition.
|
| - scoped_ptr<WebContents> inline_web_contents_;
|
| -
|
| - // Indicate if dialog should display its own close button.
|
| - // TODO(groby): Only relevant until new WebContentsModalDialog is implemented,
|
| - // from then on always true.
|
| - bool use_close_button_;
|
| -
|
| - // Signals if the picker can be closed. False during extension install.
|
| - bool can_close_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(WebIntentPickerViews);
|
| -};
|
| -
|
| -// static
|
| -WebIntentPicker* WebIntentPicker::Create(content::WebContents* web_contents,
|
| - WebIntentPickerDelegate* delegate,
|
| - WebIntentPickerModel* model) {
|
| - return new WebIntentPickerViews(web_contents, delegate, model);
|
| -}
|
| -
|
| -WebIntentPickerViews::WebIntentPickerViews(WebContents* web_contents,
|
| - WebIntentPickerDelegate* delegate,
|
| - WebIntentPickerModel* model)
|
| - : state_(INITIAL),
|
| - delegate_(delegate),
|
| - model_(model),
|
| - action_label_(NULL),
|
| - extensions_(NULL),
|
| - web_contents_(web_contents),
|
| - webview_(new views::WebView(
|
| - Profile::FromBrowserContext(web_contents->GetBrowserContext()))),
|
| - window_(NULL),
|
| - more_suggestions_link_(NULL),
|
| - inline_service_icon_(NULL),
|
| - choose_another_service_link_(NULL),
|
| - waiting_view_(NULL),
|
| - can_close_(true) {
|
| - use_close_button_ = false;
|
| -
|
| - model_->set_observer(this);
|
| - contents_ = new views::View();
|
| - contents_->set_background(views::Background::CreateSolidBackground(
|
| - chrome_style::GetBackgroundColor()));
|
| -
|
| - // Show the dialog.
|
| - window_ = ConstrainedWindowViews::Create(web_contents, this);
|
| - if (model_->IsInlineDisposition())
|
| - OnInlineDisposition(string16(), model_->inline_disposition_url());
|
| - else
|
| - UpdateContents();
|
| -}
|
| -
|
| -WebIntentPickerViews::~WebIntentPickerViews() {
|
| - model_->set_observer(NULL);
|
| -}
|
| -
|
| -void WebIntentPickerViews::ButtonPressed(views::Button* sender,
|
| - const ui::Event& event) {
|
| - DCHECK(delegate_);
|
| - delegate_->OnUserCancelledPickerDialog();
|
| -}
|
| -
|
| -void WebIntentPickerViews::WindowClosing() {
|
| - if (delegate_)
|
| - delegate_->OnClosing();
|
| -}
|
| -
|
| -void WebIntentPickerViews::DeleteDelegate() {
|
| - delete this;
|
| -}
|
| -
|
| -views::Widget* WebIntentPickerViews::GetWidget() {
|
| - return contents_->GetWidget();
|
| -}
|
| -
|
| -const views::Widget* WebIntentPickerViews::GetWidget() const {
|
| - return contents_->GetWidget();
|
| -}
|
| -
|
| -views::View* WebIntentPickerViews::GetContentsView() {
|
| - return contents_;
|
| -}
|
| -
|
| -void WebIntentPickerViews::LinkClicked(views::Link* source, int event_flags) {
|
| - DCHECK(delegate_);
|
| - if (source == more_suggestions_link_) {
|
| - delegate_->OnSuggestionsLinkClicked(
|
| - ui::DispositionFromEventFlags(event_flags));
|
| - } else if (source == choose_another_service_link_) {
|
| - // Signal cancellation of inline disposition.
|
| - delegate_->OnChooseAnotherService();
|
| - ResetContents();
|
| - } else {
|
| - NOTREACHED();
|
| - }
|
| -}
|
| -
|
| -void WebIntentPickerViews::Close() {
|
| - window_->CloseWebContentsModalDialog();
|
| -}
|
| -
|
| -void WebIntentPickerViews::SetActionString(const string16& action) {
|
| - action_text_ = action;
|
| - if (action_label_) {
|
| - action_label_->SetText(GetActionTitle());
|
| - contents_->Layout();
|
| - SizeToContents();
|
| - }
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnExtensionInstallSuccess(const std::string& id) {
|
| - can_close_ = true;
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnExtensionInstallFailure(const std::string& id) {
|
| - extensions_->StopThrobber();
|
| - extensions_->SetEnabled(true);
|
| - more_suggestions_link_->SetEnabled(true);
|
| - can_close_ = true;
|
| - contents_->Layout();
|
| - SizeToContents();
|
| -
|
| - // TODO(binji): What to display to user on failure?
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnInlineDispositionAutoResize(
|
| - const gfx::Size& size) {
|
| - webview_->SetPreferredSize(size);
|
| - contents_->Layout();
|
| - SizeToContents();
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnPendingAsyncCompleted() {
|
| - UpdateContents();
|
| -}
|
| -
|
| -void WebIntentPickerViews::InvalidateDelegate() {
|
| - delegate_ = NULL;
|
| -}
|
| -
|
| -void WebIntentPickerViews::ShowNoServicesMessage() {
|
| - if (state_ == NO_SERVICES)
|
| - return;
|
| - state_ = NO_SERVICES;
|
| -
|
| - ClearContents();
|
| - views::GridLayout* layout = new views::GridLayout(contents_);
|
| - layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
|
| - const int kContentBuiltinBottomPadding = 3;
|
| - layout->SetInsets(chrome_style::kCloseButtonPadding,
|
| - 0,
|
| - chrome_style::kClientBottomPadding -
|
| - kContentBuiltinBottomPadding,
|
| - 0);
|
| - contents_->SetLayoutManager(layout);
|
| -
|
| - enum GridLayoutColumnSets {
|
| - HEADER_ROW,
|
| - CONTENT_ROW,
|
| - };
|
| - views::ColumnSet* header_cs = layout->AddColumnSet(HEADER_ROW);
|
| - header_cs->AddPaddingColumn(
|
| - 0, chrome_style::kHorizontalPadding);
|
| - header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // Title
|
| - header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Close button
|
| - header_cs->AddPaddingColumn(
|
| - 0, chrome_style::kCloseButtonPadding);
|
| -
|
| - views::ColumnSet* content_cs = layout->AddColumnSet(CONTENT_ROW);
|
| - content_cs->AddPaddingColumn(
|
| - 0, chrome_style::kHorizontalPadding);
|
| - content_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // Body
|
| - content_cs->AddPaddingColumn(
|
| - 0, chrome_style::kHorizontalPadding);
|
| -
|
| - // Header
|
| - layout->StartRow(0, HEADER_ROW);
|
| - views::Label* title = CreateTitleLabel();
|
| - title->SetText(l10n_util::GetStringUTF16(
|
| - IDS_INTENT_PICKER_NO_SERVICES_TITLE));
|
| - layout->AddView(title);
|
| -
|
| - views::ImageButton* close_button = CreateCloseButton(this);
|
| - layout->AddView(close_button);
|
| - close_button->SetVisible(use_close_button_);
|
| -
|
| - // Content
|
| - const int kHeaderBuiltinBottomPadding = 4;
|
| - const int kContentBuiltinTopPadding = 5;
|
| - layout->AddPaddingRow(0,
|
| - chrome_style::kRowPadding -
|
| - kHeaderBuiltinBottomPadding -
|
| - kContentBuiltinTopPadding);
|
| - layout->StartRow(0, CONTENT_ROW);
|
| - views::Label* body = CreateLabel();
|
| - body->SetMultiLine(true);
|
| - body->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_NO_SERVICES));
|
| - layout->AddView(body);
|
| -
|
| - int height = contents_->GetHeightForWidth(WebIntentPicker::kWindowMinWidth);
|
| - contents_->SetSize(gfx::Size(WebIntentPicker::kWindowMinWidth, height));
|
| - contents_->Layout();
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnInlineDispositionWebContentsLoaded(
|
| - content::WebContents* web_contents) {
|
| - if (state_ == INLINE_SERVICE)
|
| - return;
|
| - state_ = INLINE_SERVICE;
|
| -
|
| - // Replace the picker with the inline disposition.
|
| - ClearContents();
|
| - views::GridLayout* grid_layout = new views::GridLayout(contents_);
|
| - grid_layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
|
| - grid_layout->SetInsets(chrome_style::kCloseButtonPadding, 0,
|
| - chrome_style::kClientBottomPadding, 0);
|
| - contents_->SetLayoutManager(grid_layout);
|
| -
|
| - enum GridLayoutColumnSets {
|
| - HEADER_ROW,
|
| - SEPARATOR_ROW,
|
| - WEB_CONTENTS_ROW,
|
| - };
|
| - views::ColumnSet* header_cs = grid_layout->AddColumnSet(HEADER_ROW);
|
| - header_cs->AddPaddingColumn(
|
| - 0, chrome_style::kHorizontalPadding);
|
| - header_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // Icon, title, link.
|
| - header_cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
|
| - header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Close button.
|
| - header_cs->AddPaddingColumn(
|
| - 0, chrome_style::kCloseButtonPadding);
|
| -
|
| - views::ColumnSet* sep_cs = grid_layout->AddColumnSet(SEPARATOR_ROW);
|
| - sep_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // Separator.
|
| -
|
| - views::ColumnSet* contents_cs = grid_layout->AddColumnSet(WEB_CONTENTS_ROW);
|
| - contents_cs->AddPaddingColumn(0, 1);
|
| - contents_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // Web contents.
|
| - contents_cs->AddPaddingColumn(0, 1);
|
| -
|
| - // Header.
|
| - grid_layout->StartRow(0, HEADER_ROW);
|
| -
|
| - const WebIntentPickerModel::InstalledService* service =
|
| - model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
|
| -
|
| - if (!inline_service_icon_)
|
| - inline_service_icon_ = new views::ImageView();
|
| - inline_service_icon_->SetImage(service->favicon.ToImageSkia());
|
| -
|
| - views::Label* title = CreateLabel();
|
| - title->SetText(ui::ElideText(
|
| - service->title, title->font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END));
|
| -
|
| - if (!choose_another_service_link_)
|
| - choose_another_service_link_ = CreateLink();
|
| - choose_another_service_link_->SetText(l10n_util::GetStringUTF16(
|
| - IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE));
|
| - choose_another_service_link_->set_listener(this);
|
| -
|
| - grid_layout->AddView(CreateInlineDispositionHeader(
|
| - inline_service_icon_, title, choose_another_service_link_));
|
| - choose_another_service_link_->SetVisible(IsUseAnotherServiceVisible(model_));
|
| -
|
| - views::ImageButton* close_button = CreateCloseButton(this);
|
| - grid_layout->AddView(close_button);
|
| - close_button->SetVisible(use_close_button_);
|
| -
|
| - // Separator.
|
| - const int kHeaderBuiltinBottomPadding = 4;
|
| - grid_layout->AddPaddingRow(0,
|
| - chrome_style::kRowPadding -
|
| - kHeaderBuiltinBottomPadding);
|
| - grid_layout->StartRow(0, SEPARATOR_ROW);
|
| - grid_layout->AddView(new views::Separator());
|
| -
|
| - // Inline web contents.
|
| - const int kSeparatorBottomPadding = 3;
|
| - grid_layout->AddPaddingRow(0, kSeparatorBottomPadding);
|
| - grid_layout->StartRow(0, WEB_CONTENTS_ROW);
|
| - grid_layout->AddView(webview_);
|
| -
|
| - contents_->Layout();
|
| - SizeToContents();
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnModelChanged(WebIntentPickerModel* model) {
|
| - if (state_ == WAITING && !model->IsWaitingForSuggestions())
|
| - UpdateContents();
|
| -
|
| - if (choose_another_service_link_) {
|
| - choose_another_service_link_->SetVisible(IsUseAnotherServiceVisible(model));
|
| - contents_->Layout();
|
| - SizeToContents();
|
| - }
|
| -
|
| - if (extensions_)
|
| - RefreshExtensions();
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnFaviconChanged(WebIntentPickerModel* model,
|
| - size_t index) {
|
| - // TODO(groby): Update favicons on extensions_;
|
| - if (inline_service_icon_)
|
| - RefreshInlineServiceIcon();
|
| - if (extensions_)
|
| - RefreshExtensions();
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnExtensionIconChanged(
|
| - WebIntentPickerModel* model,
|
| - const std::string& extension_id) {
|
| - OnFaviconChanged(model, -1);
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnInlineDisposition(
|
| - const string16&, const GURL& url) {
|
| - DCHECK(delegate_);
|
| - Profile* profile =
|
| - Profile::FromBrowserContext(web_contents_->GetBrowserContext());
|
| - if (!webview_)
|
| - webview_ = new views::WebView(profile);
|
| -
|
| - inline_web_contents_.reset(
|
| - delegate_->CreateWebContentsForInlineDisposition(profile, url));
|
| -
|
| - // Does not take ownership, so we keep a scoped_ptr
|
| - // for the WebContents locally.
|
| - webview_->SetWebContents(inline_web_contents_.get());
|
| - Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
|
| - inline_disposition_delegate_.reset(
|
| - new WebIntentInlineDispositionDelegate(this, inline_web_contents_.get(),
|
| - browser));
|
| -
|
| - inline_web_contents_->GetController().LoadURL(
|
| - url,
|
| - content::Referrer(),
|
| - content::PAGE_TRANSITION_AUTO_TOPLEVEL,
|
| - std::string());
|
| -
|
| - // Disable all buttons.
|
| - // TODO(groby): Add throbber for inline dispo - see http://crbug.com/142519.
|
| - if (extensions_)
|
| - extensions_->SetEnabled(false);
|
| - if (more_suggestions_link_)
|
| - more_suggestions_link_->SetEnabled(false);
|
| - contents_->Layout();
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnExtensionInstallClicked(
|
| - const std::string& extension_id) {
|
| - DCHECK(delegate_);
|
| - can_close_ = false;
|
| - extensions_->StartThrobber(extension_id);
|
| - more_suggestions_link_->SetEnabled(false);
|
| - contents_->Layout();
|
| - delegate_->OnExtensionInstallRequested(extension_id);
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnExtensionLinkClicked(
|
| - const std::string& extension_id,
|
| - WindowOpenDisposition disposition) {
|
| - DCHECK(delegate_);
|
| - delegate_->OnExtensionLinkClicked(extension_id, disposition);
|
| -}
|
| -
|
| -void WebIntentPickerViews::OnActionButtonClicked(
|
| - IntentRowView::ActionType type, size_t tag) {
|
| - DCHECK(delegate_);
|
| - DCHECK_EQ(IntentRowView::ACTION_INVOKE, type);
|
| - const WebIntentPickerModel::InstalledService& service =
|
| - model_->GetInstalledServiceAt(tag);
|
| - delegate_->OnServiceChosen(service.url, service.disposition,
|
| - WebIntentPickerDelegate::kEnableDefaults);
|
| -}
|
| -
|
| -void WebIntentPickerViews::UpdateContents() {
|
| - if (model_ && model_->IsInlineDisposition())
|
| - return;
|
| -
|
| - if (model_ && model_->IsWaitingForSuggestions()) {
|
| - ShowWaitingForSuggestions();
|
| - } else if (model_ && (model_->GetInstalledServiceCount() ||
|
| - model_->GetSuggestedExtensionCount())) {
|
| - ShowAvailableServices();
|
| - } else {
|
| - ShowNoServicesMessage();
|
| - }
|
| - SizeToContents();
|
| -}
|
| -
|
| -void WebIntentPickerViews::ShowWaitingForSuggestions() {
|
| - if (state_ == WAITING)
|
| - return;
|
| - state_ = WAITING;
|
| - ClearContents();
|
| - contents_->SetLayoutManager(new views::FillLayout());
|
| - waiting_view_ = new WaitingView(this, use_close_button_);
|
| - contents_->AddChildView(waiting_view_);
|
| - int height = contents_->GetHeightForWidth(kWindowMinWidth);
|
| - contents_->SetSize(gfx::Size(kWindowMinWidth, height));
|
| - contents_->Layout();
|
| -}
|
| -
|
| -const string16 WebIntentPickerViews::GetActionTitle() {
|
| - return action_text_.empty() ?
|
| - l10n_util::GetStringUTF16(IDS_INTENT_PICKER_CHOOSE_SERVICE) :
|
| - action_text_;
|
| -}
|
| -
|
| -void WebIntentPickerViews::ShowAvailableServices() {
|
| - ClearContents();
|
| - state_ = LIST_SERVICES;
|
| - extensions_ = new IntentsView(model_, this);
|
| - gfx::Size min_size = gfx::Size(extensions_->AdjustWidth(kWindowMinWidth), 0);
|
| -
|
| - views::GridLayout* grid_layout = new views::GridLayout(contents_);
|
| - grid_layout->set_minimum_size(min_size);
|
| - const int kIconBuiltinBottomPadding = 4;
|
| - grid_layout->SetInsets(chrome_style::kCloseButtonPadding,
|
| - 0,
|
| - chrome_style::kClientBottomPadding -
|
| - kIconBuiltinBottomPadding,
|
| - 0);
|
| - contents_->SetLayoutManager(grid_layout);
|
| -
|
| - enum GridLayoutColumnSets {
|
| - HEADER_ROW,
|
| - CONTENT_ROW,
|
| - };
|
| - views::ColumnSet* header_cs = grid_layout->AddColumnSet(HEADER_ROW);
|
| - header_cs->AddPaddingColumn(
|
| - 0, chrome_style::kHorizontalPadding);
|
| - header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // Action title
|
| - header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Close button
|
| - header_cs->AddPaddingColumn(
|
| - 0, chrome_style::kCloseButtonPadding);
|
| -
|
| - views::ColumnSet* content_cs = grid_layout->AddColumnSet(CONTENT_ROW);
|
| - content_cs->AddPaddingColumn(
|
| - 0, chrome_style::kHorizontalPadding);
|
| - content_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // Content.
|
| - content_cs->AddPaddingColumn(
|
| - 0, chrome_style::kHorizontalPadding);
|
| -
|
| - // Header.
|
| - grid_layout->StartRow(0, HEADER_ROW);
|
| - if (!action_label_)
|
| - action_label_ = CreateTitleLabel();
|
| - action_label_->SetText(GetActionTitle());
|
| - grid_layout->AddView(action_label_);
|
| -
|
| - views::ImageButton* close_button = CreateCloseButton(this);
|
| - grid_layout->AddView(close_button);
|
| - close_button->SetVisible(use_close_button_);
|
| -
|
| - // Extensions.
|
| - const int kHeaderBuiltinBottomPadding = 4;
|
| - grid_layout->AddPaddingRow(0,
|
| - chrome_style::kRowPadding -
|
| - kHeaderBuiltinBottomPadding);
|
| - grid_layout->StartRow(0, CONTENT_ROW);
|
| - grid_layout->AddView(extensions_);
|
| -
|
| -
|
| - // Row with "more suggestions" link.
|
| - const int kIconBuiltinTopPadding = 6;
|
| - grid_layout->AddPaddingRow(0,
|
| - chrome_style::kRowPadding -
|
| - kIconBuiltinTopPadding);
|
| - grid_layout->StartRow(0, CONTENT_ROW);
|
| - views::View* more_view = new views::View();
|
| - more_view->SetLayoutManager(new views::BoxLayout(
|
| - views::BoxLayout::kHorizontal, 0, 0, kIconTextPadding));
|
| - views::ImageView* icon = new views::ImageView();
|
| - icon->SetImage(ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
|
| - IDR_WEBSTORE_ICON_16));
|
| - more_view->AddChildView(icon);
|
| - if (!more_suggestions_link_)
|
| - more_suggestions_link_ = CreateLink();
|
| - more_suggestions_link_->SetText(
|
| - l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE));
|
| - more_suggestions_link_->set_listener(this);
|
| - more_view->AddChildView(more_suggestions_link_);
|
| - grid_layout->AddView(more_view, 1, 1,
|
| - GridLayout::LEADING, GridLayout::CENTER);
|
| -
|
| - contents_->Layout();
|
| -}
|
| -
|
| -void WebIntentPickerViews::ResetContents() {
|
| - // Abandon both web contents and webview.
|
| - webview_->SetWebContents(NULL);
|
| - inline_web_contents_.reset();
|
| - webview_ = NULL;
|
| -
|
| - // Re-initialize the UI.
|
| - UpdateContents();
|
| -
|
| - // Restore previous state.
|
| - if (extensions_)
|
| - extensions_->Update();
|
| - if (action_label_)
|
| - action_label_->SetText(action_text_);
|
| - contents_->Layout();
|
| - SizeToContents();
|
| -}
|
| -
|
| -void WebIntentPickerViews::SizeToContents() {
|
| - gfx::Size client_size = contents_->GetPreferredSize();
|
| - gfx::Rect client_bounds(client_size);
|
| - gfx::Rect new_window_bounds = window_->non_client_view()->frame_view()->
|
| - GetWindowBoundsForClientBounds(client_bounds);
|
| - window_->CenterWindow(new_window_bounds.size());
|
| -}
|
| -
|
| -void WebIntentPickerViews::ClearContents() {
|
| - DCHECK(contents_);
|
| - // The call RemoveAllChildViews(true) deletes all children of |contents|. If
|
| - // we do not set our weak pointers to NULL, then they will continue to point
|
| - // to where the deleted objects used to be, i.e. unitialized memory. This
|
| - // would cause hard-to-explain crashes.
|
| - contents_->RemoveAllChildViews(true);
|
| - action_label_ = NULL;
|
| - extensions_ = NULL;
|
| - more_suggestions_link_ = NULL;
|
| - inline_service_icon_ = NULL;
|
| - choose_another_service_link_ = NULL;
|
| -}
|
| -
|
| -void WebIntentPickerViews::RefreshInlineServiceIcon() {
|
| - DCHECK(inline_service_icon_);
|
| - const WebIntentPickerModel::InstalledService* inline_service =
|
| - model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
|
| - if (inline_service)
|
| - inline_service_icon_->SetImage(inline_service->favicon.ToImageSkia());
|
| -}
|
| -
|
| -void WebIntentPickerViews::RefreshExtensions() {
|
| - DCHECK(extensions_);
|
| - extensions_->Update();
|
| - contents_->Layout();
|
| - SizeToContents();
|
| -}
|
|
|