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/sync/test/integration/sync_app_helper.h" 6 7 #include "chrome/browser/extensions/extension_service.h" 8 #include "chrome/browser/extensions/launch_util.h" 9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/sync/test/integration/extensions_helper.h" 11 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h" 12 #include "chrome/browser/sync/test/integration/sync_extension_helper.h" 13 #include "chrome/common/extensions/extension_constants.h" 14 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 15 #include "chrome/common/extensions/sync_helper.h" 16 #include "components/crx_file/id_util.h" 17 #include "extensions/browser/app_sorting.h" 18 #include "extensions/browser/extension_prefs.h" 19 #include "extensions/browser/extension_registry.h" 20 #include "extensions/browser/extension_system.h" 21 #include "extensions/common/extension_set.h" 22 23 using extensions::ExtensionPrefs; 24 25 namespace { 26 27 struct AppState { 28 AppState(); 29 ~AppState(); 30 bool IsValid() const; 31 bool Equals(const AppState& other) const; 32 33 syncer::StringOrdinal app_launch_ordinal; 34 syncer::StringOrdinal page_ordinal; 35 extensions::LaunchType launch_type; 36 GURL launch_web_url; 37 std::string description; 38 std::string name; 39 bool from_bookmark; 40 }; 41 42 typedef std::map<std::string, AppState> AppStateMap; 43 44 AppState::AppState() : launch_type(extensions::LAUNCH_TYPE_INVALID) {} 45 46 AppState::~AppState() {} 47 48 bool AppState::IsValid() const { 49 return page_ordinal.IsValid() && app_launch_ordinal.IsValid(); 50 } 51 52 bool AppState::Equals(const AppState& other) const { 53 return app_launch_ordinal.Equals(other.app_launch_ordinal) && 54 page_ordinal.Equals(other.page_ordinal) && 55 launch_type == other.launch_type && 56 launch_web_url == other.launch_web_url && 57 description == other.description && name == other.name && 58 from_bookmark == other.from_bookmark; 59 } 60 61 // Load all the app specific values for |id| into |app_state|. 62 void LoadApp(content::BrowserContext* context, 63 const std::string& id, 64 AppState* app_state) { 65 ExtensionPrefs* prefs = ExtensionPrefs::Get(context); 66 app_state->app_launch_ordinal = prefs->app_sorting()->GetAppLaunchOrdinal(id); 67 app_state->page_ordinal = prefs->app_sorting()->GetPageOrdinal(id); 68 app_state->launch_type = extensions::GetLaunchTypePrefValue(prefs, id); 69 ExtensionService* service = 70 extensions::ExtensionSystem::Get(context)->extension_service(); 71 const extensions::Extension* extension = service->GetInstalledExtension(id); 72 app_state->launch_web_url = 73 extensions::AppLaunchInfo::GetLaunchWebURL(extension); 74 app_state->description = extension->description(); 75 app_state->name = extension->name(); 76 app_state->from_bookmark = extension->from_bookmark(); 77 } 78 79 // Returns a map from |profile|'s installed extensions to their state. 80 AppStateMap GetAppStates(Profile* profile) { 81 AppStateMap app_state_map; 82 83 scoped_ptr<const extensions::ExtensionSet> extensions( 84 extensions::ExtensionRegistry::Get(profile) 85 ->GenerateInstalledExtensionsSet()); 86 for (extensions::ExtensionSet::const_iterator it = extensions->begin(); 87 it != extensions->end(); ++it) { 88 if (extensions::sync_helper::IsSyncableApp(it->get())) { 89 const std::string& id = (*it)->id(); 90 LoadApp(profile, id, &(app_state_map[id])); 91 } 92 } 93 94 const extensions::PendingExtensionManager* pending_extension_manager = 95 extensions::ExtensionSystem::Get(profile) 96 ->extension_service() 97 ->pending_extension_manager(); 98 99 std::list<std::string> pending_crx_ids; 100 pending_extension_manager->GetPendingIdsForUpdateCheck(&pending_crx_ids); 101 102 for (std::list<std::string>::const_iterator id = pending_crx_ids.begin(); 103 id != pending_crx_ids.end(); ++id) { 104 LoadApp(profile, *id, &(app_state_map[*id])); 105 } 106 107 return app_state_map; 108 } 109 110 } // namespace 111 112 SyncAppHelper* SyncAppHelper::GetInstance() { 113 SyncAppHelper* instance = Singleton<SyncAppHelper>::get(); 114 instance->SetupIfNecessary(sync_datatype_helper::test()); 115 return instance; 116 } 117 118 void SyncAppHelper::SetupIfNecessary(SyncTest* test) { 119 if (setup_completed_) 120 return; 121 122 for (int i = 0; i < test->num_clients(); ++i) { 123 extensions::ExtensionSystem::Get( 124 test->GetProfile(i))->InitForRegularProfile(true); 125 } 126 extensions::ExtensionSystem::Get( 127 test->verifier())->InitForRegularProfile(true); 128 129 setup_completed_ = true; 130 } 131 132 bool SyncAppHelper::AppStatesMatch(Profile* profile1, Profile* profile2) { 133 if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch( 134 profile1, profile2)) 135 return false; 136 137 const AppStateMap& state_map1 = GetAppStates(profile1); 138 const AppStateMap& state_map2 = GetAppStates(profile2); 139 if (state_map1.size() != state_map2.size()) { 140 DVLOG(2) << "Number of Apps for profile " << profile1->GetDebugName() 141 << " does not match profile " << profile2->GetDebugName(); 142 return false; 143 } 144 145 AppStateMap::const_iterator it1 = state_map1.begin(); 146 AppStateMap::const_iterator it2 = state_map2.begin(); 147 while (it1 != state_map1.end()) { 148 if (it1->first != it2->first) { 149 DVLOG(2) << "Apps for profile " << profile1->GetDebugName() 150 << " do not match profile " << profile2->GetDebugName(); 151 return false; 152 } else if (!it1->second.IsValid()) { 153 DVLOG(2) << "Apps for profile " << profile1->GetDebugName() 154 << " are not valid."; 155 return false; 156 } else if (!it2->second.IsValid()) { 157 DVLOG(2) << "Apps for profile " << profile2->GetDebugName() 158 << " are not valid."; 159 return false; 160 } else if (!it1->second.Equals(it2->second)) { 161 DVLOG(2) << "App states for profile " << profile1->GetDebugName() 162 << " do not match profile " << profile2->GetDebugName(); 163 return false; 164 } 165 ++it1; 166 ++it2; 167 } 168 169 return true; 170 } 171 172 syncer::StringOrdinal SyncAppHelper::GetPageOrdinalForApp( 173 Profile* profile, 174 const std::string& name) { 175 return ExtensionPrefs::Get(profile)->app_sorting()->GetPageOrdinal( 176 crx_file::id_util::GenerateId(name)); 177 } 178 179 void SyncAppHelper::SetPageOrdinalForApp( 180 Profile* profile, 181 const std::string& name, 182 const syncer::StringOrdinal& page_ordinal) { 183 ExtensionPrefs::Get(profile)->app_sorting()->SetPageOrdinal( 184 crx_file::id_util::GenerateId(name), page_ordinal); 185 } 186 187 syncer::StringOrdinal SyncAppHelper::GetAppLaunchOrdinalForApp( 188 Profile* profile, 189 const std::string& name) { 190 return ExtensionPrefs::Get(profile)->app_sorting()->GetAppLaunchOrdinal( 191 crx_file::id_util::GenerateId(name)); 192 } 193 194 void SyncAppHelper::SetAppLaunchOrdinalForApp( 195 Profile* profile, 196 const std::string& name, 197 const syncer::StringOrdinal& app_launch_ordinal) { 198 ExtensionPrefs::Get(profile)->app_sorting()->SetAppLaunchOrdinal( 199 crx_file::id_util::GenerateId(name), app_launch_ordinal); 200 } 201 202 void SyncAppHelper::FixNTPOrdinalCollisions(Profile* profile) { 203 ExtensionPrefs::Get(profile)->app_sorting()->FixNTPOrdinalCollisions(); 204 } 205 206 SyncAppHelper::SyncAppHelper() : setup_completed_(false) {} 207 208 SyncAppHelper::~SyncAppHelper() {} 209