Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: chrome/browser/ui/ash/app_list/apps_model_builder.cc

Issue 10871011: Move common app_list delegate code to chrome/browser/ui/app_list. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Unit test file only in chrome Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/ash/app_list/apps_model_builder.h"
6
7 #include "base/i18n/case_conversion.h"
8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/ash/app_list/extension_app_item.h"
13 #include "chrome/common/chrome_notification_types.h"
14 #include "chrome/common/extensions/extension.h"
15 #include "content/public/browser/notification_service.h"
16 #include "ui/base/l10n/l10n_util_collator.h"
17
18 using extensions::Extension;
19
20 namespace {
21
22 const char* kSpecialApps[] = {
23 extension_misc::kChromeAppId,
24 extension_misc::kWebStoreAppId,
25 };
26
27 // ModelItemSortData provides a string key to sort with
28 // l10n_util::StringComparator.
29 struct ModelItemSortData {
30 explicit ModelItemSortData(app_list::AppListItemModel* app)
31 : app(app),
32 key(base::i18n::ToLower(UTF8ToUTF16(app->title()))) {
33 }
34
35 // Needed by StringComparator<Element> in SortVectorWithStringKey, which uses
36 // this method to get a key to sort.
37 const string16& GetStringKey() const {
38 return key;
39 }
40
41 app_list::AppListItemModel* app;
42 string16 key;
43 };
44
45 // Returns true if given |extension_id| is listed in kSpecialApps.
46 bool IsSpecialApp(const std::string& extension_id) {
47 for (size_t i = 0; i < arraysize(kSpecialApps); ++i) {
48 if (extension_id == kSpecialApps[i])
49 return true;
50 }
51
52 return false;
53 }
54
55 } // namespace
56
57 AppsModelBuilder::AppsModelBuilder(Profile* profile,
58 app_list::AppListModel::Apps* model,
59 AppListController* controller)
60 : profile_(profile),
61 controller_(controller),
62 model_(model),
63 special_apps_count_(0) {
64 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
65 content::Source<Profile>(profile_));
66 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
67 content::Source<Profile>(profile_));
68 registrar_.Add(this, chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST,
69 content::Source<Profile>(profile_));
70 }
71
72 AppsModelBuilder::~AppsModelBuilder() {
73 }
74
75 void AppsModelBuilder::Build() {
76 DCHECK(model_ && model_->item_count() == 0);
77 CreateSpecialApps();
78
79 Apps apps;
80 GetExtensionApps(&apps);
81
82 SortAndPopulateModel(apps);
83 HighlightApp();
84 }
85
86 void AppsModelBuilder::SortAndPopulateModel(const Apps& apps) {
87 // Just return if there is nothing to populate.
88 if (apps.empty())
89 return;
90
91 // Sort apps case insensitive alphabetically.
92 std::vector<ModelItemSortData> sorted;
93 for (Apps::const_iterator it = apps.begin(); it != apps.end(); ++it)
94 sorted.push_back(ModelItemSortData(*it));
95
96 l10n_util::SortVectorWithStringKey(g_browser_process->GetApplicationLocale(),
97 &sorted,
98 false /* needs_stable_sort */);
99 for (std::vector<ModelItemSortData>::const_iterator it = sorted.begin();
100 it != sorted.end();
101 ++it) {
102 model_->Add(it->app);
103 }
104 }
105
106 void AppsModelBuilder::InsertItemByTitle(app_list::AppListItemModel* app) {
107 DCHECK(model_);
108
109 icu::Locale locale(g_browser_process->GetApplicationLocale().c_str());
110 UErrorCode error = U_ZERO_ERROR;
111 scoped_ptr<icu::Collator> collator(
112 icu::Collator::createInstance(locale, error));
113 if (U_FAILURE(error))
114 collator.reset();
115
116 l10n_util::StringComparator<string16> c(collator.get());
117 ModelItemSortData data(app);
118 for (size_t i = special_apps_count_; i < model_->item_count(); ++i) {
119 ModelItemSortData current(model_->GetItemAt(i));
120 if (!c(current.key, data.key)) {
121 model_->AddAt(i, app);
122 return;
123 }
124 }
125 model_->Add(app);
126 }
127
128 void AppsModelBuilder::GetExtensionApps(Apps* apps) {
129 DCHECK(profile_);
130 ExtensionService* service = profile_->GetExtensionService();
131 if (!service)
132 return;
133
134 // Get extension apps.
135 const ExtensionSet* extensions = service->extensions();
136 for (ExtensionSet::const_iterator app = extensions->begin();
137 app != extensions->end(); ++app) {
138 if ((*app)->ShouldDisplayInLauncher() &&
139 !IsSpecialApp((*app)->id())) {
140 apps->push_back(new ExtensionAppItem(profile_, *app, controller_));
141 }
142 }
143 }
144
145 void AppsModelBuilder::CreateSpecialApps() {
146 DCHECK(model_ && model_->item_count() == 0);
147
148 bool is_guest_session = Profile::IsGuestSession();
149 ExtensionService* service = profile_->GetExtensionService();
150 DCHECK(service);
151 for (size_t i = 0; i < arraysize(kSpecialApps); ++i) {
152 const std::string extension_id(kSpecialApps[i]);
153 if (is_guest_session && extension_id == extension_misc::kWebStoreAppId)
154 continue;
155
156 const Extension* extension = service->GetInstalledExtension(extension_id);
157 DCHECK(extension);
158
159 model_->Add(new ExtensionAppItem(profile_, extension, controller_));
160 }
161
162 special_apps_count_ = model_->item_count();
163 }
164
165 int AppsModelBuilder::FindApp(const std::string& app_id) {
166 DCHECK(model_);
167 for (size_t i = special_apps_count_; i < model_->item_count(); ++i) {
168 ChromeAppListItem* app =
169 static_cast<ChromeAppListItem*>(model_->GetItemAt(i));
170 if (app->type() != ChromeAppListItem::TYPE_APP)
171 continue;
172
173 ExtensionAppItem* extension_item = static_cast<ExtensionAppItem*>(app);
174 if (extension_item->extension_id() == app_id)
175 return i;
176 }
177
178 return -1;
179 }
180
181 void AppsModelBuilder::HighlightApp() {
182 DCHECK(model_);
183 if (highlight_app_id_.empty())
184 return;
185
186 int index = FindApp(highlight_app_id_);
187 if (index == -1)
188 return;
189
190 model_->GetItemAt(index)->SetHighlighted(true);
191 highlight_app_id_.clear();
192 }
193
194 void AppsModelBuilder::Observe(int type,
195 const content::NotificationSource& source,
196 const content::NotificationDetails& details) {
197 switch (type) {
198 case chrome::NOTIFICATION_EXTENSION_LOADED: {
199 const Extension* extension =
200 content::Details<const Extension>(details).ptr();
201 if (!extension->ShouldDisplayInLauncher())
202 return;
203
204 if (FindApp(extension->id()) != -1)
205 return;
206
207 InsertItemByTitle(new ExtensionAppItem(profile_, extension, controller_));
208 HighlightApp();
209 break;
210 }
211 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
212 const Extension* extension =
213 content::Details<extensions::UnloadedExtensionInfo>(
214 details)->extension;
215 int index = FindApp(extension->id());
216 if (index >= 0)
217 model_->DeleteAt(index);
218 break;
219 }
220 case chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST: {
221 highlight_app_id_ = *content::Details<const std::string>(details).ptr();
222 HighlightApp();
223 break;
224 }
225 default:
226 NOTREACHED();
227 }
228 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/ash/app_list/apps_model_builder.h ('k') | chrome/browser/ui/ash/app_list/apps_model_builder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698