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