- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / extension_sorting.h
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 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_SORTING_H_
6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_SORTING_H_
7
8 #include <map>
9 #include <set>
10 #include <string>
11
12 #include "base/basictypes.h"
13 #include "chrome/browser/extensions/extension_prefs.h"
14 #include "chrome/common/extensions/extension.h"
15 #include "sync/api/string_ordinal.h"
16
17 class ExtensionScopedPrefs;
18 class ExtensionSyncService;
19 class PrefService;
20
21 class ExtensionSorting {
22  public:
23   explicit ExtensionSorting(ExtensionScopedPrefs* extension_scoped_prefs);
24   ~ExtensionSorting();
25
26   // Set up the ExtensionSyncService to inform of changes that require syncing.
27   void SetExtensionSyncService(ExtensionSyncService* extension_sync_service);
28
29   // Properly initialize ExtensionSorting internal values that require
30   // |extension_ids|.
31   void Initialize(
32       const extensions::ExtensionIdList& extension_ids);
33
34   // Resolves any conflicts the might be created as a result of syncing that
35   // results in two icons having the same page and app launch ordinal. After
36   // this is called it is guaranteed that there are no collisions of NTP icons.
37   void FixNTPOrdinalCollisions();
38
39   // This ensures that the extension has valid ordinals, and if it doesn't then
40   // properly initialize them. |suggested_page| will be used if it is valid and
41   // the extension has no valid user-set page ordinal.
42   void EnsureValidOrdinals(const std::string& extension_id,
43                            const syncer::StringOrdinal& suggested_page);
44
45   // Updates the app launcher value for the moved extension so that it is now
46   // located after the given predecessor and before the successor.
47   // Empty strings are used to indicate no successor or predecessor.
48   void OnExtensionMoved(const std::string& moved_extension_id,
49                         const std::string& predecessor_extension_id,
50                         const std::string& successor_extension_id);
51
52   // Get the application launch ordinal for an app with |extension_id|. This
53   // determines the order in which the app appears on the page it's on in the
54   // New Tab Page (Note that you can compare app launch ordinals only if the
55   // apps are on the same page). A string value close to |a*| generally
56   // indicates top left. If the extension has no launch ordinal, an invalid
57   // StringOrdinal is returned.
58   syncer::StringOrdinal GetAppLaunchOrdinal(
59       const std::string& extension_id) const;
60
61   // Sets a specific launch ordinal for an app with |extension_id|.
62   void SetAppLaunchOrdinal(const std::string& extension_id,
63                            const syncer::StringOrdinal& new_app_launch_ordinal);
64
65   // Returns a StringOrdinal that is lower than any app launch ordinal for the
66   // given page.
67   syncer::StringOrdinal CreateFirstAppLaunchOrdinal(
68       const syncer::StringOrdinal& page_ordinal) const;
69
70   // Returns a StringOrdinal that is higher than any app launch ordinal for the
71   // given page.
72   syncer::StringOrdinal CreateNextAppLaunchOrdinal(
73       const syncer::StringOrdinal& page_ordinal) const;
74
75   // Returns a StringOrdinal that is lower than any existing page ordinal.
76   syncer::StringOrdinal CreateFirstAppPageOrdinal() const;
77
78   // Gets the page a new app should install to, which is the earliest non-full
79   // page.  The returned ordinal may correspond to a page that doesn't yet exist
80   // if all pages are full.
81   syncer::StringOrdinal GetNaturalAppPageOrdinal() const;
82
83   // Get the page ordinal for an app with |extension_id|. This determines
84   // which page an app will appear on in page-based NTPs.  If the app has no
85   // page specified, an invalid StringOrdinal is returned.
86   syncer::StringOrdinal GetPageOrdinal(const std::string& extension_id) const;
87
88   // Sets a specific page ordinal for an app with |extension_id|.
89   void SetPageOrdinal(const std::string& extension_id,
90                       const syncer::StringOrdinal& new_page_ordinal);
91
92   // Removes the ordinal values for an app.
93   void ClearOrdinals(const std::string& extension_id);
94
95   // Convert the page StringOrdinal value to its integer equivalent. This takes
96   // O(# of apps) worst-case.
97   int PageStringOrdinalAsInteger(
98       const syncer::StringOrdinal& page_ordinal) const;
99
100   // Converts the page index integer to its StringOrdinal equivalent. This takes
101   // O(# of apps) worst-case.
102   syncer::StringOrdinal PageIntegerAsStringOrdinal(size_t page_index);
103
104   // Hidden extensions don't appear in the new tab page.
105   void MarkExtensionAsHidden(const std::string& extension_id);
106
107  private:
108   // The StringOrdinal is the app launch ordinal and the string is the extension
109   // id.
110   typedef std::multimap<
111       syncer::StringOrdinal, std::string,
112     syncer::StringOrdinal::LessThanFn> AppLaunchOrdinalMap;
113   // The StringOrdinal is the page ordinal and the AppLaunchOrdinalMap is the
114   // contents of that page.
115   typedef std::map<
116       syncer::StringOrdinal, AppLaunchOrdinalMap,
117     syncer::StringOrdinal::LessThanFn> PageOrdinalMap;
118
119   // Unit tests.
120   friend class ExtensionSortingDefaultOrdinalsBase;
121   friend class ExtensionSortingGetMinOrMaxAppLaunchOrdinalsOnPage;
122   friend class ExtensionSortingInitializeWithNoApps;
123   friend class ExtensionSortingPageOrdinalMapping;
124
125   // An enum used by GetMinOrMaxAppLaunchOrdinalsOnPage to specify which
126   // value should be returned.
127   enum AppLaunchOrdinalReturn {MIN_ORDINAL, MAX_ORDINAL};
128
129   // Maps an app id to its ordinals.
130   struct AppOrdinals {
131     AppOrdinals();
132     ~AppOrdinals();
133
134     syncer::StringOrdinal page_ordinal;
135     syncer::StringOrdinal app_launch_ordinal;
136   };
137   typedef std::map<std::string, AppOrdinals> AppOrdinalsMap;
138
139   // This function returns the lowest ordinal on |page_ordinal| if
140   // |return_value| == AppLaunchOrdinalReturn::MIN_ORDINAL, otherwise it returns
141   // the largest ordinal on |page_ordinal|. If there are no apps on the page
142   // then an invalid StringOrdinal is returned. It is an error to call this
143   // function with an invalid |page_ordinal|.
144   syncer::StringOrdinal GetMinOrMaxAppLaunchOrdinalsOnPage(
145       const syncer::StringOrdinal& page_ordinal,
146       AppLaunchOrdinalReturn return_type) const;
147
148   // Initialize the |page_ordinal_map_| with the page ordinals used by the
149   // given extensions.
150   void InitializePageOrdinalMap(
151       const extensions::ExtensionIdList& extension_ids);
152
153   // Migrates the app launcher and page index values.
154   void MigrateAppIndex(
155       const extensions::ExtensionIdList& extension_ids);
156
157   // Called to add a new mapping value for |extension_id| with a page ordinal
158   // of |page_ordinal| and a app launch ordinal of |app_launch_ordinal|. This
159   // works with valid and invalid StringOrdinals.
160   void AddOrdinalMapping(const std::string& extension_id,
161                          const syncer::StringOrdinal& page_ordinal,
162                          const syncer::StringOrdinal& app_launch_ordinal);
163
164   // Ensures |ntp_ordinal_map_| is of |minimum_size| number of entries.
165   void CreateOrdinalsIfNecessary(size_t minimum_size);
166
167   // Removes the mapping for |extension_id| with a page ordinal of
168   // |page_ordinal| and a app launch ordinal of |app_launch_ordinal|. If there
169   // is not matching map, nothing happens. This works with valid and invalid
170   // StringOrdinals.
171   void RemoveOrdinalMapping(const std::string& extension_id,
172                             const syncer::StringOrdinal& page_ordinal,
173                             const syncer::StringOrdinal& app_launch_ordinal);
174
175   // Syncs the extension if needed. It is an error to call this if the
176   // extension is not an application.
177   void SyncIfNeeded(const std::string& extension_id);
178
179   // Creates the default ordinals.
180   void CreateDefaultOrdinals();
181
182   // Gets the default ordinals for |extension_id|. Returns false if no default
183   // ordinals for |extension_id| is defined. Otherwise, returns true and
184   // ordinals is updated with corresponding ordinals.
185   bool GetDefaultOrdinals(const std::string& extension_id,
186                           syncer::StringOrdinal* page_ordinal,
187                           syncer::StringOrdinal* app_launch_ordinal);
188
189   // Returns |app_launch_ordinal| if it has no collision in the page specified
190   // by |page_ordinal|. Otherwise, returns an ordinal after |app_launch_ordinal|
191   // that has no conflict.
192   syncer::StringOrdinal ResolveCollision(
193       const syncer::StringOrdinal& page_ordinal,
194       const syncer::StringOrdinal& app_launch_ordinal) const;
195
196   // Returns the number of items in |m| visible on the new tab page.
197   size_t CountItemsVisibleOnNtp(const AppLaunchOrdinalMap& m) const;
198
199   ExtensionScopedPrefs* extension_scoped_prefs_;  // Weak, owns this instance.
200   ExtensionSyncService* extension_sync_service_;  // Weak.
201
202   // A map of all the StringOrdinal page ordinals mapping to the collections of
203   // app launch ordinals that exist on that page. This is used for mapping
204   // StringOrdinals to their Integer equivalent as well as quick lookup of the
205   // any collision of on the NTP (icons with the same page and same app launch
206   // ordinals). The possiblity of collisions means that a multimap must be used
207   // (although the collisions must all be resolved once all the syncing is
208   // done).
209   PageOrdinalMap ntp_ordinal_map_;
210
211   // Defines the default ordinals.
212   AppOrdinalsMap default_ordinals_;
213
214   // Used to construct the default ordinals once when needed instead of on
215   // construction when the app order may not have been determined.
216   bool default_ordinals_created_;
217
218   // The set of extensions that don't appear in the new tab page.
219   std::set<std::string> ntp_hidden_extensions_;
220
221   DISALLOW_COPY_AND_ASSIGN(ExtensionSorting);
222 };
223
224 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_SORTING_H_