1 // Copyright 2014 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 // MediaGalleries gallery watch API browser tests.
6
7 #include "base/callback_helpers.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_path_watcher.h"
10 #include "base/files/file_util.h"
11 #include "base/macros.h"
12 #include "base/run_loop.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "build/build_config.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/extensions/extension_apitest.h"
18 #include "chrome/browser/media_galleries/media_file_system_registry.h"
19 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
20 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/render_view_host.h"
24 #include "content/public/test/browser_test.h"
25 #include "extensions/browser/process_manager.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/common/switches.h"
28 #include "extensions/test/extension_test_message_listener.h"
29
30 namespace {
31
32 // Id of test extension from
33 // chrome/test/data/extensions/api_test/|kTestExtensionPath|
34 const char kTestExtensionId[] = "gceegfkgibmgpfopknlcgleimclbknie";
35 const char kTestExtensionPath[] = "media_galleries/gallerywatch";
36
37 // JS commands.
38 const char kGetMediaFileSystemsCmd[] = "getMediaFileSystems()";
39 const char kSetupWatchOnValidGalleriesCmd[] = "setupWatchOnValidGalleries()";
40 const char kSetupWatchOnUnlistenedValidGalleriesCmd[] =
41 "setupWatchOnUnlistenedValidGalleries()";
42 const char kAddGalleryChangedListenerCmd[] = "addGalleryChangedListener()";
43 const char kAddCheckingGalleryChangedListenerCmd[] =
44 "addCheckingGalleryChangedListener()";
45 const char kRemoveGalleryChangedListenerCmd[] =
46 "removeGalleryChangedListener()";
47 const char kRemoveGalleryWatchCmd[] = "removeGalleryWatch()";
48 const char kSetupWatchOnInvalidGalleryCmd[] = "setupWatchOnInvalidGallery()";
49
50 // And JS reply messages.
51 const char kAddGalleryWatchOK[] = "add_gallery_watch_ok";
52 const char kGetMediaFileSystemsCallbackOK[] =
53 "get_media_file_systems_callback_ok";
54 const char kGetMediaFileSystemsOK[] = "get_media_file_systems_ok";
55 const char kAddGalleryChangedListenerOK[] = "add_gallery_changed_listener_ok";
56 const char kRemoveGalleryChangedListenerOK[] =
57 "remove_gallery_changed_listener_ok";
58 const char kRemoveGalleryWatchOK[] = "remove_gallery_watch_ok";
59 const char kOnGalleryChangedCheckingOK[] = "on_gallery_changed_checking_ok";
60
61 // Test reply messages.
62 const char kAddGalleryWatchRequestFailed[] = "add_watch_request_failed";
63 const char kAddGalleryWatchRequestRuntimeError[] =
64 "add_watch_request_runtime_error";
65 const char kAddGalleryWatchRequestSucceeded[] = "add_watch_request_succeeded";
66 const char kGalleryChangedEventReceived[] = "gallery_changed_event_received";
67
68 } // namespace
69
70 ///////////////////////////////////////////////////////////////////////////////
71 // MediaGalleriesGalleryWatchApiTest //
72 ///////////////////////////////////////////////////////////////////////////////
73
74 class MediaGalleriesGalleryWatchApiTest : public extensions::ExtensionApiTest {
75 public:
MediaGalleriesGalleryWatchApiTest()76 MediaGalleriesGalleryWatchApiTest()
77 : extension_(nullptr), background_host_(nullptr) {}
~MediaGalleriesGalleryWatchApiTest()78 ~MediaGalleriesGalleryWatchApiTest() override {}
79
80 protected:
81 // ExtensionApiTest overrides.
SetUpCommandLine(base::CommandLine * command_line)82 void SetUpCommandLine(base::CommandLine* command_line) override {
83 extensions::ExtensionApiTest::SetUpCommandLine(command_line);
84 command_line->AppendSwitchASCII(
85 extensions::switches::kAllowlistedExtensionID, kTestExtensionId);
86 }
SetUpOnMainThread()87 void SetUpOnMainThread() override {
88 extensions::ExtensionApiTest::SetUpOnMainThread();
89 ensure_media_directories_exists_.reset(new EnsureMediaDirectoriesExists);
90 extension_ = LoadExtension(test_data_dir_.AppendASCII(kTestExtensionPath));
91 GetBackgroundHostForTestExtension();
92 CreateTestGallery();
93 FetchMediaGalleriesList();
94 }
TearDownOnMainThread()95 void TearDownOnMainThread() override {
96 extension_ = nullptr;
97 background_host_ = nullptr;
98 ensure_media_directories_exists_.reset();
99 extensions::ExtensionApiTest::TearDownOnMainThread();
100 }
101
GalleryWatchesSupported()102 bool GalleryWatchesSupported() {
103 return base::FilePathWatcher::RecursiveWatchAvailable();
104 }
105
ExecuteCmdAndCheckReply(const std::string & js_command,const std::string & ok_message)106 void ExecuteCmdAndCheckReply(const std::string& js_command,
107 const std::string& ok_message) {
108 ExtensionTestMessageListener listener(ok_message, false);
109 background_host_->GetMainFrame()->ExecuteJavaScriptForTests(
110 base::ASCIIToUTF16(js_command), base::NullCallback());
111 EXPECT_TRUE(listener.WaitUntilSatisfied());
112 }
113
AddNewFileInTestGallery()114 bool AddNewFileInTestGallery() {
115 base::ScopedAllowBlockingForTesting allow_blocking;
116 base::FilePath gallery_file =
117 test_gallery_.GetPath().Append(FILE_PATH_LITERAL("test1.txt"));
118 return base::WriteFile(gallery_file, "new content");
119 }
120
SetupGalleryWatches()121 void SetupGalleryWatches() {
122 std::string expected_result = GalleryWatchesSupported()
123 ? kAddGalleryWatchRequestSucceeded
124 : kAddGalleryWatchRequestFailed;
125
126 ExtensionTestMessageListener add_gallery_watch_finished(
127 expected_result, false /* no reply */);
128 ExecuteCmdAndCheckReply(kSetupWatchOnValidGalleriesCmd, kAddGalleryWatchOK);
129 EXPECT_TRUE(add_gallery_watch_finished.WaitUntilSatisfied());
130 }
131
132 private:
GetBackgroundHostForTestExtension()133 void GetBackgroundHostForTestExtension() {
134 ASSERT_TRUE(extension_);
135 background_host_ = extensions::ProcessManager::Get(browser()->profile())
136 ->GetBackgroundHostForExtension(extension_->id())
137 ->render_view_host();
138 ASSERT_TRUE(background_host_);
139 }
140
CreateTestGallery()141 void CreateTestGallery() {
142 MediaGalleriesPreferences* preferences =
143 g_browser_process->media_file_system_registry()->GetPreferences(
144 browser()->profile());
145 base::RunLoop runloop;
146 preferences->EnsureInitialized(runloop.QuitClosure());
147 runloop.Run();
148
149 ASSERT_TRUE(test_gallery_.CreateUniqueTempDir());
150 MediaGalleryPrefInfo gallery_info;
151 ASSERT_FALSE(preferences->LookUpGalleryByPath(test_gallery_.GetPath(),
152 &gallery_info));
153 MediaGalleryPrefId id = preferences->AddGallery(
154 gallery_info.device_id, gallery_info.path,
155 MediaGalleryPrefInfo::kAutoDetected, gallery_info.volume_label,
156 gallery_info.vendor_name, gallery_info.model_name,
157 gallery_info.total_size_in_bytes, gallery_info.last_attach_time, 0, 0,
158 0);
159
160 preferences->SetGalleryPermissionForExtension(*extension_, id, true);
161 }
162
FetchMediaGalleriesList()163 void FetchMediaGalleriesList() {
164 ExtensionTestMessageListener get_media_systems_finished(
165 kGetMediaFileSystemsCallbackOK, false /* no reply */);
166 ExecuteCmdAndCheckReply(kGetMediaFileSystemsCmd, kGetMediaFileSystemsOK);
167 EXPECT_TRUE(get_media_systems_finished.WaitUntilSatisfied());
168 }
169
170 std::unique_ptr<EnsureMediaDirectoriesExists>
171 ensure_media_directories_exists_;
172
173 base::ScopedTempDir test_gallery_;
174
175 const extensions::Extension* extension_;
176
177 content::RenderViewHost* background_host_;
178
179 DISALLOW_COPY_AND_ASSIGN(MediaGalleriesGalleryWatchApiTest);
180 };
181
IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,BasicGalleryWatch)182 IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest, BasicGalleryWatch) {
183 // Add gallery watch listener.
184 ExecuteCmdAndCheckReply(kAddGalleryChangedListenerCmd,
185 kAddGalleryChangedListenerOK);
186
187 SetupGalleryWatches();
188
189 // Modify gallery contents.
190 ExtensionTestMessageListener gallery_change_event_received(
191 kGalleryChangedEventReceived, false /* no reply */);
192
193 ASSERT_TRUE(AddNewFileInTestGallery());
194 if (GalleryWatchesSupported())
195 EXPECT_TRUE(gallery_change_event_received.WaitUntilSatisfied());
196
197 // Remove gallery watch listener.
198 ExecuteCmdAndCheckReply(kRemoveGalleryChangedListenerCmd,
199 kRemoveGalleryChangedListenerOK);
200
201 // Remove gallery watch request.
202 if (GalleryWatchesSupported())
203 ExecuteCmdAndCheckReply(kRemoveGalleryWatchCmd, kRemoveGalleryWatchOK);
204 }
205
IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,CorrectResponseOnModifyingWatchedGallery)206 IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,
207 CorrectResponseOnModifyingWatchedGallery) {
208 if (!GalleryWatchesSupported())
209 return;
210
211 // Add gallery watch listener.
212 ExecuteCmdAndCheckReply(kAddCheckingGalleryChangedListenerCmd,
213 kAddGalleryChangedListenerOK);
214 SetupGalleryWatches();
215
216 // Modify gallery contents; expect correct details.
217 ExtensionTestMessageListener got_correct_details(kOnGalleryChangedCheckingOK,
218 false);
219 ASSERT_TRUE(AddNewFileInTestGallery());
220 EXPECT_TRUE(got_correct_details.WaitUntilSatisfied());
221 }
222
IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,RemoveListenerAndModifyGallery)223 IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,
224 RemoveListenerAndModifyGallery) {
225 if (!GalleryWatchesSupported())
226 return;
227
228 // Add a gallery watch listener.
229 ExecuteCmdAndCheckReply(kAddGalleryChangedListenerCmd,
230 kAddGalleryChangedListenerOK);
231 SetupGalleryWatches();
232
233 // Modify gallery contents.
234 ExtensionTestMessageListener gallery_change_event_received(
235 kGalleryChangedEventReceived, false /* no reply */);
236 ASSERT_TRUE(AddNewFileInTestGallery());
237 EXPECT_TRUE(gallery_change_event_received.WaitUntilSatisfied());
238
239 // Remove gallery watch listener.
240 ExecuteCmdAndCheckReply(kRemoveGalleryChangedListenerCmd,
241 kRemoveGalleryChangedListenerOK);
242
243 // No listener, modify gallery contents.
244 ASSERT_TRUE(AddNewFileInTestGallery());
245
246 // Remove gallery watch.
247 ExecuteCmdAndCheckReply(kRemoveGalleryWatchCmd, kRemoveGalleryWatchOK);
248 }
249
IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,SetupGalleryWatchWithoutListeners)250 IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,
251 SetupGalleryWatchWithoutListeners) {
252 if (!GalleryWatchesSupported())
253 return;
254
255 ExecuteCmdAndCheckReply(kSetupWatchOnUnlistenedValidGalleriesCmd,
256 kAddGalleryWatchRequestRuntimeError);
257 }
258
IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,SetupGalleryChangedListenerWithoutWatchers)259 IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,
260 SetupGalleryChangedListenerWithoutWatchers) {
261 // Add gallery watch listener.
262 ExecuteCmdAndCheckReply(kAddGalleryChangedListenerCmd,
263 kAddGalleryChangedListenerOK);
264
265 // Modify gallery contents. Listener should not get called because add watch
266 // request was not called.
267 ExtensionTestMessageListener gallery_change_event_received(
268 kGalleryChangedEventReceived, false /* no reply */);
269 ASSERT_TRUE(AddNewFileInTestGallery());
270
271 // Remove gallery watch listener.
272 ExecuteCmdAndCheckReply(kRemoveGalleryChangedListenerCmd,
273 kRemoveGalleryChangedListenerOK);
274 }
275
IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,SetupWatchOnInvalidGallery)276 IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,
277 SetupWatchOnInvalidGallery) {
278 // Add gallery watch listener.
279 ExecuteCmdAndCheckReply(kAddGalleryChangedListenerCmd,
280 kAddGalleryChangedListenerOK);
281 // Set up a invalid gallery watch.
282 ExecuteCmdAndCheckReply(kSetupWatchOnInvalidGalleryCmd,
283 kAddGalleryWatchRequestFailed);
284 }
285