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

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

Powered by Google App Engine
This is Rietveld 408576698