15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/app_list/extension_app_model_builder.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/run_loop.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_function_test_utils.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/extensions/install_tracker.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/extensions/install_tracker_factory.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_controller_delegate_impl.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_test_util.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h" 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/app_sorting.h" 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/uninstall_reason.h" 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/constants.h" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h" 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_item.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get a string of all apps in |model| joined with ','. 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::string GetModelContent(app_list::AppListModel* model) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string content; 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < model->top_level_item_list()->item_count(); ++i) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i > 0) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content += ','; 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content += model->top_level_item_list()->item_at(i)->name(); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return content; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<extensions::Extension> MakeApp(const std::string& name, 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& version, 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& url, 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& id) { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string err; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue value; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) value.SetString("name", name); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) value.SetString("version", version); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) value.SetString("app.launch.web_url", url); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<extensions::Extension> app = 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::Extension::Create( 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath(), 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::Manifest::INTERNAL, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) value, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::Extension::WAS_INSTALLED_BY_DEFAULT, 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) id, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &err); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(err, ""); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return app; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class TestAppListControllerDelegate : public AppListControllerDelegate { 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public: 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual ~TestAppListControllerDelegate() {} 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void DismissView() OVERRIDE {} 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual gfx::NativeWindow GetAppListWindow() OVERRIDE { return NULL; } 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual gfx::ImageSkia GetWindowIcon() OVERRIDE { return gfx::ImageSkia(); } 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual bool IsAppPinned(const std::string& extension_id) OVERRIDE { 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void PinApp(const std::string& extension_id) OVERRIDE {} 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void UnpinApp(const std::string& extension_id) OVERRIDE {} 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual Pinnable GetPinnable() OVERRIDE { return NO_PIN; } 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual bool CanDoCreateShortcutsFlow() OVERRIDE { return false; } 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void DoCreateShortcutsFlow(Profile* profile, 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& extension_id) OVERRIDE { 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual bool CanDoShowAppInfoFlow() OVERRIDE { return false; } 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void DoShowAppInfoFlow(Profile* profile, 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extension_id) OVERRIDE { 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void CreateNewWindow(Profile* profile, bool incognito) OVERRIDE {} 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void ActivateApp(Profile* profile, 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const extensions::Extension* extension, 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AppListSource source, 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int event_flags) OVERRIDE {} 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void LaunchApp(Profile* profile, 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const extensions::Extension* extension, 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AppListSource source, 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int event_flags) OVERRIDE {} 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void ShowForProfileByPath( 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::FilePath& profile_path) OVERRIDE {} 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual bool ShouldShowUserIcon() OVERRIDE { return false; } 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kDefaultApps[] = "Packaged App 1,Packaged App 2,Hosted App"; 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kDefaultAppCount = 3u; 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ExtensionAppModelBuilderTest : public AppListTestBase { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ExtensionAppModelBuilderTest() {} 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual ~ExtensionAppModelBuilderTest() {} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() OVERRIDE { 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AppListTestBase::SetUp(); 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateBuilder(); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void TearDown() OVERRIDE { 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ResetBuilder(); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected: 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Creates a new builder, destroying any existing one. 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void CreateBuilder() { 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ResetBuilder(); // Destroy any existing builder in the correct order. 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) model_.reset(new app_list::AppListModel); 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_.reset(new TestAppListControllerDelegate); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) builder_.reset(new ExtensionAppModelBuilder(controller_.get())); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) builder_->InitializeWithProfile(profile_.get(), model_.get()); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void ResetBuilder() { 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) builder_.reset(); 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_.reset(); 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) model_.reset(); 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<app_list::AppListModel> model_; 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<TestAppListControllerDelegate> controller_; 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ExtensionAppModelBuilder> builder_; 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::ScopedTempDir second_profile_temp_dir_; 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private: 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExtensionAppModelBuilderTest); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, Build) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The apps list would have 3 extension apps in the profile. 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(kDefaultAppCount, model_->top_level_item_list()->item_count()); 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, HideWebStore) { 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Install a "web store" app. 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<extensions::Extension> store = 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MakeApp("webstore", 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "0.0", 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "http://google.com", 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string(extensions::kWebStoreAppId)); 1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) service_->AddExtension(store.get()); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Install an "enterprise web store" app. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<extensions::Extension> enterprise_store = 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MakeApp("enterprise_webstore", 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "0.0", 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "http://google.com", 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string(extension_misc::kEnterpriseWebStoreAppId)); 1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) service_->AddExtension(enterprise_store.get()); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Web stores should be present in the AppListModel. 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) app_list::AppListModel model1; 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionAppModelBuilder builder1(controller_.get()); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) builder1.InitializeWithProfile(profile_.get(), &model1); 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(model1.FindItem(store->id())); 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(model1.FindItem(enterprise_store->id())); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Activate the HideWebStoreIcon policy. 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) profile_->GetPrefs()->SetBoolean(prefs::kHideWebStoreIcon, true); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Now the web stores should not be present anymore. 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_FALSE(model1.FindItem(store->id())); 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_FALSE(model1.FindItem(enterprise_store->id())); 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Build a new AppListModel; web stores should NOT be present. 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) app_list::AppListModel model2; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionAppModelBuilder builder2(controller_.get()); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) builder2.InitializeWithProfile(profile_.get(), &model2); 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_FALSE(model2.FindItem(store->id())); 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_FALSE(model2.FindItem(enterprise_store->id())); 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Deactivate the HideWebStoreIcon policy again. 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) profile_->GetPrefs()->SetBoolean(prefs::kHideWebStoreIcon, false); 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Now the web stores should have appeared. 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(model2.FindItem(store->id())); 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(model2.FindItem(enterprise_store->id())); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, DisableAndEnable) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->DisableExtension(kHostedAppId, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::Extension::DISABLE_NONE); 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->EnableExtension(kHostedAppId); 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, Uninstall) { 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) service_->UninstallExtension(kPackagedApp2Id, 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UNINSTALL_REASON_FOR_TESTING, 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&base::DoNothing), 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL); 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(std::string("Packaged App 1,Hosted App"), 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GetModelContent(model_.get())); 2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::RunLoop().RunUntilIdle(); 2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, UninstallTerminatedApp) { 2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const extensions::Extension* app = 2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch service_->GetInstalledExtension(kPackagedApp2Id); 2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(app != NULL); 2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Simulate an app termination. 2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch service_->TrackTerminatedExtensionForTest(app); 2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) service_->UninstallExtension(kPackagedApp2Id, 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UNINSTALL_REASON_FOR_TESTING, 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&base::DoNothing), 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL); 2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(std::string("Packaged App 1,Hosted App"), 2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GetModelContent(model_.get())); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::RunLoop().RunUntilIdle(); 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, Reinstall) { 2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Install kPackagedApp1Id again should not create a new entry. 2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) extensions::InstallTracker* tracker = 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::InstallTrackerFactory::GetForBrowserContext(profile_.get()); 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::InstallObserver::ExtensionInstallParams params( 2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kPackagedApp1Id, "", gfx::ImageSkia(), true, true); 246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) tracker->OnBeginExtensionInstall(params); 2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, OrdinalPrefsChange) { 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::AppSorting* sorting = 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::ExtensionPrefs::Get(profile_.get())->app_sorting(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::StringOrdinal package_app_page = 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorting->GetPageOrdinal(kPackagedApp1Id); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorting->SetPageOrdinal(kHostedAppId, package_app_page.CreateBefore()); 2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Old behavior: This would be "Hosted App,Packaged App 1,Packaged App 2" 2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // New behavior: Sorting order doesn't change. 2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::StringOrdinal app1_ordinal = 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorting->GetAppLaunchOrdinal(kPackagedApp1Id); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::StringOrdinal app2_ordinal = 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorting->GetAppLaunchOrdinal(kPackagedApp2Id); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorting->SetPageOrdinal(kHostedAppId, package_app_page); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorting->SetAppLaunchOrdinal(kHostedAppId, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app1_ordinal.CreateBetween(app2_ordinal)); 2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Old behavior: This would be "Packaged App 1,Hosted App,Packaged App 2" 2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // New behavior: Sorting order doesn't change. 2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, OnExtensionMoved) { 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::AppSorting* sorting = 276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::ExtensionPrefs::Get(profile_.get())->app_sorting(); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorting->SetPageOrdinal(kHostedAppId, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorting->GetPageOrdinal(kPackagedApp1Id)); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) sorting->OnExtensionMoved(kHostedAppId, kPackagedApp1Id, kPackagedApp2Id); 2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Old behavior: This would be "Packaged App 1,Hosted App,Packaged App 2" 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // New behavior: Sorting order doesn't change. 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) sorting->OnExtensionMoved(kHostedAppId, kPackagedApp2Id, std::string()); 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Old behavior: This would be restored to the default order. 2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // New behavior: Sorting order still doesn't change. 2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) sorting->OnExtensionMoved(kHostedAppId, std::string(), kPackagedApp1Id); 2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Old behavior: This would be "Hosted App,Packaged App 1,Packaged App 2" 2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // New behavior: Sorting order doesn't change. 2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(std::string(kDefaultApps), GetModelContent(model_.get())); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, InvalidOrdinal) { 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creates a no-ordinal case. 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::AppSorting* sorting = 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::ExtensionPrefs::Get(profile_.get())->app_sorting(); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sorting->ClearOrdinals(kPackagedApp1Id); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Creates a corrupted ordinal case. 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::ExtensionScopedPrefs* scoped_prefs = 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::ExtensionPrefs::Get(profile_.get()); 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_prefs->UpdateExtensionPref( 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kHostedAppId, 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "page_ordinal", 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new base::StringValue("a corrupted ordinal")); 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This should not assert or crash. 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateBuilder(); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, OrdinalConfilicts) { 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creates conflict ordinals for app1 and app2. 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::StringOrdinal conflict_ordinal = 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::StringOrdinal::CreateInitialOrdinal(); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::AppSorting* sorting = 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extensions::ExtensionPrefs::Get(profile_.get())->app_sorting(); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sorting->SetPageOrdinal(kHostedAppId, conflict_ordinal); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sorting->SetAppLaunchOrdinal(kHostedAppId, conflict_ordinal); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sorting->SetPageOrdinal(kPackagedApp1Id, conflict_ordinal); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sorting->SetAppLaunchOrdinal(kPackagedApp1Id, conflict_ordinal); 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sorting->SetPageOrdinal(kPackagedApp2Id, conflict_ordinal); 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sorting->SetAppLaunchOrdinal(kPackagedApp2Id, conflict_ordinal); 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // This should not assert or crash. 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateBuilder(); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // By default, conflicted items are sorted by their app ids (= order added). 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(std::string("Hosted App,Packaged App 1,Packaged App 2"), 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GetModelContent(model_.get())); 3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This test adds a bookmark app to the app list. 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ExtensionAppModelBuilderTest, BookmarkApp) { 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string kAppName = "Bookmark App"; 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string kAppVersion = "2014.1.24.19748"; 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string kAppUrl = "http://google.com"; 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string kAppId = "podhdnefolignjhecmjkbimfgioanahm"; 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string err; 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue value; 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) value.SetString("name", kAppName); 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) value.SetString("version", kAppVersion); 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) value.SetString("app.launch.web_url", kAppUrl); 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<extensions::Extension> bookmark_app = 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::Extension::Create( 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath(), 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::Manifest::INTERNAL, 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) value, 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::Extension::WAS_INSTALLED_BY_DEFAULT | 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::Extension::FROM_BOOKMARK, 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kAppId, 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &err); 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(err.empty()); 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) service_->AddExtension(bookmark_app.get()); 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(kDefaultAppCount + 1, model_->top_level_item_list()->item_count()); 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_NE(std::string::npos, GetModelContent(model_.get()).find(kAppName)); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 364