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.
5 #include "chrome/browser/sync/test/integration/sync_app_helper.h"
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"
23 using extensions::ExtensionPrefs
;
31 bool Equals(const AppState
& other
) const;
33 syncer::StringOrdinal app_launch_ordinal
;
34 syncer::StringOrdinal page_ordinal
;
35 extensions::LaunchType launch_type
;
37 std::string description
;
42 typedef std::map
<std::string
, AppState
> AppStateMap
;
45 : launch_type(extensions::LAUNCH_TYPE_INVALID
), from_bookmark(false) {}
47 AppState::~AppState() {}
49 bool AppState::IsValid() const {
50 return page_ordinal
.IsValid() && app_launch_ordinal
.IsValid();
53 bool AppState::Equals(const AppState
& other
) const {
54 return app_launch_ordinal
.Equals(other
.app_launch_ordinal
) &&
55 page_ordinal
.Equals(other
.page_ordinal
) &&
56 launch_type
== other
.launch_type
&&
57 launch_web_url
== other
.launch_web_url
&&
58 description
== other
.description
&& name
== other
.name
&&
59 from_bookmark
== other
.from_bookmark
;
62 // Load all the app specific values for |id| into |app_state|.
63 void LoadApp(content::BrowserContext
* context
,
64 const std::string
& id
,
65 AppState
* app_state
) {
66 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
67 app_state
->app_launch_ordinal
= prefs
->app_sorting()->GetAppLaunchOrdinal(id
);
68 app_state
->page_ordinal
= prefs
->app_sorting()->GetPageOrdinal(id
);
69 app_state
->launch_type
= extensions::GetLaunchTypePrefValue(prefs
, id
);
70 ExtensionService
* service
=
71 extensions::ExtensionSystem::Get(context
)->extension_service();
72 const extensions::Extension
* extension
= service
->GetInstalledExtension(id
);
73 // GetInstalledExtension(id) returns null if |id| is for a pending extension.
74 // In case of running tests against real backend servers, pending apps won't
77 app_state
->launch_web_url
=
78 extensions::AppLaunchInfo::GetLaunchWebURL(extension
);
79 app_state
->description
= extension
->description();
80 app_state
->name
= extension
->name();
81 app_state
->from_bookmark
= extension
->from_bookmark();
85 // Returns a map from |profile|'s installed extensions to their state.
86 AppStateMap
GetAppStates(Profile
* profile
) {
87 AppStateMap app_state_map
;
89 scoped_ptr
<const extensions::ExtensionSet
> extensions(
90 extensions::ExtensionRegistry::Get(profile
)
91 ->GenerateInstalledExtensionsSet());
92 for (const auto& extension
: *extensions
) {
93 if (extension
->is_app() &&
94 extensions::sync_helper::IsSyncable(extension
.get())) {
95 const std::string
& id
= extension
->id();
96 LoadApp(profile
, id
, &(app_state_map
[id
]));
100 const extensions::PendingExtensionManager
* pending_extension_manager
=
101 extensions::ExtensionSystem::Get(profile
)
102 ->extension_service()
103 ->pending_extension_manager();
105 std::list
<std::string
> pending_crx_ids
;
106 pending_extension_manager
->GetPendingIdsForUpdateCheck(&pending_crx_ids
);
108 for (std::list
<std::string
>::const_iterator id
= pending_crx_ids
.begin();
109 id
!= pending_crx_ids
.end(); ++id
) {
110 LoadApp(profile
, *id
, &(app_state_map
[*id
]));
113 return app_state_map
;
118 SyncAppHelper
* SyncAppHelper::GetInstance() {
119 SyncAppHelper
* instance
= base::Singleton
<SyncAppHelper
>::get();
120 instance
->SetupIfNecessary(sync_datatype_helper::test());
124 void SyncAppHelper::SetupIfNecessary(SyncTest
* test
) {
125 if (setup_completed_
)
128 for (int i
= 0; i
< test
->num_clients(); ++i
) {
129 extensions::ExtensionSystem::Get(
130 test
->GetProfile(i
))->InitForRegularProfile(true);
132 if (test
->use_verifier()) {
133 extensions::ExtensionSystem::Get(test
->verifier())
134 ->InitForRegularProfile(true);
137 setup_completed_
= true;
140 bool SyncAppHelper::AppStatesMatch(Profile
* profile1
, Profile
* profile2
) {
141 if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
145 const AppStateMap
& state_map1
= GetAppStates(profile1
);
146 const AppStateMap
& state_map2
= GetAppStates(profile2
);
147 if (state_map1
.size() != state_map2
.size()) {
148 DVLOG(2) << "Number of Apps for profile " << profile1
->GetDebugName()
149 << " does not match profile " << profile2
->GetDebugName();
153 AppStateMap::const_iterator it1
= state_map1
.begin();
154 AppStateMap::const_iterator it2
= state_map2
.begin();
155 while (it1
!= state_map1
.end()) {
156 if (it1
->first
!= it2
->first
) {
157 DVLOG(2) << "Apps for profile " << profile1
->GetDebugName()
158 << " do not match profile " << profile2
->GetDebugName();
160 } else if (!it1
->second
.IsValid()) {
161 DVLOG(2) << "Apps for profile " << profile1
->GetDebugName()
162 << " are not valid.";
164 } else if (!it2
->second
.IsValid()) {
165 DVLOG(2) << "Apps for profile " << profile2
->GetDebugName()
166 << " are not valid.";
168 } else if (!sync_datatype_helper::test()->UsingExternalServers() &&
169 !it1
->second
.Equals(it2
->second
)) {
170 // If this test is run against real backend servers then we do not expect
171 // to install pending apps. So, we don't check equality of AppStates of
172 // each app per profile.
173 DVLOG(2) << "App states for profile " << profile1
->GetDebugName()
174 << " do not match profile " << profile2
->GetDebugName();
184 syncer::StringOrdinal
SyncAppHelper::GetPageOrdinalForApp(
186 const std::string
& name
) {
187 return ExtensionPrefs::Get(profile
)->app_sorting()->GetPageOrdinal(
188 crx_file::id_util::GenerateId(name
));
191 void SyncAppHelper::SetPageOrdinalForApp(
193 const std::string
& name
,
194 const syncer::StringOrdinal
& page_ordinal
) {
195 ExtensionPrefs::Get(profile
)->app_sorting()->SetPageOrdinal(
196 crx_file::id_util::GenerateId(name
), page_ordinal
);
199 syncer::StringOrdinal
SyncAppHelper::GetAppLaunchOrdinalForApp(
201 const std::string
& name
) {
202 return ExtensionPrefs::Get(profile
)->app_sorting()->GetAppLaunchOrdinal(
203 crx_file::id_util::GenerateId(name
));
206 void SyncAppHelper::SetAppLaunchOrdinalForApp(
208 const std::string
& name
,
209 const syncer::StringOrdinal
& app_launch_ordinal
) {
210 ExtensionPrefs::Get(profile
)->app_sorting()->SetAppLaunchOrdinal(
211 crx_file::id_util::GenerateId(name
), app_launch_ordinal
);
214 void SyncAppHelper::FixNTPOrdinalCollisions(Profile
* profile
) {
215 ExtensionPrefs::Get(profile
)->app_sorting()->FixNTPOrdinalCollisions();
218 SyncAppHelper::SyncAppHelper() : setup_completed_(false) {}
220 SyncAppHelper::~SyncAppHelper() {}