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/ash/holding_space/holding_space_browsertest_base.h"
6
7 #include <string>
8
9 #include "ash/public/cpp/ash_features.h"
10 #include "ash/public/cpp/holding_space/holding_space_controller.h"
11 #include "ash/public/cpp/holding_space/holding_space_image.h"
12 #include "ash/public/cpp/holding_space/holding_space_item.h"
13 #include "ash/public/cpp/holding_space/holding_space_model.h"
14 #include "ash/public/cpp/holding_space/holding_space_test_api.h"
15 #include "base/callback_helpers.h"
16 #include "base/files/file_util.h"
17 #include "base/scoped_observer.h"
18 #include "base/unguessable_token.h"
19 #include "chrome/browser/chromeos/file_manager/path_util.h"
20 #include "chrome/browser/extensions/component_loader.h"
21 #include "chrome/browser/profiles/profile_manager.h"
22 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h"
23 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h"
24 #include "chrome/browser/ui/ash/holding_space/holding_space_util.h"
25 #include "chromeos/dbus/session_manager/session_manager_client.h"
26 #include "components/session_manager/core/session_manager.h"
27 #include "components/session_manager/core/session_manager_observer.h"
28 #include "storage/browser/file_system/external_mount_points.h"
29 #include "ui/gfx/image/image_skia.h"
30 #include "ui/views/view.h"
31
32 namespace ash {
33
34 namespace {
35
36 // Helpers ---------------------------------------------------------------------
37
38 // Returns the path of the downloads mount point for the given `profile`.
GetDownloadsPath(Profile * profile)39 base::FilePath GetDownloadsPath(Profile* profile) {
40 base::FilePath result;
41 EXPECT_TRUE(
42 storage::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(
43 file_manager::util::GetDownloadsMountPointName(profile), &result));
44 return result;
45 }
46
47 // Creates a file at the root of the downloads mount point with the specified
48 // `extension`, returning the path of the created file.
CreateFile(Profile * profile,const std::string & extension)49 base::FilePath CreateFile(Profile* profile, const std::string& extension) {
50 const base::FilePath file_path =
51 GetDownloadsPath(profile).Append(base::StringPrintf(
52 "%s.%s", base::UnguessableToken::Create().ToString().c_str(),
53 extension.c_str()));
54
55 {
56 base::ScopedAllowBlockingForTesting allow_blocking;
57 if (!base::CreateDirectory(file_path.DirName())) {
58 ADD_FAILURE() << "Failed to create parent directory.";
59 return base::FilePath();
60 }
61 if (!base::WriteFile(file_path, /*content=*/std::string())) {
62 ADD_FAILURE() << "Filed to write file contents.";
63 return base::FilePath();
64 }
65 }
66
67 return file_path;
68 }
69
70 // Creates a .txt file at the root of the downloads mount point and returns the
71 // path of the created file.
CreateTextFile(Profile * profile)72 base::FilePath CreateTextFile(Profile* profile) {
73 return CreateFile(profile, "txt");
74 }
75
76 // Creates a .png file at the root of the downloads mount point and returns the
77 // path of the created file.
CreateImageFile(Profile * profile)78 base::FilePath CreateImageFile(Profile* profile) {
79 return CreateFile(profile, "png");
80 }
81
82 // SessionStateWaiter ----------------------------------------------------------
83
84 // Utility class which allows waiting for a `session_manager::SessionState`.
85 class SessionStateWaiter : public session_manager::SessionManagerObserver {
86 public:
SessionStateWaiter()87 SessionStateWaiter() {
88 session_manager_observer_.Add(session_manager::SessionManager::Get());
89 }
90
WaitFor(session_manager::SessionState state)91 void WaitFor(session_manager::SessionState state) {
92 if (session_state() == state)
93 return;
94
95 state_ = state;
96
97 wait_loop_ = std::make_unique<base::RunLoop>();
98 wait_loop_->Run();
99 wait_loop_.reset();
100 }
101
102 private:
103 // session_manager::SessionManagerObserver:
OnSessionStateChanged()104 void OnSessionStateChanged() override {
105 if (wait_loop_ && session_state() == state_)
106 wait_loop_->Quit();
107 }
108
session_state() const109 session_manager::SessionState session_state() const {
110 return session_manager::SessionManager::Get()->session_state();
111 }
112
113 session_manager::SessionState state_ = session_manager::SessionState::UNKNOWN;
114 std::unique_ptr<base::RunLoop> wait_loop_;
115
116 ScopedObserver<session_manager::SessionManager,
117 session_manager::SessionManagerObserver>
118 session_manager_observer_{this};
119 };
120
121 } // namespace
122
123 // HoldingSpaceBrowserTestBase -------------------------------------------------
124
HoldingSpaceBrowserTestBase()125 HoldingSpaceBrowserTestBase::HoldingSpaceBrowserTestBase() {
126 scoped_feature_list_.InitAndEnableFeature(features::kTemporaryHoldingSpace);
127 }
128
129 HoldingSpaceBrowserTestBase::~HoldingSpaceBrowserTestBase() = default;
130
SetUpInProcessBrowserTestFixture()131 void HoldingSpaceBrowserTestBase::SetUpInProcessBrowserTestFixture() {
132 InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
133 extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
134 }
135
SetUpOnMainThread()136 void HoldingSpaceBrowserTestBase::SetUpOnMainThread() {
137 InProcessBrowserTest::SetUpOnMainThread();
138 test_api_ = std::make_unique<HoldingSpaceTestApi>();
139 }
140
141 // static
GetRootWindowForNewWindows()142 aura::Window* HoldingSpaceBrowserTestBase::GetRootWindowForNewWindows() {
143 return HoldingSpaceTestApi::GetRootWindowForNewWindows();
144 }
145
GetProfile()146 Profile* HoldingSpaceBrowserTestBase::GetProfile() {
147 return ProfileManager::GetActiveUserProfile();
148 }
149
Show()150 void HoldingSpaceBrowserTestBase::Show() {
151 test_api_->Show();
152 }
153
Close()154 void HoldingSpaceBrowserTestBase::Close() {
155 test_api_->Close();
156 }
157
IsShowing()158 bool HoldingSpaceBrowserTestBase::IsShowing() {
159 return test_api_->IsShowing();
160 }
161
IsShowingInShelf()162 bool HoldingSpaceBrowserTestBase::IsShowingInShelf() {
163 return test_api_->IsShowingInShelf();
164 }
165
AddDownloadFile()166 HoldingSpaceItem* HoldingSpaceBrowserTestBase::AddDownloadFile() {
167 return AddItem(GetProfile(), HoldingSpaceItem::Type::kDownload,
168 /*file_path=*/CreateTextFile(GetProfile()));
169 }
170
AddNearbyShareFile()171 HoldingSpaceItem* HoldingSpaceBrowserTestBase::AddNearbyShareFile() {
172 return AddItem(GetProfile(), HoldingSpaceItem::Type::kNearbyShare,
173 /*file_path=*/CreateImageFile(GetProfile()));
174 }
175
AddPinnedFile()176 HoldingSpaceItem* HoldingSpaceBrowserTestBase::AddPinnedFile() {
177 return AddItem(GetProfile(), HoldingSpaceItem::Type::kPinnedFile,
178 /*file_path=*/CreateTextFile(GetProfile()));
179 }
180
AddScreenshotFile()181 HoldingSpaceItem* HoldingSpaceBrowserTestBase::AddScreenshotFile() {
182 return AddItem(GetProfile(), HoldingSpaceItem::Type::kScreenshot,
183 /*file_path=*/CreateImageFile(GetProfile()));
184 }
185
AddScreenRecordingFile()186 HoldingSpaceItem* HoldingSpaceBrowserTestBase::AddScreenRecordingFile() {
187 return AddItem(GetProfile(), HoldingSpaceItem::Type::kScreenRecording,
188 /*file_path=*/CreateImageFile(GetProfile()));
189 }
190
AddItem(Profile * profile,HoldingSpaceItem::Type type,const base::FilePath & file_path)191 HoldingSpaceItem* HoldingSpaceBrowserTestBase::AddItem(
192 Profile* profile,
193 HoldingSpaceItem::Type type,
194 const base::FilePath& file_path) {
195 auto item = HoldingSpaceItem::CreateFileBackedItem(
196 type, file_path,
197 holding_space_util::ResolveFileSystemUrl(profile, file_path),
198 /*image=*/
199 std::make_unique<HoldingSpaceImage>(
200 /*placeholder=*/gfx::ImageSkia(),
201 /*async_bitmap_resolver=*/base::DoNothing()));
202
203 auto* item_ptr = item.get();
204
205 // Add holding space items through the holding space keyed service so that the
206 // time of first add will be marked in preferences. The time of first add
207 // contributes to deciding when the holding space tray is visible.
208 HoldingSpaceKeyedServiceFactory::GetInstance()
209 ->GetService(GetProfile())
210 ->AddItem(std::move(item));
211
212 return item_ptr;
213 }
214
RemoveItem(const HoldingSpaceItem * item)215 void HoldingSpaceBrowserTestBase::RemoveItem(const HoldingSpaceItem* item) {
216 HoldingSpaceController::Get()->model()->RemoveItem(item->id());
217 }
218
GetDownloadChips()219 std::vector<views::View*> HoldingSpaceBrowserTestBase::GetDownloadChips() {
220 return test_api_->GetDownloadChips();
221 }
222
GetPinnedFileChips()223 std::vector<views::View*> HoldingSpaceBrowserTestBase::GetPinnedFileChips() {
224 return test_api_->GetPinnedFileChips();
225 }
226
GetScreenCaptureViews()227 std::vector<views::View*> HoldingSpaceBrowserTestBase::GetScreenCaptureViews() {
228 return test_api_->GetScreenCaptureViews();
229 }
230
GetTrayIcon()231 views::View* HoldingSpaceBrowserTestBase::GetTrayIcon() {
232 return test_api_->GetTrayIcon();
233 }
234
RequestAndAwaitLockScreen()235 void HoldingSpaceBrowserTestBase::RequestAndAwaitLockScreen() {
236 if (session_manager::SessionManager::Get()->IsScreenLocked())
237 return;
238
239 chromeos::SessionManagerClient::Get()->RequestLockScreen();
240 SessionStateWaiter().WaitFor(session_manager::SessionState::LOCKED);
241 }
242
243 } // namespace ash
244