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

Side by Side Diff: chrome/browser/ui/app_list/drive/drive_app_provider_browsertest.cc

Issue 308003005: app_list: Drive app integration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: format Created 6 years, 6 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "chrome/browser/ui/app_list/drive/drive_app_provider.h"
6
7 #include "base/logging.h"
8 #include "base/macros.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/path_service.h"
11 #include "base/timer/timer.h"
12 #include "chrome/browser/drive/drive_app_registry.h"
13 #include "chrome/browser/drive/fake_drive_service.h"
14 #include "chrome/browser/extensions/extension_browsertest.h"
15 #include "chrome/browser/extensions/install_tracker.h"
16 #include "chrome/browser/extensions/install_tracker_factory.h"
17 #include "chrome/browser/ui/app_list/drive/drive_app_mapping.h"
18 #include "chrome/browser/ui/app_list/drive/drive_service_bridge.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
21 #include "content/public/test/test_utils.h"
22 #include "extensions/browser/extension_registry.h"
23 #include "sync/api/string_ordinal.h"
24 #include "ui/app_list/app_list_folder_item.h"
25 #include "ui/app_list/app_list_item.h"
26 #include "ui/app_list/app_list_item_list.h"
27 #include "ui/app_list/test/app_list_test_model.h"
28
29 namespace {
30
31 const char kDriveAppId[] = "drive_app_id";
32 const char kDriveAppName[] = "Fake Drive App";
33 const char kLaunchUrl[] = "http://example.com/drive";
34
35 // App id of hosted_app.crx.
36 const char kChromeAppId[] = "kbmnembihfiondgfjekmnmcbddelicoi";
37
38 // Stub drive service bridge.
39 class TestDriveServiceBridge : public DriveServiceBridge {
40 public:
41 explicit TestDriveServiceBridge(drive::DriveAppRegistry* registry)
42 : registry_(registry) {}
43 virtual ~TestDriveServiceBridge() {}
44
45 virtual drive::DriveAppRegistry* GetAppRegistry() OVERRIDE {
46 return registry_;
47 }
48
49 private:
50 drive::DriveAppRegistry* registry_;
51
52 DISALLOW_COPY_AND_ASSIGN(TestDriveServiceBridge);
53 };
54
55 // A model builder that creates and deletes items of a given model when app
56 // is installed and uninstalled in the given profile.
57 class TestModelBuilder : public extensions::InstallObserver {
58 public:
59 TestModelBuilder(Profile* profile, app_list::test::AppListTestModel* model)
60 : profile_(profile), model_(model) {
61 extensions::InstallTracker::Get(profile_)->AddObserver(this);
62 }
63 virtual ~TestModelBuilder() {
64 extensions::InstallTracker::Get(profile_)->RemoveObserver(this);
65 }
66
67 // extensions::InstallObserver
68 virtual void OnExtensionLoaded(
69 const extensions::Extension* extension) OVERRIDE {
70 model_->CreateAndAddItem(extension->id());
71 }
72 virtual void OnExtensionUninstalled(
73 const extensions::Extension* extension) OVERRIDE {
74 model_->DeleteItem(extension->id());
75 }
76
77 private:
78 Profile* profile_;
79 app_list::test::AppListTestModel* model_;
80
81 DISALLOW_COPY_AND_ASSIGN(TestModelBuilder);
82 };
83
84 } // namespace
85
86 class DriveAppProviderTest : public ExtensionBrowserTest {
87 public:
88 DriveAppProviderTest() {}
89 virtual ~DriveAppProviderTest() {}
90
91 // ExtensionBrowserTest:
92 virtual void SetUpOnMainThread() OVERRIDE {
93 ExtensionBrowserTest::SetUpOnMainThread();
94
95 fake_drive_service_.reset(new drive::FakeDriveService);
96 fake_drive_service_->LoadAppListForDriveApi("drive/applist_empty.json");
97 apps_registry_.reset(
98 new drive::DriveAppRegistry(fake_drive_service_.get()));
99
100 model_.reset(new app_list::test::AppListTestModel);
101 model_builder_.reset(new TestModelBuilder(profile(), model_.get()));
102
103 provider_.reset(new DriveAppProvider(profile(), model_.get()));
104 provider_->SetDriveServiceBridgeForTest(
105 make_scoped_ptr(new TestDriveServiceBridge(apps_registry_.get()))
106 .PassAs<DriveServiceBridge>());
107 }
108
109 virtual void CleanUpOnMainThread() OVERRIDE {
110 provider_.reset();
111 apps_registry_.reset();
112 fake_drive_service_.reset();
113 model_builder_.reset();
114
115 ExtensionBrowserTest::CleanUpOnMainThread();
116 }
117
118 const extensions::Extension* InstallChromeApp(int expected_change) {
119 base::FilePath test_data_path;
120 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_data_path)) {
121 ADD_FAILURE();
122 return NULL;
123 }
124 test_data_path =
125 test_data_path.AppendASCII("extensions").AppendASCII("hosted_app.crx");
126 const extensions::Extension* extension =
127 InstallExtension(test_data_path, expected_change);
128 return extension;
129 }
130
131 void RefreshDriveAppRegistry() {
132 apps_registry_->Update();
133 content::RunAllPendingInMessageLoop();
134 }
135
136 void WaitForPendingDriveAppConverters() {
137 DCHECK(!runner_);
138
139 if (provider_->pending_converters_.empty())
140 return;
141
142 runner_ = new content::MessageLoopRunner;
143
144 pending_drive_app_converter_check_timer_.Start(
145 FROM_HERE,
146 base::TimeDelta::FromMilliseconds(50),
147 base::Bind(&DriveAppProviderTest::OnPendingDriveAppConverterCheckTimer,
148 base::Unretained(this)));
149
150 runner_->Run();
151
152 pending_drive_app_converter_check_timer_.Stop();
153 runner_ = NULL;
154 }
155
156 drive::FakeDriveService* fake_drive_service() {
157 return fake_drive_service_.get();
158 }
159 app_list::test::AppListTestModel* model() { return model_.get(); }
160 DriveAppProvider* provider() { return provider_.get(); }
161 DriveAppMapping* mapping() { return provider_->mapping_.get(); }
162
163 private:
164 void OnPendingDriveAppConverterCheckTimer() {
165 if (provider_->pending_converters_.empty())
166 runner_->Quit();
167 }
168
169 scoped_ptr<drive::FakeDriveService> fake_drive_service_;
170 scoped_ptr<drive::DriveAppRegistry> apps_registry_;
171 scoped_ptr<TestModelBuilder> model_builder_;
172 scoped_ptr<app_list::test::AppListTestModel> model_;
173 scoped_ptr<DriveAppProvider> provider_;
174
175 base::RepeatingTimer<DriveAppProviderTest>
176 pending_drive_app_converter_check_timer_;
177 scoped_refptr<content::MessageLoopRunner> runner_;
178
179 DISALLOW_COPY_AND_ASSIGN(DriveAppProviderTest);
180 };
181
182 // A Drive app maps to an existing Chrome app that has a matching id.
183 // Uninstalling the chrome app would also disconnect the drive app.
184 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, ExistingChromeApp) {
185 // Prepare an existing chrome app.
186 const extensions::Extension* chrome_app = InstallChromeApp(1);
187 ASSERT_TRUE(chrome_app);
188
189 // Prepare a Drive app that matches the chrome app id.
190 fake_drive_service()->AddApp(
191 kDriveAppId, kDriveAppName, chrome_app->id(), kLaunchUrl);
192 RefreshDriveAppRegistry();
193 WaitForPendingDriveAppConverters();
194
195 // The Drive app should use the matching chrome app.
196 EXPECT_EQ(chrome_app->id(), mapping()->GetChromeApp(kDriveAppId));
197
198 // Unintalling chrome app should disconnect the Drive app on server.
199 EXPECT_TRUE(fake_drive_service()->HasApp(kDriveAppId));
200 UninstallExtension(chrome_app->id());
201 EXPECT_FALSE(fake_drive_service()->HasApp(kDriveAppId));
202 }
203
204 // A Drive app creates an URL app when no matching Chrome app presents.
205 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, CreateUrlApp) {
206 // Prepare a Drive app with no underlying chrome app.
207 fake_drive_service()->AddApp(kDriveAppId, kDriveAppName, "", kLaunchUrl);
208 RefreshDriveAppRegistry();
209 WaitForPendingDriveAppConverters();
210
211 // An Url app should be created.
212 const extensions::Extension* chrome_app =
213 extensions::ExtensionRegistry::Get(profile())
214 ->GetExtensionById(mapping()->GetChromeApp(kDriveAppId),
215 extensions::ExtensionRegistry::EVERYTHING);
216 ASSERT_TRUE(chrome_app);
217 EXPECT_EQ(kDriveAppName, chrome_app->name());
218 EXPECT_TRUE(chrome_app->is_hosted_app());
219 EXPECT_TRUE(chrome_app->from_bookmark());
220 EXPECT_EQ(GURL(kLaunchUrl),
221 extensions::AppLaunchInfo::GetLaunchWebURL(chrome_app));
222
223 EXPECT_EQ(chrome_app->id(), mapping()->GetChromeApp(kDriveAppId));
224
225 // Unintalling the chrome app should disconnect the Drive app on server.
226 EXPECT_TRUE(fake_drive_service()->HasApp(kDriveAppId));
227 UninstallExtension(chrome_app->id());
228 EXPECT_FALSE(fake_drive_service()->HasApp(kDriveAppId));
229 }
230
231 // A matching Chrome app replaces the created URL app.
232 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, MatchingChromeAppInstalled) {
233 // Prepare a Drive app that matches the not-yet-installed kChromeAppId.
234 fake_drive_service()->AddApp(
235 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl);
236 RefreshDriveAppRegistry();
237 WaitForPendingDriveAppConverters();
238
239 // An Url app should be created.
240 const extensions::Extension* url_app =
241 extensions::ExtensionRegistry::Get(profile())
242 ->GetExtensionById(mapping()->GetChromeApp(kDriveAppId),
243 extensions::ExtensionRegistry::EVERYTHING);
244 EXPECT_TRUE(url_app->is_hosted_app());
245 EXPECT_TRUE(url_app->from_bookmark());
246
247 const std::string url_app_id = url_app->id();
248 EXPECT_NE(kChromeAppId, url_app_id);
249 EXPECT_EQ(url_app_id, mapping()->GetChromeApp(kDriveAppId));
250
251 // Installs a chrome app with matching id.
252 InstallChromeApp(0);
253
254 // The Drive app should be mapped to chrome app.
255 EXPECT_EQ(kChromeAppId, mapping()->GetChromeApp(kDriveAppId));
256
257 // Url app should be auto uninstalled.
258 EXPECT_FALSE(extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
259 url_app_id, extensions::ExtensionRegistry::EVERYTHING));
260 }
261
262 // Tests that the corresponding URL app is uninstalled when a Drive app is
263 // disconnected.
264 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest,
265 DisconnectDriveAppUninstallUrlApp) {
266 // Prepare a Drive app that matches the not-yet-installed kChromeAppId.
267 fake_drive_service()->AddApp(
268 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl);
269 RefreshDriveAppRegistry();
270 WaitForPendingDriveAppConverters();
271
272 // Url app is created.
273 const std::string url_app_id = mapping()->GetChromeApp(kDriveAppId);
274 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
275 url_app_id, extensions::ExtensionRegistry::EVERYTHING));
276
277 fake_drive_service()->RemoveAppByProductId(kChromeAppId);
278 RefreshDriveAppRegistry();
279
280 // Url app is auto uninstalled.
281 EXPECT_FALSE(extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
282 url_app_id, extensions::ExtensionRegistry::EVERYTHING));
283 }
284
285 // Tests that the matching Chrome app is preserved when a Drive app is
286 // disconnected.
287 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest,
288 DisconnectDriveAppPreserveChromeApp) {
289 // Prepare an existing chrome app.
290 const extensions::Extension* chrome_app = InstallChromeApp(1);
291 ASSERT_TRUE(chrome_app);
292
293 // Prepare a Drive app that matches the chrome app id.
294 fake_drive_service()->AddApp(
295 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl);
296 RefreshDriveAppRegistry();
297 WaitForPendingDriveAppConverters();
298
299 fake_drive_service()->RemoveAppByProductId(kChromeAppId);
300 RefreshDriveAppRegistry();
301
302 // Chrome app is still present after the Drive app is disconnected.
303 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
304 kChromeAppId, extensions::ExtensionRegistry::EVERYTHING));
305 }
306
307 // A new URL app replaces the existing one and keeps existing// position when a
308 // Drive app changes its name or URL.
309 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, DriveAppChanged) {
310 // Prepare a Drive app with no underlying chrome app.
311 fake_drive_service()->AddApp(
312 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl);
313 RefreshDriveAppRegistry();
314 WaitForPendingDriveAppConverters();
315
316 // An Url app should be created.
317 const std::string url_app_id = mapping()->GetChromeApp(kDriveAppId);
318 const extensions::Extension* url_app =
319 extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
320 url_app_id, extensions::ExtensionRegistry::EVERYTHING);
321 ASSERT_TRUE(url_app);
322 EXPECT_EQ(kDriveAppName, url_app->name());
323 EXPECT_TRUE(url_app->is_hosted_app());
324 EXPECT_TRUE(url_app->from_bookmark());
325 EXPECT_EQ(GURL(kLaunchUrl),
326 extensions::AppLaunchInfo::GetLaunchWebURL(url_app));
327
328 // Put url app into a test folder position.
329 const char kTestFolder[] = "test-folder";
330 const size_t kExpectedIndex = 3;
331 for (size_t i = 0; i < kExpectedIndex; ++i) {
332 model()->AddItemToFolder(
333 model()->CreateItem(model()->GetItemName(static_cast<int>(i))),
334 kTestFolder);
335 }
336 app_list::AppListFolderItem* folder = model()->FindFolderItem(kTestFolder);
337 ASSERT_TRUE(folder);
338 model()->MoveItemToFolderAt(model()->FindItem(url_app->id()),
339 kTestFolder,
340 folder->item_list()
341 ->item_at(kExpectedIndex - 1)
342 ->position()
343 .CreateAfter());
344
345 // Register the Drive app with a different name and URL.
346 const char kAnotherName[] = "Another drive app name";
347 const char kAnotherLaunchUrl[] = "http://example.com/another_end_point";
348 fake_drive_service()->RemoveAppByProductId(kChromeAppId);
349 fake_drive_service()->AddApp(
350 kDriveAppId, kAnotherName, kChromeAppId, kAnotherLaunchUrl);
351 RefreshDriveAppRegistry();
352 WaitForPendingDriveAppConverters();
353
354 // Old URL app should be auto uninstalled.
355 url_app = extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
356 url_app_id, extensions::ExtensionRegistry::EVERYTHING);
357 EXPECT_FALSE(url_app);
358
359 // New URL app should be used.
360 const std::string new_url_app_id = mapping()->GetChromeApp(kDriveAppId);
361 EXPECT_NE(new_url_app_id, url_app_id);
362
363 const extensions::Extension* new_url_app =
364 extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
365 new_url_app_id, extensions::ExtensionRegistry::EVERYTHING);
366 ASSERT_TRUE(new_url_app);
367 EXPECT_EQ(kAnotherName, new_url_app->name());
368 EXPECT_TRUE(new_url_app->is_hosted_app());
369 EXPECT_TRUE(new_url_app->from_bookmark());
370 EXPECT_EQ(GURL(kAnotherLaunchUrl),
371 extensions::AppLaunchInfo::GetLaunchWebURL(new_url_app));
372
373 app_list::AppListItem* item = model()->FindItem(new_url_app_id);
374 ASSERT_TRUE(item);
375 EXPECT_EQ(kTestFolder, item->folder_id());
376 size_t item_index;
377 ASSERT_TRUE(folder->item_list()->FindItemIndex(new_url_app_id, &item_index));
378 EXPECT_EQ(kExpectedIndex, item_index);
379 }
380
381 // An existing URL app is not changed when underlying drive app data (name and
382 // URL) is not changed.
383 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, NoChange) {
384 // Prepare one Drive app.
385 fake_drive_service()->AddApp(
386 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl);
387 RefreshDriveAppRegistry();
388 WaitForPendingDriveAppConverters();
389
390 const std::string url_app_id = mapping()->GetChromeApp(kDriveAppId);
391 const extensions::Extension* url_app =
392 extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
393 url_app_id, extensions::ExtensionRegistry::EVERYTHING);
394
395 // Refresh with no actual change.
396 RefreshDriveAppRegistry();
397 WaitForPendingDriveAppConverters();
398
399 // Url app should remain unchanged.
400 const std::string new_url_app_id = mapping()->GetChromeApp(kDriveAppId);
401 EXPECT_EQ(new_url_app_id, url_app_id);
402
403 const extensions::Extension* new_url_app =
404 extensions::ExtensionRegistry::Get(profile())->GetExtensionById(
405 new_url_app_id, extensions::ExtensionRegistry::EVERYTHING);
406 EXPECT_EQ(url_app, new_url_app);
407 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698