OLD | NEW |
---|---|
(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 | |
24 using extensions::AppLaunchInfo; | |
25 using extensions::Extension; | |
26 using extensions::ExtensionRegistry; | |
27 | |
28 namespace { | |
29 | |
30 const char kDriveAppId[] = "drive_app_id"; | |
31 const char kDriveAppName[] = "Fake Drive App"; | |
32 const char kLaunchUrl[] = "http://example.com/drive"; | |
33 | |
34 // App id of hosted_app.crx. | |
35 const char kChromeAppId[] = "kbmnembihfiondgfjekmnmcbddelicoi"; | |
36 | |
37 // Stub drive service bridge. | |
38 class TestDriveServiceBridge : public DriveServiceBridge { | |
39 public: | |
40 explicit TestDriveServiceBridge(drive::DriveAppRegistry* registry) | |
41 : registry_(registry) {} | |
42 virtual ~TestDriveServiceBridge() {} | |
43 | |
44 virtual drive::DriveAppRegistry* GetAppRegistry() OVERRIDE { | |
45 return registry_; | |
46 } | |
47 | |
48 private: | |
49 drive::DriveAppRegistry* registry_; | |
50 | |
51 DISALLOW_COPY_AND_ASSIGN(TestDriveServiceBridge); | |
52 }; | |
53 | |
54 } // namespace | |
55 | |
56 class DriveAppProviderTest : public ExtensionBrowserTest { | |
57 public: | |
58 DriveAppProviderTest() {} | |
59 virtual ~DriveAppProviderTest() {} | |
60 | |
61 // ExtensionBrowserTest: | |
62 virtual void SetUpOnMainThread() OVERRIDE { | |
63 ExtensionBrowserTest::SetUpOnMainThread(); | |
64 | |
65 fake_drive_service_.reset(new drive::FakeDriveService); | |
66 fake_drive_service_->LoadAppListForDriveApi("drive/applist_empty.json"); | |
67 apps_registry_.reset( | |
68 new drive::DriveAppRegistry(fake_drive_service_.get())); | |
69 | |
70 provider_.reset(new DriveAppProvider(profile())); | |
71 provider_->SetDriveServiceBridgeForTest( | |
72 make_scoped_ptr(new TestDriveServiceBridge(apps_registry_.get())) | |
73 .PassAs<DriveServiceBridge>()); | |
74 } | |
75 | |
76 virtual void CleanUpOnMainThread() OVERRIDE { | |
77 provider_.reset(); | |
78 apps_registry_.reset(); | |
79 fake_drive_service_.reset(); | |
80 | |
81 ExtensionBrowserTest::CleanUpOnMainThread(); | |
82 } | |
83 | |
84 const Extension* InstallChromeApp(int expected_change) { | |
85 base::FilePath test_data_path; | |
86 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_data_path)) { | |
87 ADD_FAILURE(); | |
88 return NULL; | |
89 } | |
90 test_data_path = | |
91 test_data_path.AppendASCII("extensions").AppendASCII("hosted_app.crx"); | |
92 const Extension* extension = | |
93 InstallExtension(test_data_path, expected_change); | |
94 return extension; | |
95 } | |
96 | |
97 void RefreshDriveAppRegistry() { | |
98 apps_registry_->Update(); | |
99 content::RunAllPendingInMessageLoop(); | |
100 } | |
101 | |
102 void WaitForPendingDriveAppConverters() { | |
103 DCHECK(!runner_); | |
104 | |
105 if (provider_->pending_converters_.empty()) | |
106 return; | |
107 | |
108 runner_ = new content::MessageLoopRunner; | |
109 | |
110 pending_drive_app_converter_check_timer_.Start( | |
111 FROM_HERE, | |
112 base::TimeDelta::FromMilliseconds(50), | |
113 base::Bind(&DriveAppProviderTest::OnPendingDriveAppConverterCheckTimer, | |
114 base::Unretained(this))); | |
115 | |
116 runner_->Run(); | |
117 | |
118 pending_drive_app_converter_check_timer_.Stop(); | |
119 runner_ = NULL; | |
120 } | |
121 | |
122 drive::FakeDriveService* fake_drive_service() { | |
123 return fake_drive_service_.get(); | |
124 } | |
125 DriveAppProvider* provider() { return provider_.get(); } | |
126 DriveAppMapping* mapping() { return provider_->mapping_.get(); } | |
127 | |
128 private: | |
129 void OnPendingDriveAppConverterCheckTimer() { | |
130 if (provider_->pending_converters_.empty()) | |
131 runner_->Quit(); | |
132 } | |
133 | |
134 scoped_ptr<drive::FakeDriveService> fake_drive_service_; | |
135 scoped_ptr<drive::DriveAppRegistry> apps_registry_; | |
136 scoped_ptr<DriveAppProvider> provider_; | |
137 | |
138 base::RepeatingTimer<DriveAppProviderTest> | |
139 pending_drive_app_converter_check_timer_; | |
140 scoped_refptr<content::MessageLoopRunner> runner_; | |
141 | |
142 DISALLOW_COPY_AND_ASSIGN(DriveAppProviderTest); | |
143 }; | |
144 | |
145 // A Drive app maps to an existing Chrome app that has a matching id. | |
146 // Uninstalling the chrome app would also disconnect the drive app. | |
147 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, ExistingChromeApp) { | |
148 // Prepare an existing chrome app. | |
149 const Extension* chrome_app = InstallChromeApp(1); | |
150 ASSERT_TRUE(chrome_app); | |
151 | |
152 // Prepare a Drive app that matches the chrome app id. | |
153 fake_drive_service()->AddApp( | |
154 kDriveAppId, kDriveAppName, chrome_app->id(), kLaunchUrl); | |
155 RefreshDriveAppRegistry(); | |
156 WaitForPendingDriveAppConverters(); | |
benwells
2014/06/11 00:15:21
Why is this necessary here? Shouldn't there be no
xiyuan
2014/06/11 04:52:34
There should not be any. But it would be good to h
benwells
2014/06/12 06:28:59
OK, could we check instead that there are no pendi
xiyuan
2014/06/12 19:30:20
Done. Updated here an elsewhere it makes sense.
| |
157 | |
158 // The Drive app should use the matching chrome app. | |
159 EXPECT_EQ(chrome_app->id(), mapping()->GetChromeApp(kDriveAppId)); | |
160 | |
161 // Unintalling chrome app should disconnect the Drive app on server. | |
162 EXPECT_TRUE(fake_drive_service()->HasApp(kDriveAppId)); | |
163 UninstallExtension(chrome_app->id()); | |
164 EXPECT_FALSE(fake_drive_service()->HasApp(kDriveAppId)); | |
165 } | |
166 | |
167 // A Drive app creates an URL app when no matching Chrome app presents. | |
168 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, CreateUrlApp) { | |
169 // Prepare a Drive app with no underlying chrome app. | |
170 fake_drive_service()->AddApp(kDriveAppId, kDriveAppName, "", kLaunchUrl); | |
171 RefreshDriveAppRegistry(); | |
172 WaitForPendingDriveAppConverters(); | |
173 | |
174 // An Url app should be created. | |
175 const Extension* chrome_app = | |
176 ExtensionRegistry::Get(profile())->GetExtensionById( | |
177 mapping()->GetChromeApp(kDriveAppId), ExtensionRegistry::EVERYTHING); | |
178 ASSERT_TRUE(chrome_app); | |
179 EXPECT_EQ(kDriveAppName, chrome_app->name()); | |
180 EXPECT_TRUE(chrome_app->is_hosted_app()); | |
181 EXPECT_TRUE(chrome_app->from_bookmark()); | |
182 EXPECT_EQ(GURL(kLaunchUrl), AppLaunchInfo::GetLaunchWebURL(chrome_app)); | |
183 | |
184 EXPECT_EQ(chrome_app->id(), mapping()->GetChromeApp(kDriveAppId)); | |
185 | |
186 // Unintalling the chrome app should disconnect the Drive app on server. | |
187 EXPECT_TRUE(fake_drive_service()->HasApp(kDriveAppId)); | |
188 UninstallExtension(chrome_app->id()); | |
189 EXPECT_FALSE(fake_drive_service()->HasApp(kDriveAppId)); | |
190 } | |
191 | |
192 // A matching Chrome app replaces the created URL app. | |
193 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, MatchingChromeAppInstalled) { | |
194 // Prepare a Drive app that matches the not-yet-installed kChromeAppId. | |
195 fake_drive_service()->AddApp( | |
196 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl); | |
197 RefreshDriveAppRegistry(); | |
198 WaitForPendingDriveAppConverters(); | |
199 | |
200 // An Url app should be created. | |
201 const Extension* url_app = | |
202 ExtensionRegistry::Get(profile())->GetExtensionById( | |
203 mapping()->GetChromeApp(kDriveAppId), ExtensionRegistry::EVERYTHING); | |
204 EXPECT_TRUE(url_app->is_hosted_app()); | |
205 EXPECT_TRUE(url_app->from_bookmark()); | |
206 | |
207 const std::string url_app_id = url_app->id(); | |
208 EXPECT_NE(kChromeAppId, url_app_id); | |
209 EXPECT_EQ(url_app_id, mapping()->GetChromeApp(kDriveAppId)); | |
210 | |
211 // Installs a chrome app with matching id. | |
212 InstallChromeApp(0); | |
213 | |
214 // The Drive app should be mapped to chrome app. | |
215 EXPECT_EQ(kChromeAppId, mapping()->GetChromeApp(kDriveAppId)); | |
216 | |
217 // Url app should be auto uninstalled. | |
218 EXPECT_FALSE(ExtensionRegistry::Get(profile())->GetExtensionById( | |
219 url_app_id, ExtensionRegistry::EVERYTHING)); | |
220 } | |
221 | |
222 // Tests that the corresponding URL app is uninstalled when a Drive app is | |
223 // disconnected. | |
224 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, | |
225 DisconnectDriveAppUninstallUrlApp) { | |
226 // Prepare a Drive app that matches the not-yet-installed kChromeAppId. | |
227 fake_drive_service()->AddApp( | |
228 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl); | |
229 RefreshDriveAppRegistry(); | |
230 WaitForPendingDriveAppConverters(); | |
231 | |
232 // Url app is created. | |
233 const std::string url_app_id = mapping()->GetChromeApp(kDriveAppId); | |
234 EXPECT_TRUE(ExtensionRegistry::Get(profile())->GetExtensionById( | |
235 url_app_id, ExtensionRegistry::EVERYTHING)); | |
236 | |
237 fake_drive_service()->RemoveAppByProductId(kChromeAppId); | |
238 RefreshDriveAppRegistry(); | |
239 | |
240 // Url app is auto uninstalled. | |
241 EXPECT_FALSE(ExtensionRegistry::Get(profile())->GetExtensionById( | |
242 url_app_id, ExtensionRegistry::EVERYTHING)); | |
243 } | |
244 | |
245 // Tests that the matching Chrome app is preserved when a Drive app is | |
246 // disconnected. | |
247 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, | |
248 DisconnectDriveAppPreserveChromeApp) { | |
249 // Prepare an existing chrome app. | |
250 const Extension* chrome_app = InstallChromeApp(1); | |
251 ASSERT_TRUE(chrome_app); | |
252 | |
253 // Prepare a Drive app that matches the chrome app id. | |
254 fake_drive_service()->AddApp( | |
255 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl); | |
256 RefreshDriveAppRegistry(); | |
257 WaitForPendingDriveAppConverters(); | |
258 | |
259 fake_drive_service()->RemoveAppByProductId(kChromeAppId); | |
260 RefreshDriveAppRegistry(); | |
261 | |
262 // Chrome app is still present after the Drive app is disconnected. | |
263 EXPECT_TRUE(ExtensionRegistry::Get(profile())->GetExtensionById( | |
264 kChromeAppId, ExtensionRegistry::EVERYTHING)); | |
265 } | |
266 | |
267 // A new URL app replaces the existing one and keeps existing// position when a | |
268 // Drive app changes its name or URL. | |
269 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, DriveAppChanged) { | |
270 // Prepare a Drive app with no underlying chrome app. | |
271 fake_drive_service()->AddApp( | |
272 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl); | |
273 RefreshDriveAppRegistry(); | |
274 WaitForPendingDriveAppConverters(); | |
275 | |
276 // An Url app should be created. | |
277 const std::string url_app_id = mapping()->GetChromeApp(kDriveAppId); | |
278 const Extension* url_app = | |
279 ExtensionRegistry::Get(profile()) | |
280 ->GetExtensionById(url_app_id, ExtensionRegistry::EVERYTHING); | |
281 ASSERT_TRUE(url_app); | |
282 EXPECT_EQ(kDriveAppName, url_app->name()); | |
283 EXPECT_TRUE(url_app->is_hosted_app()); | |
284 EXPECT_TRUE(url_app->from_bookmark()); | |
285 EXPECT_EQ(GURL(kLaunchUrl), AppLaunchInfo::GetLaunchWebURL(url_app)); | |
286 | |
287 // Register the Drive app with a different name and URL. | |
288 const char kAnotherName[] = "Another drive app name"; | |
289 const char kAnotherLaunchUrl[] = "http://example.com/another_end_point"; | |
290 fake_drive_service()->RemoveAppByProductId(kChromeAppId); | |
291 fake_drive_service()->AddApp( | |
292 kDriveAppId, kAnotherName, kChromeAppId, kAnotherLaunchUrl); | |
293 RefreshDriveAppRegistry(); | |
294 WaitForPendingDriveAppConverters(); | |
295 | |
296 // Old URL app should be auto uninstalled. | |
297 url_app = ExtensionRegistry::Get(profile()) | |
298 ->GetExtensionById(url_app_id, ExtensionRegistry::EVERYTHING); | |
299 EXPECT_FALSE(url_app); | |
300 | |
301 // New URL app should be used. | |
302 const std::string new_url_app_id = mapping()->GetChromeApp(kDriveAppId); | |
303 EXPECT_NE(new_url_app_id, url_app_id); | |
304 | |
305 const Extension* new_url_app = | |
306 ExtensionRegistry::Get(profile()) | |
307 ->GetExtensionById(new_url_app_id, ExtensionRegistry::EVERYTHING); | |
308 ASSERT_TRUE(new_url_app); | |
309 EXPECT_EQ(kAnotherName, new_url_app->name()); | |
310 EXPECT_TRUE(new_url_app->is_hosted_app()); | |
311 EXPECT_TRUE(new_url_app->from_bookmark()); | |
312 EXPECT_EQ(GURL(kAnotherLaunchUrl), | |
313 AppLaunchInfo::GetLaunchWebURL(new_url_app)); | |
314 } | |
315 | |
316 // An existing URL app is not changed when underlying drive app data (name and | |
317 // URL) is not changed. | |
318 IN_PROC_BROWSER_TEST_F(DriveAppProviderTest, NoChange) { | |
319 // Prepare one Drive app. | |
320 fake_drive_service()->AddApp( | |
321 kDriveAppId, kDriveAppName, kChromeAppId, kLaunchUrl); | |
322 RefreshDriveAppRegistry(); | |
323 WaitForPendingDriveAppConverters(); | |
324 | |
325 const std::string url_app_id = mapping()->GetChromeApp(kDriveAppId); | |
326 const Extension* url_app = | |
327 ExtensionRegistry::Get(profile()) | |
328 ->GetExtensionById(url_app_id, ExtensionRegistry::EVERYTHING); | |
329 | |
330 // Refresh with no actual change. | |
331 RefreshDriveAppRegistry(); | |
332 WaitForPendingDriveAppConverters(); | |
333 | |
334 // Url app should remain unchanged. | |
335 const std::string new_url_app_id = mapping()->GetChromeApp(kDriveAppId); | |
336 EXPECT_EQ(new_url_app_id, url_app_id); | |
337 | |
338 const Extension* new_url_app = | |
339 ExtensionRegistry::Get(profile()) | |
340 ->GetExtensionById(new_url_app_id, ExtensionRegistry::EVERYTHING); | |
341 EXPECT_EQ(url_app, new_url_app); | |
342 } | |
OLD | NEW |