Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2306)

Unified Diff: chrome/browser/ui/views/arc_app_dialog_view.cc

Issue 2529783002: arc: Implement uninstall confirmation dialog for Arc app. (Closed)
Patch Set: Clean up. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/arc_app_dialog_view.cc
diff --git a/chrome/browser/ui/views/arc_app_dialog_view.cc b/chrome/browser/ui/views/arc_app_dialog_view.cc
new file mode 100644
index 0000000000000000000000000000000000000000..09a2a33e368781a8694fb43cfed4d4c32f793001
--- /dev/null
+++ b/chrome/browser/ui/views/arc_app_dialog_view.cc
@@ -0,0 +1,305 @@
+// Copyright 2016 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/app_list/arc/arc_app_dialog.h"
+
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_util.h"
+#include "chrome/browser/profiles/profile.h"
msw 2016/11/29 20:47:36 ditto nit: just use forward decl.
lgcheng 2016/11/30 19:28:47 Need this so that compile knows Profile is subclas
+#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
+#include "chrome/browser/ui/native_window_tracker.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/constrained_window/constrained_window_views.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/view.h"
+#include "ui/views/window/dialog_delegate.h"
+
+namespace arc {
+
+namespace {
+
+const int kRightColumnWidth = 210;
+const int kIconSize = 64;
+const int kIconSourceSize = 32;
msw 2016/11/29 20:47:37 Can we just ask the loader for 64px and let it dea
lgcheng 2016/11/30 19:28:46 Make loader handles the resizing. Remove kIconSour
+
+class ArcAppDialogView : public views::DialogDelegateView,
+ public AppIconLoaderDelegate {
+ public:
+ ArcAppDialogView(Profile* profile,
+ AppListControllerDelegate* controller,
+ const std::string& app_id,
+ const base::string16& window_title,
+ const base::string16& head_text,
msw 2016/11/29 20:47:36 nit: |heading_text| here and elsewhere
lgcheng 2016/11/30 19:28:46 Done.
+ const base::string16& confirm_button_text,
+ const base::string16& cancel_button_text,
+ ArcAppConfirmCallback& confirm_callback);
+ ~ArcAppDialogView() override;
+
+ // Public method to start dialog process.
msw 2016/11/29 20:47:36 nit: "Start loading the icon; the dialog will be s
lgcheng 2016/11/30 19:28:46 Remove this method. Inline in constructor.
+ void Execute();
+
+ // Public method used for test only.
+ void SelectOptionForTest(bool confirm);
msw 2016/11/29 20:47:37 optional nit: |ConfirmOrCancelForTest|
lgcheng 2016/11/30 19:28:46 Done.
+
+ private:
+ // views::WidgetDelegate:
+ base::string16 GetWindowTitle() const override { return window_title_; }
msw 2016/11/29 20:47:37 nit: define these out-of-line, to be consistent wi
lgcheng 2016/11/30 19:28:47 Done.
+ void DeleteDelegate() override;
+ ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_WINDOW; }
+
+ // views::View:
+ gfx::Size GetPreferredSize() const override;
+ void Layout() override;
+
+ // views::DialogDelegate:
+ base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
+ bool Cancel() override;
+ bool Accept() override;
+
+ // AppIconLoaderDelegate:
+ void OnAppImageUpdated(const std::string& app_id,
+ const gfx::ImageSkia& image) override;
+
+ // Popups the constrained window of confirmation dialog.
msw 2016/11/29 20:47:37 nit: "Constructs and shows the modal dialog widget
lgcheng 2016/11/30 19:28:47 Done.
+ void Show();
+
+ bool initial_setup_ = true;
+ gfx::ImageSkia icon_ = gfx::ImageSkia();
msw 2016/11/29 20:47:37 You don't need to explicitly invoke the default ct
lgcheng 2016/11/30 19:28:47 Done.
+
+ views::ImageView* icon_view_;
msw 2016/11/29 20:47:36 nit: = nullptr;
lgcheng 2016/11/30 19:28:47 Done.
+ views::Label* heading_view_;
msw 2016/11/29 20:47:37 nit: = nullptr;
lgcheng 2016/11/30 19:28:47 Done.
+
+ std::unique_ptr<ArcAppIconLoader> icon_loader_;
+
+ Profile* const profile_;
+
+ AppListControllerDelegate* controller_;
+
+ gfx::NativeWindow parent_;
+
+ // Tracks whether |parent_| got destroyed.
+ std::unique_ptr<NativeWindowTracker> parent_window_tracker_;
+
+ const std::string app_id_;
+ const base::string16 window_title_;
+ const base::string16 confirm_button_text_;
+ const base::string16 cancel_button_text_;
+ ArcAppConfirmCallback confirm_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcAppDialogView);
+};
+
+// Browertest use only. Global pointer of ArcAppDialogView which is shown.
+ArcAppDialogView* g_current_arc_app_dialog_view = nullptr;
+
+ArcAppDialogView::ArcAppDialogView(Profile* profile,
+ AppListControllerDelegate* controller,
+ const std::string& app_id,
+ const base::string16& window_title,
+ const base::string16& head_text,
+ const base::string16& confirm_button_text,
+ const base::string16& cancel_button_text,
+ ArcAppConfirmCallback& confirm_callback)
+ : profile_(profile),
+ controller_(controller),
+ app_id_(app_id),
+ window_title_(window_title),
+ confirm_button_text_(confirm_button_text),
+ cancel_button_text_(cancel_button_text),
+ confirm_callback_(confirm_callback) {
+ DCHECK(controller);
+ parent_ = controller_->GetAppListWindow();
+ if (parent_)
+ parent_window_tracker_ = NativeWindowTracker::Create(parent_);
+
+ gfx::Size size(gfx::Size(kIconSize, kIconSize));
msw 2016/11/29 20:47:36 nit: "gfx::Size size(kIconSize, kIconSize);" or ju
lgcheng 2016/11/30 19:28:47 Done.
+ icon_view_ = new views::ImageView();
+ icon_view_->SetImageSize(size);
+ AddChildView(icon_view_);
+
+ heading_view_ = new views::Label(head_text);
+ heading_view_->SetMultiLine(true);
+ heading_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ heading_view_->SetAllowCharacterBreak(true);
+ AddChildView(heading_view_);
+}
+
+ArcAppDialogView::~ArcAppDialogView() {
+ g_current_arc_app_dialog_view = nullptr;
msw 2016/11/29 20:47:37 nit: DCHECK_EQ(this, g_current_arc_app_dialog_view
lgcheng 2016/11/30 19:28:46 Done.
+}
+
+void ArcAppDialogView::Execute() {
+ icon_loader_.reset(new ArcAppIconLoader(profile_, kIconSourceSize, this));
msw 2016/11/29 20:47:37 optional nit: inline this in the constructor?
lgcheng 2016/11/30 19:28:46 Done.
+ icon_loader_->FetchImage(app_id_);
+}
+
+void ArcAppDialogView::SelectOptionForTest(bool confirm) {
+ if (confirm)
+ Accept();
+ else
+ Cancel();
+}
+
+void ArcAppDialogView::DeleteDelegate() {
+ if (controller_) {
msw 2016/11/29 20:47:37 optional nit: remove curlies.
lgcheng 2016/11/30 19:28:47 Done.
+ controller_->OnCloseChildDialog();
+ }
+ delete this;
msw 2016/11/29 20:47:37 optional nit: call DialogDelegateView::DeleteDeleg
lgcheng 2016/11/30 19:28:46 Done.
+}
+
+gfx::Size ArcAppDialogView::GetPreferredSize() const {
msw 2016/11/29 20:47:36 nit: Can you use a LayoutManager instead of doing
lgcheng 2016/11/30 19:28:47 This part is identical with extension uninstall di
msw 2016/11/30 23:26:57 I see. Please file a bug to update both in a follo
lgcheng 2016/12/01 02:05:56 Done.
+ int width = kRightColumnWidth;
+ width += kIconSize;
+ width += views::kButtonHEdgeMarginNew * 2;
+ width += views::kRelatedControlHorizontalSpacing;
+
+ int height = views::kPanelVertMargin * 2;
+ height += heading_view_->GetHeightForWidth(kRightColumnWidth);
+
+ return gfx::Size(width,
+ std::max(height, kIconSize + views::kPanelVertMargin * 2));
+}
+
+void ArcAppDialogView::Layout() {
+ int x = views::kButtonHEdgeMarginNew;
+ int y = views::kPanelVertMargin;
+
+ heading_view_->SizeToFit(kRightColumnWidth);
+
+ if (heading_view_->height() <= kIconSize) {
+ icon_view_->SetBounds(x, y, kIconSize, kIconSize);
+ x += kIconSize;
+ x += views::kRelatedControlHorizontalSpacing;
+
+ heading_view_->SetX(x);
+ heading_view_->SetY(y + (kIconSize - heading_view_->height()) / 2);
+ } else {
+ icon_view_->SetBounds(x, y + (heading_view_->height() - kIconSize) / 2,
+ kIconSize, kIconSize);
+ x += kIconSize;
+ x += views::kRelatedControlHorizontalSpacing;
+
+ heading_view_->SetX(x);
+ heading_view_->SetY(y);
+ }
+}
+
+base::string16 ArcAppDialogView::GetDialogButtonLabel(
+ ui::DialogButton button) const {
+ return button == ui::DIALOG_BUTTON_CANCEL ? cancel_button_text_
+ : confirm_button_text_;
+}
+
+bool ArcAppDialogView::Cancel() {
msw 2016/11/29 20:47:37 Not needed; DialogDelegateView::Cancel already ret
lgcheng 2016/11/30 19:28:46 Done.
+ return true;
+}
+
+bool ArcAppDialogView::Accept() {
+ confirm_callback_.Run(app_id_, profile_);
+ return true;
+}
+
+void ArcAppDialogView::OnAppImageUpdated(const std::string& app_id,
+ const gfx::ImageSkia& image) {
+ DCHECK_EQ(app_id, app_id_);
+
+ if (image.isNull()) {
msw 2016/11/29 20:47:36 nit: remove curlies
lgcheng 2016/11/30 19:28:46 Redundant check removed.
+ icon_ = extensions::util::GetDefaultAppIcon();
msw 2016/11/29 20:47:37 Remove the |icon_| class member and just do: icon_
lgcheng 2016/11/30 19:28:47 Redundant image nullity check removed.
+ } else {
+ icon_ = image;
+ }
+
+ icon_view_->SetImage(icon_);
+
+ if (initial_setup_)
+ Show();
msw 2016/11/29 20:47:36 So we only create and show the dialog once icon lo
lgcheng 2016/11/30 19:28:46 There is safeguard in ArcAppIconLoader ensures tha
msw 2016/11/30 23:26:57 It would be even better to have a safeguard here,
+}
+
+void ArcAppDialogView::Show() {
+ initial_setup_ = false;
+
+ // Parent window is killed before icon_ is loaded.
+ if (parent_ && parent_window_tracker_->WasNativeWindowClosed()) {
+ Cancel();
msw 2016/11/29 20:47:37 Does |this| ArcAppDialogView leak here? Perhaps it
lgcheng 2016/11/30 19:28:47 Yes, there is a potential here. delete this added.
+ return;
+ }
+
+ if (controller_)
+ controller_->OnShowChildDialog();
+
+ g_current_arc_app_dialog_view = this;
+ constrained_window::CreateBrowserModalDialogViews(this, parent_)->Show();
+}
+
+void ShowDialogImpl(Profile* profile,
msw 2016/11/29 20:47:36 optional nit: inline this in ShowArcAppUninstallDi
lgcheng 2016/11/30 19:28:47 Done.
+ AppListControllerDelegate* controller,
+ const std::string& app_id,
+ const base::string16& window_title,
+ const base::string16& head_text,
+ const base::string16& confirm_button_text,
+ const base::string16& cancel_button_text,
+ ArcAppConfirmCallback& confirm_callback) {
+ ArcAppDialogView* arc_app_dialog = new ArcAppDialogView(
+ profile, controller, app_id, window_title, head_text, confirm_button_text,
+ cancel_button_text, confirm_callback);
+ arc_app_dialog->Execute();
+}
+
+} // namespace
+
+void ShowArcAppUninstallDialog(Profile* profile,
+ AppListControllerDelegate* controller,
+ const std::string& app_id,
+ ArcAppConfirmCallback confirm_callback) {
msw 2016/11/29 20:47:37 nit: bind arc::UninstallArcApp in this function, n
lgcheng 2016/11/30 19:28:46 Done.
+ ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile);
+ DCHECK(arc_prefs);
+ std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
+ arc_prefs->GetApp(app_id);
+
+ if (!app_info)
+ return;
+
+ bool is_shortcut = app_info->shortcut;
+
+ base::string16 window_title = l10n_util::GetStringUTF16(
+ is_shortcut ? IDS_EXTENSION_UNINSTALL_PROMPT_TITLE
+ : IDS_APP_UNINSTALL_PROMPT_TITLE);
+
+ base::string16 head_text = base::UTF8ToUTF16(l10n_util::GetStringFUTF8(
+ is_shortcut ? IDS_EXTENSION_UNINSTALL_PROMPT_HEADING
+ : IDS_ARC_APP_UNINSTALL_PROMPT_HEADING,
+ base::UTF8ToUTF16(app_info->name)));
+
+ base::string16 confirm_button_text = l10n_util::GetStringUTF16(
+ is_shortcut ? IDS_EXTENSION_PROMPT_UNINSTALL_BUTTON
+ : IDS_EXTENSION_PROMPT_UNINSTALL_APP_BUTTON);
+
+ base::string16 cancel_button_text = l10n_util::GetStringUTF16(IDS_CANCEL);
+
+ return ShowDialogImpl(profile, controller, app_id, window_title, head_text,
+ confirm_button_text, cancel_button_text,
+ confirm_callback);
+}
+
+bool IsArcAppDialogViewAliveForTest() {
+ return g_current_arc_app_dialog_view != nullptr;
+}
+
+bool CloseAppDialogViewAndConfirmForTest(bool confirm) {
+ if (!g_current_arc_app_dialog_view)
+ return false;
+
+ g_current_arc_app_dialog_view->SelectOptionForTest(confirm);
+ return true;
+}
+
+} // namespace arc

Powered by Google App Engine
This is Rietveld 408576698