1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.h"
6
7 #include <string>
8
9 #include "base/run_loop.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/apps/app_service/app_service_proxy.h"
14 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
15 #include "chrome/browser/chromeos/arc/arc_util.h"
16 #include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/app_list/arc/arc_app_icon.h"
19 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/test/test_browser_dialog.h"
22 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
23 #include "chrome/browser/web_applications/components/app_registrar.h"
24 #include "chrome/browser/web_applications/components/web_app_provider_base.h"
25 #include "chrome/browser/web_applications/components/web_application_info.h"
26 #include "chrome/grit/generated_resources.h"
27 #include "chrome/test/base/in_process_browser_test.h"
28 #include "components/arc/arc_util.h"
29 #include "components/arc/test/connection_holder_util.h"
30 #include "components/arc/test/fake_app_instance.h"
31 #include "content/public/test/browser_test.h"
32 #include "content/public/test/test_navigation_observer.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "ui/base/l10n/l10n_util.h"
35
36 class AppUninstallDialogViewBrowserTest : public DialogBrowserTest {
37 public:
ActiveView()38 AppDialogView* ActiveView() {
39 return AppUninstallDialogView::GetActiveViewForTesting();
40 }
41
ShowUi(const std::string & name)42 void ShowUi(const std::string& name) override {
43 EXPECT_EQ(nullptr, ActiveView());
44
45 auto* app_service_proxy =
46 apps::AppServiceProxyFactory::GetForProfile(browser()->profile());
47 ASSERT_TRUE(app_service_proxy);
48
49 base::RunLoop run_loop;
50 app_service_proxy->UninstallForTesting(app_id_, nullptr,
51 run_loop.QuitClosure());
52 run_loop.Run();
53
54 ASSERT_NE(nullptr, ActiveView());
55 EXPECT_EQ(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
56 ActiveView()->GetDialogButtons());
57 base::string16 title =
58 base::ASCIIToUTF16("Uninstall \"" + app_name_ + "\"?");
59 EXPECT_EQ(title, ActiveView()->GetWindowTitle());
60
61 if (name == "accept") {
62 ActiveView()->AcceptDialog();
63
64 app_service_proxy->FlushMojoCallsForTesting();
65 bool is_uninstalled = false;
66 app_service_proxy->AppRegistryCache().ForOneApp(
67 app_id_, [&is_uninstalled, name](const apps::AppUpdate& update) {
68 is_uninstalled = (update.Readiness() ==
69 apps::mojom::Readiness::kUninstalledByUser);
70 });
71
72 EXPECT_TRUE(is_uninstalled);
73 } else {
74 ActiveView()->CancelDialog();
75
76 app_service_proxy->FlushMojoCallsForTesting();
77 bool is_installed = true;
78 app_service_proxy->AppRegistryCache().ForOneApp(
79 app_id_, [&is_installed, name](const apps::AppUpdate& update) {
80 is_installed =
81 (update.Readiness() == apps::mojom::Readiness::kReady);
82 });
83
84 EXPECT_TRUE(is_installed);
85 }
86 EXPECT_EQ(nullptr, ActiveView());
87 }
88
89 protected:
90 std::string app_id_;
91 std::string app_name_;
92 };
93
94 class ArcAppsUninstallDialogViewBrowserTest
95 : public AppUninstallDialogViewBrowserTest {
96 public:
SetUpCommandLine(base::CommandLine * command_line)97 void SetUpCommandLine(base::CommandLine* command_line) override {
98 arc::SetArcAvailableCommandLineForTesting(command_line);
99 }
100
SetUpInProcessBrowserTestFixture()101 void SetUpInProcessBrowserTestFixture() override {
102 arc::ArcSessionManager::SetUiEnabledForTesting(false);
103 }
104
SetUpOnMainThread()105 void SetUpOnMainThread() override {
106 AppUninstallDialogViewBrowserTest::SetUpOnMainThread();
107
108 arc::SetArcPlayStoreEnabledForProfile(browser()->profile(), true);
109
110 // Validating decoded content does not fit well for unit tests.
111 ArcAppIcon::DisableSafeDecodingForTesting();
112
113 arc_app_list_pref_ = ArcAppListPrefs::Get(browser()->profile());
114 ASSERT_TRUE(arc_app_list_pref_);
115 base::RunLoop run_loop;
116 arc_app_list_pref_->SetDefaultAppsReadyCallback(run_loop.QuitClosure());
117 run_loop.Run();
118
119 app_instance_ = std::make_unique<arc::FakeAppInstance>(arc_app_list_pref_);
120 arc_app_list_pref_->app_connection_holder()->SetInstance(
121 app_instance_.get());
122 WaitForInstanceReady(arc_app_list_pref_->app_connection_holder());
123 }
124
TearDownOnMainThread()125 void TearDownOnMainThread() override {
126 arc_app_list_pref_->app_connection_holder()->CloseInstance(
127 app_instance_.get());
128 app_instance_.reset();
129 arc::ArcSessionManager::Get()->Shutdown();
130 }
131
CreateApp()132 void CreateApp() {
133 arc::mojom::AppInfo app;
134 app.name = "Fake App 0";
135 app.package_name = "fake.package.0";
136 app.activity = "fake.app.0.activity";
137 app.sticky = false;
138 app_instance_->SendRefreshAppList(std::vector<arc::mojom::AppInfo>(1, app));
139 base::RunLoop().RunUntilIdle();
140
141 EXPECT_EQ(1u, arc_app_list_pref_->GetAppIds().size());
142 app_id_ = arc_app_list_pref_->GetAppId(app.package_name, app.activity);
143 app_name_ = app.name;
144 }
145
146 private:
147 ArcAppListPrefs* arc_app_list_pref_ = nullptr;
148 std::unique_ptr<arc::FakeAppInstance> app_instance_;
149 };
150
IN_PROC_BROWSER_TEST_F(ArcAppsUninstallDialogViewBrowserTest,InvokeUi_Accept)151 IN_PROC_BROWSER_TEST_F(ArcAppsUninstallDialogViewBrowserTest, InvokeUi_Accept) {
152 CreateApp();
153 ShowUi("accept");
154 }
155
IN_PROC_BROWSER_TEST_F(ArcAppsUninstallDialogViewBrowserTest,InvokeUi_Cancel)156 IN_PROC_BROWSER_TEST_F(ArcAppsUninstallDialogViewBrowserTest, InvokeUi_Cancel) {
157 CreateApp();
158 ShowUi("cancel");
159 }
160
161 class WebAppsUninstallDialogViewBrowserTest
162 : public AppUninstallDialogViewBrowserTest {
163 public:
SetUpOnMainThread()164 void SetUpOnMainThread() override {
165 AppUninstallDialogViewBrowserTest::SetUpOnMainThread();
166
167 https_server_.AddDefaultHandlers(GetChromeTestDataDir());
168 ASSERT_TRUE(https_server_.Start());
169 }
170
CreateApp()171 void CreateApp() {
172 auto web_app_info = std::make_unique<WebApplicationInfo>();
173 web_app_info->start_url = GetAppURL();
174 web_app_info->scope = GetAppURL().GetWithoutFilename();
175
176 app_id_ =
177 web_app::InstallWebApp(browser()->profile(), std::move(web_app_info));
178 content::TestNavigationObserver navigation_observer(GetAppURL());
179 navigation_observer.StartWatchingNewWebContents();
180 web_app::LaunchWebAppBrowser(browser()->profile(), app_id_);
181 navigation_observer.WaitForNavigationFinished();
182
183 auto* provider =
184 web_app::WebAppProviderBase::GetProviderBase(browser()->profile());
185 DCHECK(provider);
186 app_name_ = provider->registrar().GetAppShortName(app_id_);
187 }
188
GetAppURL() const189 GURL GetAppURL() const {
190 return https_server_.GetURL("app.com", "/ssl/google.html");
191 }
192
193 protected:
194 // For mocking a secure site.
195 net::EmbeddedTestServer https_server_;
196 };
197
IN_PROC_BROWSER_TEST_F(WebAppsUninstallDialogViewBrowserTest,InvokeUi_Accept)198 IN_PROC_BROWSER_TEST_F(WebAppsUninstallDialogViewBrowserTest, InvokeUi_Accept) {
199 CreateApp();
200 ShowUi("accept");
201 }
202
IN_PROC_BROWSER_TEST_F(WebAppsUninstallDialogViewBrowserTest,InvokeUi_Cancel)203 IN_PROC_BROWSER_TEST_F(WebAppsUninstallDialogViewBrowserTest, InvokeUi_Cancel) {
204 CreateApp();
205 ShowUi("cancel");
206 }
207