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

Side by Side Diff: chrome/browser/ui/webui/ntp/app_launcher_handler.cc

Issue 8637001: [NTP4] Auto-deletion of empty apps panes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: removing bits for refactor Created 8 years, 11 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
« no previous file with comments | « chrome/browser/ui/webui/ntp/app_launcher_handler.h ('k') | chrome/common/pref_names.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h" 5 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
6 6
7 #include <algorithm>
7 #include <string> 8 #include <string>
8 #include <vector> 9 #include <vector>
9 10
11
12 #include "base/json/json_writer.h"
13
14
10 #include "base/auto_reset.h" 15 #include "base/auto_reset.h"
11 #include "base/bind.h" 16 #include "base/bind.h"
12 #include "base/bind_helpers.h" 17 #include "base/bind_helpers.h"
13 #include "base/i18n/rtl.h" 18 #include "base/i18n/rtl.h"
14 #include "base/metrics/histogram.h" 19 #include "base/metrics/histogram.h"
15 #include "base/string_number_conversions.h" 20 #include "base/string_number_conversions.h"
16 #include "base/string_split.h" 21 #include "base/string_split.h"
17 #include "base/string_util.h" 22 #include "base/string_util.h"
18 #include "base/utf_string_conversions.h" 23 #include "base/utf_string_conversions.h"
19 #include "base/values.h" 24 #include "base/values.h"
20 #include "chrome/browser/extensions/app_notification_manager.h" 25 #include "chrome/browser/extensions/app_notification_manager.h"
21 #include "chrome/browser/extensions/apps_promo.h" 26 #include "chrome/browser/extensions/apps_promo.h"
22 #include "chrome/browser/extensions/crx_installer.h" 27 #include "chrome/browser/extensions/crx_installer.h"
23 #include "chrome/browser/extensions/extension_prefs.h" 28 #include "chrome/browser/extensions/extension_prefs.h"
24 #include "chrome/browser/extensions/extension_service.h" 29 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/prefs/pref_service.h" 30 #include "chrome/browser/prefs/pref_service.h"
26 #include "chrome/browser/prefs/scoped_user_pref_update.h" 31 #include "chrome/browser/prefs/scoped_user_pref_update.h"
27 #include "chrome/browser/profiles/profile.h" 32 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/ui/browser.h" 33 #include "chrome/browser/ui/browser.h"
29 #include "chrome/browser/ui/browser_list.h" 34 #include "chrome/browser/ui/browser_list.h"
30 #include "chrome/browser/ui/browser_window.h" 35 #include "chrome/browser/ui/browser_window.h"
31 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 36 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
32 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" 37 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
33 #include "chrome/browser/ui/webui/web_ui_util.h" 38 #include "chrome/browser/ui/webui/web_ui_util.h"
34 #include "chrome/common/chrome_notification_types.h" 39 #include "chrome/common/chrome_notification_types.h"
40 #include "chrome/common/extensions/extension_constants.h"
35 #include "chrome/common/extensions/extension.h" 41 #include "chrome/common/extensions/extension.h"
36 #include "chrome/common/extensions/extension_constants.h"
37 #include "chrome/common/extensions/extension_icon_set.h" 42 #include "chrome/common/extensions/extension_icon_set.h"
38 #include "chrome/common/extensions/extension_resource.h" 43 #include "chrome/common/extensions/extension_resource.h"
39 #include "chrome/common/favicon_url.h" 44 #include "chrome/common/favicon_url.h"
40 #include "chrome/common/pref_names.h" 45 #include "chrome/common/pref_names.h"
46 #include "chrome/common/string_ordinal.h"
41 #include "chrome/common/url_constants.h" 47 #include "chrome/common/url_constants.h"
42 #include "chrome/common/web_apps.h" 48 #include "chrome/common/web_apps.h"
43 #include "content/browser/webui/web_ui.h" 49 #include "content/browser/webui/web_ui.h"
44 #include "content/public/browser/notification_service.h" 50 #include "content/public/browser/notification_service.h"
45 #include "googleurl/src/gurl.h" 51 #include "googleurl/src/gurl.h"
46 #include "grit/browser_resources.h" 52 #include "grit/browser_resources.h"
47 #include "grit/generated_resources.h" 53 #include "grit/generated_resources.h"
48 #include "net/base/escape.h" 54 #include "net/base/escape.h"
49 #include "ui/base/animation/animation.h" 55 #include "ui/base/animation/animation.h"
50 #include "ui/base/l10n/l10n_util.h" 56 #include "ui/base/l10n/l10n_util.h"
51 #include "ui/gfx/codec/png_codec.h" 57 #include "ui/gfx/codec/png_codec.h"
52 58
53 using content::WebContents; 59 using content::WebContents;
54 60
55 namespace { 61 namespace {
56 62
57 const net::UnescapeRule::Type kUnescapeRules = 63 const net::UnescapeRule::Type kUnescapeRules =
58 net::UnescapeRule::NORMAL | net::UnescapeRule::URL_SPECIAL_CHARS; 64 net::UnescapeRule::NORMAL | net::UnescapeRule::URL_SPECIAL_CHARS;
59 65
60 extension_misc::AppLaunchBucket ParseLaunchSource( 66 extension_misc::AppLaunchBucket ParseLaunchSource(
61 const std::string& launch_source) { 67 const std::string& launch_source) {
62 int bucket_num = extension_misc::APP_LAUNCH_BUCKET_INVALID; 68 int bucket_num = extension_misc::APP_LAUNCH_BUCKET_INVALID;
63 base::StringToInt(launch_source, &bucket_num); 69 base::StringToInt(launch_source, &bucket_num);
64 extension_misc::AppLaunchBucket bucket = 70 extension_misc::AppLaunchBucket bucket =
65 static_cast<extension_misc::AppLaunchBucket>(bucket_num); 71 static_cast<extension_misc::AppLaunchBucket>(bucket_num);
66 CHECK(bucket < extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); 72 CHECK(bucket < extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
67 return bucket; 73 return bucket;
68 } 74 }
69 75
76 enum PageListPrefMigrationUMABuckets {
77 NONE_REQUIRED = 0,
78 LIST_TO_DICTIONARY = 1,
79 BOUNDARY_BUCKET,
80 };
81
82 // Returns whether the original ordinal was valid.
83 static void EnsurePageOrdinalIsValid(const Extension* extension,
84 ExtensionPrefs* ext_prefs) {
85 DCHECK(extension && ext_prefs);
86 StringOrdinal page_ordinal = ext_prefs->GetPageOrdinal(extension->id());
87
88 // Make sure every app has a page ordinal (some predate the page ordinal).
89 if (!page_ordinal.IsValid()) {
90 // If the ordinal lacking app is the webstore, put it on the first page.
91 page_ordinal = extension->id() == extension_misc::kWebStoreAppId ?
92 ext_prefs->CreateFirstAppPageOrdinal() :
93 ext_prefs->GetNaturalAppPageOrdinal();
94 LOG(ERROR) << "extension(" << extension->id() << ") didn't have a valid page ordinal! Creating one for it as " << page_ordinal.ToString();
95 ext_prefs->SetPageOrdinal(extension->id(), page_ordinal);
96 }
97 }
98
70 } // namespace 99 } // namespace
71 100
72 AppLauncherHandler::AppInstallInfo::AppInstallInfo() {} 101 AppLauncherHandler::AppInstallInfo::AppInstallInfo() {}
73 102
74 AppLauncherHandler::AppInstallInfo::~AppInstallInfo() {} 103 AppLauncherHandler::AppInstallInfo::~AppInstallInfo() {}
75 104
76 AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service) 105 AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service)
77 : extension_service_(extension_service), 106 : extension_service_(extension_service),
78 ignore_changes_(false), 107 ignore_changes_(false),
79 attempted_bookmark_app_install_(false), 108 attempted_bookmark_app_install_(false),
80 has_loaded_apps_(false) { 109 has_loaded_apps_(false),
110 uninstall_from_page_(false) {
81 } 111 }
82 112
83 AppLauncherHandler::~AppLauncherHandler() {} 113 AppLauncherHandler::~AppLauncherHandler() {}
84 114
85 // Serializes |notification| into a new DictionaryValue which the caller then 115 // Serializes |notification| into a new DictionaryValue which the caller then
86 // owns. 116 // owns.
87 static DictionaryValue* SerializeNotification( 117 static DictionaryValue* SerializeNotification(
88 const AppNotification& notification) { 118 const AppNotification& notification) {
89 DictionaryValue* dictionary = new DictionaryValue(); 119 DictionaryValue* dictionary = new DictionaryValue();
90 dictionary->SetString("title", notification.title()); 120 dictionary->SetString("title", notification.title());
(...skipping 12 matching lines...) Expand all
103 (extension->id() == extension_misc::kCloudPrintAppId)) { 133 (extension->id() == extension_misc::kCloudPrintAppId)) {
104 return true; 134 return true;
105 } 135 }
106 return false; 136 return false;
107 } 137 }
108 138
109 void AppLauncherHandler::CreateAppInfo(const Extension* extension, 139 void AppLauncherHandler::CreateAppInfo(const Extension* extension,
110 const AppNotification* notification, 140 const AppNotification* notification,
111 ExtensionService* service, 141 ExtensionService* service,
112 DictionaryValue* value) { 142 DictionaryValue* value) {
143 // Change this check if you'd like to pass a non-empty dictionary here.
144 DCHECK(value && value->empty());
145
113 bool enabled = service->IsExtensionEnabled(extension->id()) && 146 bool enabled = service->IsExtensionEnabled(extension->id()) &&
114 !service->GetTerminatedExtension(extension->id()); 147 !service->GetTerminatedExtension(extension->id());
115 bool icon_big_exists = true; 148 bool icon_big_exists = true;
116 // Instead of setting grayscale here, we do it in apps_page.js. 149 // Instead of setting grayscale here, we do it in apps_page.js.
117 GURL icon_big = 150 GURL icon_big =
118 ExtensionIconSource::GetIconURL(extension, 151 ExtensionIconSource::GetIconURL(extension,
119 Extension::EXTENSION_ICON_LARGE, 152 Extension::EXTENSION_ICON_LARGE,
120 ExtensionIconSet::MATCH_EXACTLY, 153 ExtensionIconSet::MATCH_EXACTLY,
121 false, &icon_big_exists); 154 false, &icon_big_exists);
122 bool icon_small_exists = true; 155 bool icon_small_exists = true;
(...skipping 26 matching lines...) Expand all
149 value->SetInteger("launch_type", 182 value->SetInteger("launch_type",
150 prefs->GetLaunchType(extension->id(), 183 prefs->GetLaunchType(extension->id(),
151 ExtensionPrefs::LAUNCH_DEFAULT)); 184 ExtensionPrefs::LAUNCH_DEFAULT));
152 value->SetBoolean("offline_enabled", extension->offline_enabled()); 185 value->SetBoolean("offline_enabled", extension->offline_enabled());
153 value->SetBoolean("is_component", 186 value->SetBoolean("is_component",
154 extension->location() == Extension::COMPONENT); 187 extension->location() == Extension::COMPONENT);
155 value->SetBoolean("is_webstore", 188 value->SetBoolean("is_webstore",
156 extension->id() == extension_misc::kWebStoreAppId); 189 extension->id() == extension_misc::kWebStoreAppId);
157 190
158 if (extension->HasAPIPermission(ExtensionAPIPermission::kAppNotifications)) { 191 if (extension->HasAPIPermission(ExtensionAPIPermission::kAppNotifications)) {
159 ExtensionPrefs* prefs = service->extension_prefs();
160 value->SetBoolean("notifications_disabled", 192 value->SetBoolean("notifications_disabled",
161 prefs->IsAppNotificationDisabled(extension->id())); 193 prefs->IsAppNotificationDisabled(extension->id()));
162 } 194 }
163 195
164 if (notification) 196 if (notification)
165 value->Set("notification", SerializeNotification(*notification)); 197 value->Set("notification", SerializeNotification(*notification));
166 198
199 EnsurePageOrdinalIsValid(extension, prefs);
167 StringOrdinal page_ordinal = prefs->GetPageOrdinal(extension->id()); 200 StringOrdinal page_ordinal = prefs->GetPageOrdinal(extension->id());
168 if (!page_ordinal.IsValid()) { 201 value->SetString("page_ordinal", page_ordinal.ToString());
169 // Make sure every app has a page ordinal (some predate the page ordinal).
170 // The webstore app should be on the first page.
171 page_ordinal = extension->id() == extension_misc::kWebStoreAppId ?
172 prefs->CreateFirstAppPageOrdinal() : prefs->GetNaturalAppPageOrdinal();
173 prefs->SetPageOrdinal(extension->id(), page_ordinal);
174 }
175 // We convert the page_ordinal to an integer because the pages are referenced
176 // from within an array in the javascript code, which can't be easily
177 // changed to handle the StringOrdinal values, so we do the conversion here.
178 int page_index = prefs->PageStringOrdinalAsInteger(page_ordinal);
179 value->SetInteger("page_index", page_index >= 0 ? page_index : 0);
180 202
181 StringOrdinal app_launch_ordinal = 203 StringOrdinal app_launch_ordinal =
182 prefs->GetAppLaunchOrdinal(extension->id()); 204 prefs->GetAppLaunchOrdinal(extension->id());
183 if (!app_launch_ordinal.IsValid()) { 205 if (!app_launch_ordinal.IsValid()) {
184 // Make sure every app has a launch ordinal (some predate the launch 206 // Make sure every app has a launch ordinal (some predate the launch
185 // ordinal). The webstore's app launch ordinal is always set to the first 207 // ordinal). The webstore's app launch ordinal is always set to the first
186 // position. 208 // position.
187 app_launch_ordinal = extension->id() == extension_misc::kWebStoreAppId ? 209 app_launch_ordinal = extension->id() == extension_misc::kWebStoreAppId ?
188 prefs->CreateFirstAppLaunchOrdinal(page_ordinal) : 210 prefs->CreateFirstAppLaunchOrdinal(page_ordinal) :
189 prefs->CreateNextAppLaunchOrdinal(page_ordinal); 211 prefs->CreateNextAppLaunchOrdinal(page_ordinal);
190 prefs->SetAppLaunchOrdinal(extension->id(), app_launch_ordinal); 212 prefs->SetAppLaunchOrdinal(extension->id(), app_launch_ordinal);
191 } 213 }
192 value->SetString("app_launch_ordinal", app_launch_ordinal.ToString()); 214 value->SetString("app_launch_ordinal", app_launch_ordinal.ToString());
193 } 215 }
194 216
195 void AppLauncherHandler::RegisterMessages() { 217 void AppLauncherHandler::RegisterMessages() {
196 registrar_.Add(this, chrome::NOTIFICATION_APP_INSTALLED_TO_NTP, 218 registrar_.Add(this, chrome::NOTIFICATION_APP_INSTALLED_TO_NTP,
197 content::Source<WebContents>(web_ui()->web_contents())); 219 content::Source<WebContents>(web_ui()->web_contents()));
198 220
221 web_ui()->RegisterMessageCallback("deleteEmptyAppsPage",
222 base::Bind(&AppLauncherHandler::HandleDeleteEmptyAppsPage,
223 base::Unretained(this)));
199 web_ui()->RegisterMessageCallback("getApps", 224 web_ui()->RegisterMessageCallback("getApps",
200 base::Bind(&AppLauncherHandler::HandleGetApps, 225 base::Bind(&AppLauncherHandler::HandleGetApps,
201 base::Unretained(this))); 226 base::Unretained(this)));
202 web_ui()->RegisterMessageCallback("launchApp", 227 web_ui()->RegisterMessageCallback("launchApp",
203 base::Bind(&AppLauncherHandler::HandleLaunchApp, 228 base::Bind(&AppLauncherHandler::HandleLaunchApp,
204 base::Unretained(this))); 229 base::Unretained(this)));
205 web_ui()->RegisterMessageCallback("setLaunchType", 230 web_ui()->RegisterMessageCallback("setLaunchType",
206 base::Bind(&AppLauncherHandler::HandleSetLaunchType, 231 base::Bind(&AppLauncherHandler::HandleSetLaunchType,
207 base::Unretained(this))); 232 base::Unretained(this)));
208 web_ui()->RegisterMessageCallback("uninstallApp", 233 web_ui()->RegisterMessageCallback("uninstallApp",
209 base::Bind(&AppLauncherHandler::HandleUninstallApp, 234 base::Bind(&AppLauncherHandler::HandleUninstallApp,
210 base::Unretained(this))); 235 base::Unretained(this)));
211 web_ui()->RegisterMessageCallback("hideAppsPromo", 236 web_ui()->RegisterMessageCallback("hideAppsPromo",
212 base::Bind(&AppLauncherHandler::HandleHideAppsPromo, 237 base::Bind(&AppLauncherHandler::HandleHideAppsPromo,
213 base::Unretained(this))); 238 base::Unretained(this)));
214 web_ui()->RegisterMessageCallback("createAppShortcut", 239 web_ui()->RegisterMessageCallback("createAppShortcut",
215 base::Bind(&AppLauncherHandler::HandleCreateAppShortcut, 240 base::Bind(&AppLauncherHandler::HandleCreateAppShortcut,
216 base::Unretained(this))); 241 base::Unretained(this)));
217 web_ui()->RegisterMessageCallback("reorderApps", 242 web_ui()->RegisterMessageCallback("reorderApps",
218 base::Bind(&AppLauncherHandler::HandleReorderApps, 243 base::Bind(&AppLauncherHandler::HandleReorderApps,
219 base::Unretained(this))); 244 base::Unretained(this)));
220 web_ui()->RegisterMessageCallback("setPageIndex", 245 web_ui()->RegisterMessageCallback("setPageIndex",
221 base::Bind(&AppLauncherHandler::HandleSetPageIndex, 246 base::Bind(&AppLauncherHandler::HandleSetPageIndex,
222 base::Unretained(this))); 247 base::Unretained(this)));
223 web_ui()->RegisterMessageCallback("promoSeen", 248 web_ui()->RegisterMessageCallback("promoSeen",
224 base::Bind(&AppLauncherHandler::HandlePromoSeen, 249 base::Bind(&AppLauncherHandler::HandlePromoSeen,
225 base::Unretained(this))); 250 base::Unretained(this)));
226 web_ui()->RegisterMessageCallback("saveAppPageName", 251 web_ui()->RegisterMessageCallback("saveAppsPageName",
227 base::Bind(&AppLauncherHandler::HandleSaveAppPageName, 252 base::Bind(&AppLauncherHandler::HandleSaveAppsPageName,
228 base::Unretained(this))); 253 base::Unretained(this)));
229 web_ui()->RegisterMessageCallback("generateAppForLink", 254 web_ui()->RegisterMessageCallback("generateAppForLink",
230 base::Bind(&AppLauncherHandler::HandleGenerateAppForLink, 255 base::Bind(&AppLauncherHandler::HandleGenerateAppForLink,
231 base::Unretained(this))); 256 base::Unretained(this)));
232 web_ui()->RegisterMessageCallback("recordAppLaunchByURL", 257 web_ui()->RegisterMessageCallback("recordAppLaunchByURL",
233 base::Bind(&AppLauncherHandler::HandleRecordAppLaunchByURL, 258 base::Bind(&AppLauncherHandler::HandleRecordAppLaunchByURL,
234 base::Unretained(this))); 259 base::Unretained(this)));
235 web_ui()->RegisterMessageCallback("closeNotification", 260 web_ui()->RegisterMessageCallback("closeNotification",
236 base::Bind(&AppLauncherHandler::HandleNotificationClose, 261 base::Bind(&AppLauncherHandler::HandleNotificationClose,
237 base::Unretained(this))); 262 base::Unretained(this)));
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 content::Details<UnloadedExtensionInfo>(details)->extension; 320 content::Details<UnloadedExtensionInfo>(details)->extension;
296 if (!extension->is_app()) 321 if (!extension->is_app())
297 return; 322 return;
298 323
299 scoped_ptr<DictionaryValue> app_info(GetAppInfo(extension)); 324 scoped_ptr<DictionaryValue> app_info(GetAppInfo(extension));
300 scoped_ptr<base::FundamentalValue> uninstall_value( 325 scoped_ptr<base::FundamentalValue> uninstall_value(
301 Value::CreateBooleanValue( 326 Value::CreateBooleanValue(
302 content::Details<UnloadedExtensionInfo>(details)->reason == 327 content::Details<UnloadedExtensionInfo>(details)->reason ==
303 extension_misc::UNLOAD_REASON_UNINSTALL)); 328 extension_misc::UNLOAD_REASON_UNINSTALL));
304 if (app_info.get()) { 329 if (app_info.get()) {
330 scoped_ptr<base::FundamentalValue> from_page(
331 Value::CreateBooleanValue(uninstall_from_page_));
305 web_ui()->CallJavascriptFunction( 332 web_ui()->CallJavascriptFunction(
306 "ntp4.appRemoved", *app_info, *uninstall_value); 333 "ntp4.appRemoved", *app_info, *uninstall_value, *from_page);
307 } 334 }
308 break; 335 break;
309 } 336 }
310 case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED: 337 case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED: {
311 // The promo may not load until a couple seconds after the first NTP view, 338 DictionaryValue pages;
312 // so we listen for the load notification and notify the NTP when ready. 339 const ExtensionSet* extensions = extension_service_->extensions();
313 case chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED: 340 ExtensionPrefs* prefs = extension_service_->extension_prefs();
314 // TODO(estade): try to get rid of this inefficient operation. 341 for (ExtensionSet::const_iterator it = extensions->begin();
342 it != extensions->end(); ++it) {
343 if (!IsAppExcludedFromList(*it)) {
344 std::string page_ordinal_string =
345 prefs->GetPageOrdinal((*it)->id()).ToString();
346 if (!pages.HasKey(page_ordinal_string))
347 pages.Set(page_ordinal_string, new DictionaryValue());
348 DictionaryValue* page;
349 CHECK(pages.GetDictionary(page_ordinal_string, &page));
350 page->SetString(prefs->GetAppLaunchOrdinal((*it)->id()).ToString(),
351 (*it)->id());
352 }
353 }
354 web_ui()->CallJavascriptFunction("ntp4.appsReordered", pages);
355 break;
356 }
357 case chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED: {
358 // The promo may not load until a couple seconds after the first NTP view,
359 // so we listen for the load notification and notify the NTP when ready.
315 HandleGetApps(NULL); 360 HandleGetApps(NULL);
316 break; 361 break;
362 }
317 case chrome::NOTIFICATION_PREF_CHANGED: { 363 case chrome::NOTIFICATION_PREF_CHANGED: {
364 LOG(ERROR) << "Pref changed!";
318 DictionaryValue dictionary; 365 DictionaryValue dictionary;
319 FillAppDictionary(&dictionary); 366 FillAppDictionary(&dictionary);
320 web_ui()->CallJavascriptFunction("appsPrefChangeCallback", dictionary); 367 web_ui()->CallJavascriptFunction("appsPrefChangeCallback", dictionary);
321 break; 368 break;
322 } 369 }
323 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: { 370 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
324 CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr(); 371 CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr();
325 if (!Profile::FromWebUI(web_ui())->IsSameProfile( 372 if (!Profile::FromWebUI(web_ui())->IsSameProfile(
326 crx_installer->profile())) { 373 crx_installer->profile())) {
327 return; 374 return;
328 } 375 }
329 // Fall Through. 376 // Fall Through.
330 } 377 }
331 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: { 378 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: {
332 attempted_bookmark_app_install_ = false; 379 attempted_bookmark_app_install_ = false;
333 break; 380 break;
334 } 381 }
335 default: 382 default:
336 NOTREACHED(); 383 NOTREACHED();
337 } 384 }
338 } 385 }
339 386
387 void AppLauncherHandler::RemoveNonAppExtensionOrdinals(
388 const ExtensionSet* extensions) {
389 ExtensionSet::const_iterator it;
390 for (it = extensions->begin(); it != extensions->end(); ++it) {
391 const Extension* extension = *it;
392 // Ensure any previous non-app extensions aren't showing / don't have a page
393 // ordinal or migrated page index. This is necessary because in some
394 // previous versions of chrome, we set a page index for non-app extensions.
395 // Old profiles can persist this error, and this fixes it. This caused
396 // GetNaturalAppPageIndex() to break (see http://crbug.com/98325) before it
397 // was an ordinal value.
398 if (IsAppExcludedFromList(extension)) {
399 ExtensionPrefs* ext_prefs = extension_service_->extension_prefs();
400 if (ext_prefs->GetPageOrdinal(extension->id()).IsValid())
401 ext_prefs->ClearPageOrdinal(extension->id());
402 }
403 }
404 }
405
340 void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) { 406 void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) {
341 // CreateAppInfo and ClearPageOrdinal can change the extension prefs. 407 // CreateAppInfo and ClearPageOrdinal can change the extension prefs.
342 AutoReset<bool> auto_reset(&ignore_changes_, true); 408 AutoReset<bool> auto_reset(&ignore_changes_, true);
343 409
344 ListValue* list = new ListValue(); 410 RemoveNonAppExtensionOrdinals(extension_service_->extensions());
345 const ExtensionSet* extensions = extension_service_->extensions(); 411
346 ExtensionSet::const_iterator it; 412 // Start NULL, CHECK() that it's not NULL after being populated with names.
347 for (it = extensions->begin(); it != extensions->end(); ++it) { 413 DictionaryValue* apps_page_names = NULL;
348 const Extension* extension = *it; 414
349 if (!IsAppExcludedFromList(extension)) { 415 // Get all the existing apps' page_ordinals, de-duped and sorted, and make
350 DictionaryValue* app_info = GetAppInfo(extension); 416 // sure we've got page names for all the existing pages (or populate with
351 list->Append(app_info); 417 // default). If there's a page without any apps on it, delete that pref.
352 } else { 418 scoped_ptr<std::vector<std::string> > page_ordinals(PageOrdinalsFromApps());
353 // This is necessary because in some previous versions of chrome, we set a 419
354 // page index for non-app extensions. Old profiles can persist this error, 420 // Most of the time we probably won't need to update, so let's only do this
355 // and this fixes it. This caused GetNaturalAppPageIndex() to break 421 // when something changes (during migration or an edge case like mentioned
356 // (see http://crbug.com/98325) before it was an ordinal value. 422 // above when the page names pref doesn't match the apps' info).
357 ExtensionPrefs* prefs = extension_service_->extension_prefs(); 423 bool update_required = false;
358 if (prefs->GetPageOrdinal(extension->id()).IsValid()) 424
359 prefs->ClearPageOrdinal(extension->id()); 425 // If the legacy preference exists, migrate it from a list to a dictionary.
426 // TODO(dbeam): Remove migration when UMA hits sufficiently small number.
427 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
428 if (prefs->HasPrefPath(prefs::kNTPAppsPageNamesOld)) {
429 LOG(ERROR) << "Migrating from list to dict for page names required!";
430 apps_page_names = new DictionaryValue();
431 scoped_ptr<ListValue> apps_page_names_list(
432 prefs->GetList(prefs::kNTPAppsPageNamesOld)->DeepCopy());
433 string16 default_page_name(
434 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME));
435 for (size_t i = 0; i < page_ordinals->size(); ++i) {
436 if (i >= apps_page_names_list->GetSize()) {
437 apps_page_names->Set(page_ordinals->at(i),
438 Value::CreateStringValue(default_page_name));
439 } else {
440 Value* name;
441 CHECK(apps_page_names_list->Get(i, &name));
442 apps_page_names->Set(page_ordinals->at(i), name->DeepCopy());
443 }
444 }
445 // If there were extra entries just ignore, we're deleting whole preference.
446 prefs->ClearPref(prefs::kNTPAppsPageNamesOld);
447 update_required = true;
448 UMA_HISTOGRAM_ENUMERATION("NewTabPage.PageNamesPrefMigration",
449 LIST_TO_DICTIONARY, BOUNDARY_BUCKET);
450 } else {
451 LOG(ERROR) << "No migration required!";
452 apps_page_names =
453 prefs->GetDictionary(prefs::kNTPAppsPageNames)->DeepCopy();
454 update_required = SyncPageNamesToApps(apps_page_names);
455 // Log this to more easily track how many folks are done migrating prefs.
456 UMA_HISTOGRAM_ENUMERATION("NewTabPage.PageNamesPrefMigration",
457 NONE_REQUIRED, BOUNDARY_BUCKET);
458 }
459 // There should always be something in this pref (as there should always be at
460 // least one app which requires a page to live on).
461 CHECK(apps_page_names && !apps_page_names->empty());
462
463 if (update_required) {
464 LOG(ERROR) << "Something about page names changed, updating!";
465 scoped_ptr<DictionaryValue> page_names_copy(apps_page_names->DeepCopy());
466 DictionaryPrefUpdate update(prefs, prefs::kNTPAppsPageNames);
467 update.Get()->Swap(page_names_copy.get());
468 }
469
470 std::string json;
471 base::JSONWriter::Write(apps_page_names, false, &json);
472 LOG(ERROR) << apps_page_names->size() << ", " << json;
473
474 // Create a dictionary structured by pages and app ordinals, like this:
475 // {
476 // "<page_ordinal>": {
477 // "name": <page_name>,
478 // "apps": {
479 // <app_launch_ordinal>": { <app_info> },
480 // ...
481 // }
482 // ...
483 // },
484 // ...
485 // }
486 DictionaryValue* apps_pages = new DictionaryValue();
487
488 scoped_ptr<const ExtensionSet> installed_extensions(
489 extension_service_->GetAllInstalledExtensions());
490
491 for (ExtensionSet::const_iterator it = installed_extensions->begin();
492 it != installed_extensions->end(); ++it) {
493 if (!IsAppExcludedFromList(*it)) {
494 DictionaryValue* app_info = new DictionaryValue();
495 CreateAppInfo(*it, NULL, extension_service_, app_info);
496
497 std::string page_ordinal;
498 DCHECK(app_info->GetString("page_ordinal", &page_ordinal));
499 LOG(ERROR) << "App had page_ordinal: " << page_ordinal;
500
501 if (!apps_pages->HasKey(page_ordinal))
502 apps_pages->Set(page_ordinal, new DictionaryValue());
503
504 DictionaryValue* page;
505 DCHECK(apps_pages->GetDictionary(page_ordinal, &page));
506
507 if (!page->HasKey("apps"))
508 page->Set("apps", new DictionaryValue());
509
510 if (!page->HasKey("name")) {
511 std::string page_name;
512 DCHECK(apps_page_names->GetString(page_ordinal, &page_name));
513 page->Set("name", Value::CreateStringValue(page_name));
514 }
515
516 DictionaryValue* apps;
517 DCHECK(page->GetDictionary("apps", &apps));
518
519 std::string app_launch_ordinal;
520 DCHECK(app_info->GetString("app_launch_ordinal", &app_launch_ordinal));
521
522 DCHECK(!apps->HasKey(app_launch_ordinal));
523 apps->Set(app_launch_ordinal, app_info);
360 } 524 }
361 } 525 }
526 CHECK(apps_pages->size() >= 1);
527 dictionary->Set("appsPages", apps_pages);
528 }
362 529
363 extensions = extension_service_->disabled_extensions(); 530 bool AppLauncherHandler::SyncPageNamesToApps(DictionaryValue* page_names) {
364 for (it = extensions->begin(); it != extensions->end(); ++it) { 531 string16 default_page_name =
365 if (!IsAppExcludedFromList(*it)) { 532 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME);
366 DictionaryValue* app_info = new DictionaryValue(); 533 bool value_changed = false;
367 CreateAppInfo(*it, 534 // Get all the unique page ordinals that the current set of apps has and if no
368 NULL, 535 // page name exists for that page yet, create one with the default value.
369 extension_service_, 536 scoped_ptr<std::vector<std::string> > ordinals(PageOrdinalsFromApps());
370 app_info); 537 for (std::vector<std::string>::const_iterator it = ordinals->begin();
371 list->Append(app_info); 538 it != ordinals->end(); ++it) {
539 if (!page_names->HasKey(*it)) {
540 LOG(ERROR) << "Found new page ordinal, " << *it << ", setting it to defaul t page name! (" << default_page_name << ")";
541 page_names->SetString(*it, default_page_name);
542 value_changed = true;
372 } 543 }
373 } 544 }
374 545 // Make a copy to avoid invalidating our iterator if a key is deleted.
375 extensions = extension_service_->terminated_extensions(); 546 scoped_ptr<DictionaryValue> page_names_copy(page_names->DeepCopy());
376 for (it = extensions->begin(); it != extensions->end(); ++it) { 547 // Look for extraneous pages that no longer have apps on them.
377 if (!IsAppExcludedFromList(*it)) { 548 for (DictionaryValue::key_iterator it = page_names->begin_keys();
378 DictionaryValue* app_info = new DictionaryValue(); 549 it != page_names->end_keys(); ++it) {
379 CreateAppInfo(*it, 550 if (std::find(ordinals->begin(), ordinals->end(), *it) == ordinals->end()) {
380 NULL, 551 LOG(ERROR) << "Found left over page ordinal, " << *it << ", deleting!";
381 extension_service_, 552 DCHECK(page_names_copy->Remove(*it, NULL));
382 app_info); 553 value_changed = true;
383 list->Append(app_info);
384 } 554 }
385 } 555 }
386 556 // Swap with the possibly affected dictionary.
387 dictionary->Set("apps", list); 557 page_names->Swap(page_names_copy.get());
388 558 // Tell the caller whether anything changed in this method.
389 // TODO(estade): remove these settings when the old NTP is removed. The new 559 return value_changed;
390 // NTP does it in js.
391 #if defined(OS_MACOSX)
392 // App windows are not yet implemented on mac.
393 dictionary->SetBoolean("disableAppWindowLaunch", true);
394 dictionary->SetBoolean("disableCreateAppShortcut", true);
395 #endif
396
397 #if defined(OS_CHROMEOS)
398 // Making shortcut does not make sense on ChromeOS because it does not have
399 // a desktop.
400 dictionary->SetBoolean("disableCreateAppShortcut", true);
401 #endif
402
403 dictionary->SetBoolean(
404 "showLauncher",
405 extension_service_->apps_promo()->ShouldShowAppLauncher(
406 extension_service_->GetAppIds()));
407
408 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
409 const ListValue* app_page_names = prefs->GetList(prefs::kNTPAppPageNames);
410 if (!app_page_names || !app_page_names->GetSize()) {
411 ListPrefUpdate update(prefs, prefs::kNTPAppPageNames);
412 ListValue* list = update.Get();
413 list->Set(0, Value::CreateStringValue(
414 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME)));
415 dictionary->Set("appPageNames",
416 static_cast<ListValue*>(list->DeepCopy()));
417 } else {
418 dictionary->Set("appPageNames",
419 static_cast<ListValue*>(app_page_names->DeepCopy()));
420 }
421 } 560 }
422 561
423 DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) { 562 DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) {
424 AppNotificationManager* notification_manager = 563 AppNotificationManager* notification_manager =
425 extension_service_->app_notification_manager(); 564 extension_service_->app_notification_manager();
426 DictionaryValue* app_info = new DictionaryValue(); 565 DictionaryValue* app_info = new DictionaryValue();
427 // CreateAppInfo can change the extension prefs. 566 // CreateAppInfo can change the extension prefs.
428 AutoReset<bool> auto_reset(&ignore_changes_, true); 567 AutoReset<bool> auto_reset(&ignore_changes_, true);
429 CreateAppInfo(extension, 568 CreateAppInfo(extension,
430 notification_manager->GetLast(extension->id()), 569 notification_manager->GetLast(extension->id()),
431 extension_service_, 570 extension_service_,
432 app_info); 571 app_info);
433 return app_info; 572 return app_info;
434 } 573 }
435 574
575 std::vector<std::string>* AppLauncherHandler::PageOrdinalsFromApps() {
576 std::vector<std::string>* pages = new std::vector<std::string>();
577 const ExtensionSet* extensions = extension_service_->extensions();
578 ExtensionPrefs* ext_prefs = extension_service_->extension_prefs();
579 for (ExtensionSet::const_iterator it = extensions->begin();
580 it != extensions->end(); ++it) {
581 if (!IsAppExcludedFromList(*it)) {
582 EnsurePageOrdinalIsValid(*it, ext_prefs);
583 std::string ordinal(ext_prefs->GetPageOrdinal((*it)->id()).ToString());
584 if (std::find(pages->begin(), pages->end(), ordinal) == pages->end())
585 pages->push_back(ordinal);
586 }
587 }
588 std::sort(pages->begin(), pages->end());
589 return pages;
590 }
591
436 void AppLauncherHandler::FillPromoDictionary(DictionaryValue* dictionary) { 592 void AppLauncherHandler::FillPromoDictionary(DictionaryValue* dictionary) {
437 AppsPromo::PromoData data = AppsPromo::GetPromo(); 593 AppsPromo::PromoData data = AppsPromo::GetPromo();
438 dictionary->SetString("promoHeader", data.header); 594 dictionary->SetString("promoHeader", data.header);
439 dictionary->SetString("promoButton", data.button); 595 dictionary->SetString("promoButton", data.button);
440 dictionary->SetString("promoLink", data.link.spec()); 596 dictionary->SetString("promoLink", data.link.spec());
441 dictionary->SetString("promoLogo", data.logo.spec()); 597 dictionary->SetString("promoLogo", data.logo.spec());
442 dictionary->SetString("promoExpire", data.expire); 598 dictionary->SetString("promoExpire", data.expire);
443 } 599 }
444 600
601 void AppLauncherHandler::HandleDeleteEmptyAppsPage(const ListValue* args) {
602 std::string page_ordinal;
603 CHECK(args->GetString(0, &page_ordinal));
604
605 AutoReset<bool> auto_reset(&ignore_changes_, true);
606
607 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
608 const DictionaryValue* dict = prefs->GetDictionary(prefs::kNTPAppsPageNames);
609 std::string value;
610 DCHECK(dict->GetString(page_ordinal, &value));
611
612 LOG(ERROR) << "Its value is: " << value;
613
614 // Ensure the page we're deleting is empty.
615 scoped_ptr<std::vector<std::string> > pages(PageOrdinalsFromApps());
616 DCHECK(std::find(pages->begin(), pages->end(), page_ordinal) == pages->end());
617
618 DictionaryPrefUpdate update(prefs, prefs::kNTPAppsPageNames);
619 DCHECK(update.Get()->Remove(page_ordinal, NULL));
620
621 dict = prefs->GetDictionary(prefs::kNTPAppsPageNames);
622
623 std::string json;
624 base::JSONWriter::Write(dict, false, &json);
625 LOG(ERROR) << "now is: " << dict->size() << ", " << json;
626 }
627
628 void AppLauncherHandler::CleanupAfterUninstall() {
629 uninstall_from_page_ = false;
630 extension_id_prompting_ = "";
631 }
632
445 void AppLauncherHandler::HandleGetApps(const ListValue* args) { 633 void AppLauncherHandler::HandleGetApps(const ListValue* args) {
446 DictionaryValue dictionary; 634 DictionaryValue dictionary;
447 635
448 // Tell the client whether to show the promo for this view. We don't do this 636 // Tell the client whether to show the promo for this view. We don't do this
449 // in the case of PREF_CHANGED because: 637 // in the case of PREF_CHANGED because:
450 // 638 //
451 // a) At that point in time, depending on the pref that changed, it can look 639 // a) At that point in time, depending on the pref that changed, it can look
452 // like the set of apps installed has changed, and we will mark the promo 640 // like the set of apps installed has changed, and we will mark the promo
453 // expired. 641 // expired.
454 // b) Conceptually, it doesn't really make sense to count a 642 // b) Conceptually, it doesn't really make sense to count a
(...skipping 20 matching lines...) Expand all
475 SetAppToBeHighlighted(); 663 SetAppToBeHighlighted();
476 FillAppDictionary(&dictionary); 664 FillAppDictionary(&dictionary);
477 web_ui()->CallJavascriptFunction("getAppsCallback", dictionary); 665 web_ui()->CallJavascriptFunction("getAppsCallback", dictionary);
478 666
479 // First time we get here we set up the observer so that we can tell update 667 // First time we get here we set up the observer so that we can tell update
480 // the apps as they change. 668 // the apps as they change.
481 if (!has_loaded_apps_) { 669 if (!has_loaded_apps_) {
482 pref_change_registrar_.Init( 670 pref_change_registrar_.Init(
483 extension_service_->extension_prefs()->pref_service()); 671 extension_service_->extension_prefs()->pref_service());
484 pref_change_registrar_.Add(ExtensionPrefs::kExtensionsPref, this); 672 pref_change_registrar_.Add(ExtensionPrefs::kExtensionsPref, this);
485 pref_change_registrar_.Add(prefs::kNTPAppPageNames, this); 673 pref_change_registrar_.Add(prefs::kNTPAppsPageNames, this);
486 674
487 registrar_.Add(this, chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED, 675 registrar_.Add(this, chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED,
488 content::Source<Profile>(profile)); 676 content::Source<Profile>(profile));
489 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 677 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
490 content::Source<Profile>(profile)); 678 content::Source<Profile>(profile));
491 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 679 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
492 content::Source<Profile>(profile)); 680 content::Source<Profile>(profile));
493 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED, 681 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED,
494 content::Source<ExtensionPrefs>(extension_service_->extension_prefs())); 682 content::Source<ExtensionPrefs>(extension_service_->extension_prefs()));
495 registrar_.Add(this, chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED, 683 registrar_.Add(this, chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED,
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 if (!extension_id_prompting_.empty()) 796 if (!extension_id_prompting_.empty())
609 return; // Only one prompt at a time. 797 return; // Only one prompt at a time.
610 798
611 extension_id_prompting_ = extension_id; 799 extension_id_prompting_ = extension_id;
612 800
613 bool dont_confirm = false; 801 bool dont_confirm = false;
614 if (args->GetBoolean(1, &dont_confirm) && dont_confirm) { 802 if (args->GetBoolean(1, &dont_confirm) && dont_confirm) {
615 AutoReset<bool> auto_reset(&ignore_changes_, true); 803 AutoReset<bool> auto_reset(&ignore_changes_, true);
616 ExtensionUninstallAccepted(); 804 ExtensionUninstallAccepted();
617 } else { 805 } else {
806 // We don't use an AutoReset<bool> here as the uninstall dialog runs in a
807 // different thread so it's not sync.
808 uninstall_from_page_ = true;
618 GetExtensionUninstallDialog()->ConfirmUninstall(extension); 809 GetExtensionUninstallDialog()->ConfirmUninstall(extension);
619 } 810 }
620 } 811 }
621 812
622 void AppLauncherHandler::HandleHideAppsPromo(const ListValue* args) { 813 void AppLauncherHandler::HandleHideAppsPromo(const ListValue* args) {
623 // If the user has intentionally hidden the promotion, we'll uninstall all the 814 // If the user has intentionally hidden the promotion, we'll uninstall all the
624 // default apps (we know the user hasn't installed any apps on their own at 815 // default apps (we know the user hasn't installed any apps on their own at
625 // this point, or the promotion wouldn't have been shown). 816 // this point, or the promotion wouldn't have been shown).
626 // TODO(estade): this isn't used right now as we sort out the future of the 817 // TODO(estade): this isn't used right now as we sort out the future of the
627 // apps promo on ntp4. 818 // apps promo on ntp4.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 extension_service_->extension_prefs()->SetPageOrdinal(extension_id, 880 extension_service_->extension_prefs()->SetPageOrdinal(extension_id,
690 page_ordinal); 881 page_ordinal);
691 } 882 }
692 883
693 void AppLauncherHandler::HandlePromoSeen(const ListValue* args) { 884 void AppLauncherHandler::HandlePromoSeen(const ListValue* args) {
694 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, 885 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram,
695 extension_misc::PROMO_SEEN, 886 extension_misc::PROMO_SEEN,
696 extension_misc::PROMO_BUCKET_BOUNDARY); 887 extension_misc::PROMO_BUCKET_BOUNDARY);
697 } 888 }
698 889
699 void AppLauncherHandler::HandleSaveAppPageName(const ListValue* args) { 890 void AppLauncherHandler::HandleSaveAppsPageName(const ListValue* args) {
700 string16 name; 891 string16 name;
701 CHECK(args->GetString(0, &name)); 892 CHECK(args->GetString(0, &name));
702 893
703 double page_index; 894 double page_index_double;
704 CHECK(args->GetDouble(1, &page_index)); 895 CHECK(args->GetDouble(1, &page_index_double));
896 size_t page_index = static_cast<size_t>(page_index_double);
705 897
706 AutoReset<bool> auto_reset(&ignore_changes_, true); 898 bool should_notify;
899 CHECK(args->GetBoolean(2, &should_notify));
900
901 // There is logic within ExtensionPrefs::PageIntegerAsStringOrdinal() to give
902 // us the next page ordinal if we're requesting an index that's greater than
903 // what already exists (but only if it's +1 larger, which is fine for us).
904 ExtensionPrefs* ext_prefs = extension_service_->extension_prefs();
905 StringOrdinal page_ordinal(ext_prefs->PageIntegerAsStringOrdinal(page_index));
906 CHECK(page_ordinal.IsValid());
907
908 // Don't ignore changes in same cases when we need to propagate the page
909 // ordinal to the JS.
910 AutoReset<bool> auto_reset(&ignore_changes_, !should_notify);
911
707 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 912 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
708 ListPrefUpdate update(prefs, prefs::kNTPAppPageNames); 913 DictionaryPrefUpdate update(prefs, prefs::kNTPAppsPageNames);
709 ListValue* list = update.Get(); 914 update.Get()->Set(page_ordinal.ToString(), Value::CreateStringValue(name));
710 list->Set(static_cast<size_t>(page_index), Value::CreateStringValue(name));
711 } 915 }
712 916
713 void AppLauncherHandler::HandleGenerateAppForLink(const ListValue* args) { 917 void AppLauncherHandler::HandleGenerateAppForLink(const ListValue* args) {
714 std::string url; 918 std::string url;
715 CHECK(args->GetString(0, &url)); 919 CHECK(args->GetString(0, &url));
716 GURL launch_url(url); 920 GURL launch_url(url);
717 921
718 string16 title; 922 string16 title;
719 CHECK(args->GetString(1, &title)); 923 CHECK(args->GetString(1, &title));
720 924
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 return; 1026 return;
823 1027
824 StringValue app_id(highlight_app_id_); 1028 StringValue app_id(highlight_app_id_);
825 web_ui()->CallJavascriptFunction("ntp4.setAppToBeHighlighted", app_id); 1029 web_ui()->CallJavascriptFunction("ntp4.setAppToBeHighlighted", app_id);
826 highlight_app_id_.clear(); 1030 highlight_app_id_.clear();
827 } 1031 }
828 1032
829 // static 1033 // static
830 void AppLauncherHandler::RegisterUserPrefs(PrefService* pref_service) { 1034 void AppLauncherHandler::RegisterUserPrefs(PrefService* pref_service) {
831 // TODO(csharp): We will want this to be a syncable preference instead. 1035 // TODO(csharp): We will want this to be a syncable preference instead.
832 pref_service->RegisterListPref(prefs::kNTPAppPageNames, 1036 pref_service->RegisterDictionaryPref(prefs::kNTPAppsPageNames,
1037 PrefService::UNSYNCABLE_PREF);
1038 pref_service->RegisterListPref(prefs::kNTPAppsPageNamesOld,
833 PrefService::UNSYNCABLE_PREF); 1039 PrefService::UNSYNCABLE_PREF);
834 } 1040 }
835 1041
836 // static 1042 // static
837 void AppLauncherHandler::RecordWebStoreLaunch(bool promo_active) { 1043 void AppLauncherHandler::RecordWebStoreLaunch(bool promo_active) {
838 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram, 1044 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram,
839 extension_misc::APP_LAUNCH_NTP_WEBSTORE, 1045 extension_misc::APP_LAUNCH_NTP_WEBSTORE,
840 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); 1046 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
841 1047
842 if (!promo_active) return; 1048 if (!promo_active) return;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 1117
912 // The extension can be uninstalled in another window while the UI was 1118 // The extension can be uninstalled in another window while the UI was
913 // showing. Do nothing in that case. 1119 // showing. Do nothing in that case.
914 const Extension* extension = 1120 const Extension* extension =
915 extension_service_->GetExtensionById(extension_id_prompting_, true); 1121 extension_service_->GetExtensionById(extension_id_prompting_, true);
916 if (!extension) 1122 if (!extension)
917 return; 1123 return;
918 1124
919 extension_service_->UninstallExtension(extension_id_prompting_, 1125 extension_service_->UninstallExtension(extension_id_prompting_,
920 false /* external_uninstall */, NULL); 1126 false /* external_uninstall */, NULL);
921 1127 CleanupAfterUninstall();
922 extension_id_prompting_ = "";
923 } 1128 }
924 1129
925 void AppLauncherHandler::ExtensionUninstallCanceled() { 1130 void AppLauncherHandler::ExtensionUninstallCanceled() {
926 extension_id_prompting_ = ""; 1131 CleanupAfterUninstall();
927 } 1132 }
928 1133
929 void AppLauncherHandler::InstallUIProceed() { 1134 void AppLauncherHandler::InstallUIProceed() {
930 // Do the re-enable work here. 1135 // Do the re-enable work here.
931 DCHECK(!extension_id_prompting_.empty()); 1136 DCHECK(!extension_id_prompting_.empty());
932 1137
933 // The extension can be uninstalled in another window while the UI was 1138 // The extension can be uninstalled in another window while the UI was
934 // showing. Do nothing in that case. 1139 // showing. Do nothing in that case.
935 const Extension* extension = 1140 const Extension* extension =
936 extension_service_->GetExtensionById(extension_id_prompting_, true); 1141 extension_service_->GetExtensionById(extension_id_prompting_, true);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 1186
982 void AppLauncherHandler::UninstallDefaultApps() { 1187 void AppLauncherHandler::UninstallDefaultApps() {
983 AppsPromo* apps_promo = extension_service_->apps_promo(); 1188 AppsPromo* apps_promo = extension_service_->apps_promo();
984 const ExtensionIdSet& app_ids = apps_promo->old_default_apps(); 1189 const ExtensionIdSet& app_ids = apps_promo->old_default_apps();
985 for (ExtensionIdSet::const_iterator iter = app_ids.begin(); 1190 for (ExtensionIdSet::const_iterator iter = app_ids.begin();
986 iter != app_ids.end(); ++iter) { 1191 iter != app_ids.end(); ++iter) {
987 if (extension_service_->GetExtensionById(*iter, true)) 1192 if (extension_service_->GetExtensionById(*iter, true))
988 extension_service_->UninstallExtension(*iter, false, NULL); 1193 extension_service_->UninstallExtension(*iter, false, NULL);
989 } 1194 }
990 } 1195 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/webui/ntp/app_launcher_handler.h ('k') | chrome/common/pref_names.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698