Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / extension_app_model_builder_unittest.cc
1 // Copyright (c) 2012 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/extension_app_model_builder.h"
6
7 #include <string>
8
9 #include "base/files/file_path.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/run_loop.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/extension_function_test_utils.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/install_tracker.h"
17 #include "chrome/browser/extensions/install_tracker_factory.h"
18 #include "chrome/browser/ui/app_list/app_list_controller_delegate_impl.h"
19 #include "chrome/browser/ui/app_list/app_list_test_util.h"
20 #include "chrome/common/chrome_constants.h"
21 #include "chrome/common/extensions/extension_constants.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "extensions/browser/app_sorting.h"
25 #include "extensions/browser/extension_prefs.h"
26 #include "extensions/browser/uninstall_reason.h"
27 #include "extensions/common/extension_set.h"
28 #include "extensions/common/manifest.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "ui/app_list/app_list_item.h"
31
32 namespace {
33
34 // Get a string of all apps in |model| joined with ','.
35 std::string GetModelContent(app_list::AppListModel* model) {
36   std::string content;
37   for (size_t i = 0; i < model->top_level_item_list()->item_count(); ++i) {
38     if (i > 0)
39       content += ',';
40     content += model->top_level_item_list()->item_at(i)->name();
41   }
42   return content;
43 }
44
45 scoped_refptr<extensions::Extension> MakeApp(const std::string& name,
46                                              const std::string& version,
47                                              const std::string& url,
48                                              const std::string& id) {
49   std::string err;
50   base::DictionaryValue value;
51   value.SetString("name", name);
52   value.SetString("version", version);
53   value.SetString("app.launch.web_url", url);
54   scoped_refptr<extensions::Extension> app =
55       extensions::Extension::Create(
56           base::FilePath(),
57           extensions::Manifest::INTERNAL,
58           value,
59           extensions::Extension::WAS_INSTALLED_BY_DEFAULT,
60           id,
61           &err);
62   EXPECT_EQ(err, "");
63   return app;
64 }
65
66 class TestAppListControllerDelegate : public AppListControllerDelegate {
67  public:
68   virtual ~TestAppListControllerDelegate() {}
69   virtual void DismissView() OVERRIDE {}
70   virtual gfx::NativeWindow GetAppListWindow() OVERRIDE { return NULL; }
71   virtual gfx::ImageSkia GetWindowIcon() OVERRIDE { return gfx::ImageSkia(); }
72   virtual bool IsAppPinned(const std::string& extension_id) OVERRIDE {
73     return false;
74   }
75   virtual void PinApp(const std::string& extension_id) OVERRIDE {}
76   virtual void UnpinApp(const std::string& extension_id) OVERRIDE {}
77   virtual Pinnable GetPinnable() OVERRIDE { return NO_PIN; }
78   virtual bool CanDoCreateShortcutsFlow() OVERRIDE { return false; }
79   virtual void DoCreateShortcutsFlow(Profile* profile,
80                                      const std::string& extension_id) OVERRIDE {
81   }
82   virtual bool CanDoShowAppInfoFlow() OVERRIDE { return false; }
83   virtual void DoShowAppInfoFlow(Profile* profile,
84                                  const std::string& extension_id) OVERRIDE {
85   };
86   virtual void CreateNewWindow(Profile* profile, bool incognito) OVERRIDE {}
87   virtual void ActivateApp(Profile* profile,
88                            const extensions::Extension* extension,
89                            AppListSource source,
90                            int event_flags) OVERRIDE {}
91   virtual void LaunchApp(Profile* profile,
92                          const extensions::Extension* extension,
93                          AppListSource source,
94                          int event_flags) OVERRIDE {}
95   virtual void ShowForProfileByPath(
96       const base::FilePath& profile_path) OVERRIDE {}
97   virtual bool ShouldShowUserIcon() OVERRIDE { return false; }
98 };
99
100 const char kDefaultApps[] = "Packaged App 1,Packaged App 2,Hosted App";
101 const size_t kDefaultAppCount = 3u;
102
103 }  // namespace
104
105 class ExtensionAppModelBuilderTest : public AppListTestBase {
106  public:
107   ExtensionAppModelBuilderTest() {}
108   virtual ~ExtensionAppModelBuilderTest() {}
109
110   virtual void SetUp() OVERRIDE {
111     AppListTestBase::SetUp();
112
113     CreateBuilder();
114   }
115
116   virtual void TearDown() OVERRIDE {
117     ResetBuilder();
118   }
119
120  protected:
121   // Creates a new builder, destroying any existing one.
122   void CreateBuilder() {
123     ResetBuilder();  // Destroy any existing builder in the correct order.
124
125     model_.reset(new app_list::AppListModel);
126     controller_.reset(new TestAppListControllerDelegate);
127     builder_.reset(new ExtensionAppModelBuilder(controller_.get()));
128     builder_->InitializeWithProfile(profile_.get(), model_.get());
129   }
130
131   void ResetBuilder() {
132     builder_.reset();
133     controller_.reset();
134     model_.reset();
135   }
136
137   scoped_ptr<app_list::AppListModel> model_;
138   scoped_ptr<TestAppListControllerDelegate> controller_;
139   scoped_ptr<ExtensionAppModelBuilder> builder_;
140
141   base::ScopedTempDir second_profile_temp_dir_;
142
143  private:
144   DISALLOW_COPY_AND_ASSIGN(ExtensionAppModelBuilderTest);
145 };
146
147 TEST_F(ExtensionAppModelBuilderTest, Build) {
148   // The apps list would have 3 extension apps in the profile.
149   EXPECT_EQ(kDefaultAppCount, model_->top_level_item_list()->item_count());
150   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
151 }
152
153 TEST_F(ExtensionAppModelBuilderTest, HideWebStore) {
154   // Install a "web store" app.
155   scoped_refptr<extensions::Extension> store =
156       MakeApp("webstore",
157               "0.0",
158               "http://google.com",
159               std::string(extension_misc::kWebStoreAppId));
160   service_->AddExtension(store.get());
161
162   // Install an "enterprise web store" app.
163   scoped_refptr<extensions::Extension> enterprise_store =
164       MakeApp("enterprise_webstore",
165               "0.0",
166               "http://google.com",
167               std::string(extension_misc::kEnterpriseWebStoreAppId));
168   service_->AddExtension(enterprise_store.get());
169
170   // Web stores should be present in the AppListModel.
171   app_list::AppListModel model1;
172   ExtensionAppModelBuilder builder1(controller_.get());
173   builder1.InitializeWithProfile(profile_.get(), &model1);
174   EXPECT_TRUE(model1.FindItem(store->id()));
175   EXPECT_TRUE(model1.FindItem(enterprise_store->id()));
176
177   // Activate the HideWebStoreIcon policy.
178   profile_->GetPrefs()->SetBoolean(prefs::kHideWebStoreIcon, true);
179
180   // Now the web stores should not be present anymore.
181   EXPECT_FALSE(model1.FindItem(store->id()));
182   EXPECT_FALSE(model1.FindItem(enterprise_store->id()));
183
184   // Build a new AppListModel; web stores should NOT be present.
185   app_list::AppListModel model2;
186   ExtensionAppModelBuilder builder2(controller_.get());
187   builder2.InitializeWithProfile(profile_.get(), &model2);
188   EXPECT_FALSE(model2.FindItem(store->id()));
189   EXPECT_FALSE(model2.FindItem(enterprise_store->id()));
190
191   // Deactivate the HideWebStoreIcon policy again.
192   profile_->GetPrefs()->SetBoolean(prefs::kHideWebStoreIcon, false);
193
194   // Now the web stores should have appeared.
195   EXPECT_TRUE(model2.FindItem(store->id()));
196   EXPECT_TRUE(model2.FindItem(enterprise_store->id()));
197 }
198
199 TEST_F(ExtensionAppModelBuilderTest, DisableAndEnable) {
200   service_->DisableExtension(kHostedAppId,
201                              extensions::Extension::DISABLE_NONE);
202   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
203
204   service_->EnableExtension(kHostedAppId);
205   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
206 }
207
208 TEST_F(ExtensionAppModelBuilderTest, Uninstall) {
209   service_->UninstallExtension(kPackagedApp2Id,
210                                extensions::UNINSTALL_REASON_FOR_TESTING,
211                                base::Bind(&base::DoNothing),
212                                NULL);
213   EXPECT_EQ(std::string("Packaged App 1,Hosted App"),
214             GetModelContent(model_.get()));
215
216   base::RunLoop().RunUntilIdle();
217 }
218
219 TEST_F(ExtensionAppModelBuilderTest, UninstallTerminatedApp) {
220   const extensions::Extension* app =
221       service_->GetInstalledExtension(kPackagedApp2Id);
222   ASSERT_TRUE(app != NULL);
223
224   // Simulate an app termination.
225   service_->TrackTerminatedExtensionForTest(app);
226
227   service_->UninstallExtension(kPackagedApp2Id,
228                                extensions::UNINSTALL_REASON_FOR_TESTING,
229                                base::Bind(&base::DoNothing),
230                                NULL);
231   EXPECT_EQ(std::string("Packaged App 1,Hosted App"),
232             GetModelContent(model_.get()));
233
234   base::RunLoop().RunUntilIdle();
235 }
236
237 TEST_F(ExtensionAppModelBuilderTest, Reinstall) {
238   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
239
240   // Install kPackagedApp1Id again should not create a new entry.
241   extensions::InstallTracker* tracker =
242       extensions::InstallTrackerFactory::GetForBrowserContext(profile_.get());
243   extensions::InstallObserver::ExtensionInstallParams params(
244       kPackagedApp1Id, "", gfx::ImageSkia(), true, true);
245   tracker->OnBeginExtensionInstall(params);
246
247   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
248 }
249
250 TEST_F(ExtensionAppModelBuilderTest, OrdinalPrefsChange) {
251   extensions::AppSorting* sorting =
252       extensions::ExtensionPrefs::Get(profile_.get())->app_sorting();
253
254   syncer::StringOrdinal package_app_page =
255       sorting->GetPageOrdinal(kPackagedApp1Id);
256   sorting->SetPageOrdinal(kHostedAppId, package_app_page.CreateBefore());
257   // Old behavior: This would be "Hosted App,Packaged App 1,Packaged App 2"
258   // New behavior: Sorting order doesn't change.
259   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
260
261   syncer::StringOrdinal app1_ordinal =
262       sorting->GetAppLaunchOrdinal(kPackagedApp1Id);
263   syncer::StringOrdinal app2_ordinal =
264       sorting->GetAppLaunchOrdinal(kPackagedApp2Id);
265   sorting->SetPageOrdinal(kHostedAppId, package_app_page);
266   sorting->SetAppLaunchOrdinal(kHostedAppId,
267                                app1_ordinal.CreateBetween(app2_ordinal));
268   // Old behavior: This would be "Packaged App 1,Hosted App,Packaged App 2"
269   // New behavior: Sorting order doesn't change.
270   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
271 }
272
273 TEST_F(ExtensionAppModelBuilderTest, OnExtensionMoved) {
274   extensions::AppSorting* sorting =
275       extensions::ExtensionPrefs::Get(profile_.get())->app_sorting();
276   sorting->SetPageOrdinal(kHostedAppId,
277                           sorting->GetPageOrdinal(kPackagedApp1Id));
278
279   sorting->OnExtensionMoved(kHostedAppId, kPackagedApp1Id, kPackagedApp2Id);
280   // Old behavior: This would be "Packaged App 1,Hosted App,Packaged App 2"
281   // New behavior: Sorting order doesn't change.
282   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
283
284   sorting->OnExtensionMoved(kHostedAppId, kPackagedApp2Id, std::string());
285   // Old behavior: This would be restored to the default order.
286   // New behavior: Sorting order still doesn't change.
287   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
288
289   sorting->OnExtensionMoved(kHostedAppId, std::string(), kPackagedApp1Id);
290   // Old behavior: This would be "Hosted App,Packaged App 1,Packaged App 2"
291   // New behavior: Sorting order doesn't change.
292   EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get()));
293 }
294
295 TEST_F(ExtensionAppModelBuilderTest, InvalidOrdinal) {
296   // Creates a no-ordinal case.
297   extensions::AppSorting* sorting =
298       extensions::ExtensionPrefs::Get(profile_.get())->app_sorting();
299   sorting->ClearOrdinals(kPackagedApp1Id);
300
301   // Creates a corrupted ordinal case.
302   extensions::ExtensionScopedPrefs* scoped_prefs =
303       extensions::ExtensionPrefs::Get(profile_.get());
304   scoped_prefs->UpdateExtensionPref(
305       kHostedAppId,
306       "page_ordinal",
307       new base::StringValue("a corrupted ordinal"));
308
309   // This should not assert or crash.
310   CreateBuilder();
311 }
312
313 TEST_F(ExtensionAppModelBuilderTest, OrdinalConfilicts) {
314   // Creates conflict ordinals for app1 and app2.
315   syncer::StringOrdinal conflict_ordinal =
316       syncer::StringOrdinal::CreateInitialOrdinal();
317
318   extensions::AppSorting* sorting =
319       extensions::ExtensionPrefs::Get(profile_.get())->app_sorting();
320   sorting->SetPageOrdinal(kHostedAppId, conflict_ordinal);
321   sorting->SetAppLaunchOrdinal(kHostedAppId, conflict_ordinal);
322
323   sorting->SetPageOrdinal(kPackagedApp1Id, conflict_ordinal);
324   sorting->SetAppLaunchOrdinal(kPackagedApp1Id, conflict_ordinal);
325
326   sorting->SetPageOrdinal(kPackagedApp2Id, conflict_ordinal);
327   sorting->SetAppLaunchOrdinal(kPackagedApp2Id, conflict_ordinal);
328
329   // This should not assert or crash.
330   CreateBuilder();
331
332   // By default, conflicted items are sorted by their app ids (= order added).
333   EXPECT_EQ(std::string("Hosted App,Packaged App 1,Packaged App 2"),
334             GetModelContent(model_.get()));
335 }
336
337 // This test adds a bookmark app to the app list.
338 TEST_F(ExtensionAppModelBuilderTest, BookmarkApp) {
339   const std::string kAppName = "Bookmark App";
340   const std::string kAppVersion = "2014.1.24.19748";
341   const std::string kAppUrl = "http://google.com";
342   const std::string kAppId = "podhdnefolignjhecmjkbimfgioanahm";
343   std::string err;
344   base::DictionaryValue value;
345   value.SetString("name", kAppName);
346   value.SetString("version", kAppVersion);
347   value.SetString("app.launch.web_url", kAppUrl);
348   scoped_refptr<extensions::Extension> bookmark_app =
349       extensions::Extension::Create(
350           base::FilePath(),
351           extensions::Manifest::INTERNAL,
352           value,
353           extensions::Extension::WAS_INSTALLED_BY_DEFAULT |
354               extensions::Extension::FROM_BOOKMARK,
355           kAppId,
356           &err);
357   EXPECT_TRUE(err.empty());
358
359   service_->AddExtension(bookmark_app.get());
360   EXPECT_EQ(kDefaultAppCount + 1, model_->top_level_item_list()->item_count());
361   EXPECT_NE(std::string::npos, GetModelContent(model_.get()).find(kAppName));
362 }