| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 CHECK(bucket < extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); | 64 CHECK(bucket < extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); |
| 65 return bucket; | 65 return bucket; |
| 66 } | 66 } |
| 67 | 67 |
| 68 } // namespace | 68 } // namespace |
| 69 | 69 |
| 70 AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service) | 70 AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service) |
| 71 : extension_service_(extension_service), | 71 : extension_service_(extension_service), |
| 72 ignore_changes_(false), | 72 ignore_changes_(false), |
| 73 attempted_bookmark_app_install_(false), | 73 attempted_bookmark_app_install_(false), |
| 74 has_loaded_apps_(false) { | 74 has_loaded_apps_(false), |
| 75 uninstall_from_page_(false) { |
| 75 } | 76 } |
| 76 | 77 |
| 77 AppLauncherHandler::~AppLauncherHandler() {} | 78 AppLauncherHandler::~AppLauncherHandler() {} |
| 78 | 79 |
| 79 // Serializes |notification| into a new DictionaryValue which the caller then | 80 // Serializes |notification| into a new DictionaryValue which the caller then |
| 80 // owns. | 81 // owns. |
| 81 static DictionaryValue* SerializeNotification( | 82 static DictionaryValue* SerializeNotification( |
| 82 const AppNotification& notification) { | 83 const AppNotification& notification) { |
| 83 DictionaryValue* dictionary = new DictionaryValue(); | 84 DictionaryValue* dictionary = new DictionaryValue(); |
| 84 dictionary->SetString("title", notification.title()); | 85 dictionary->SetString("title", notification.title()); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 // Make sure every app has a launch index (some predate the launch index). | 164 // Make sure every app has a launch index (some predate the launch index). |
| 164 // The webstore's app launch index is set to -2 to make sure it's first. | 165 // The webstore's app launch index is set to -2 to make sure it's first. |
| 165 // The next time the user drags (any) app this will be set to something | 166 // The next time the user drags (any) app this will be set to something |
| 166 // sane (i.e. >= 0). | 167 // sane (i.e. >= 0). |
| 167 app_launch_index = extension->id() == extension_misc::kWebStoreAppId ? | 168 app_launch_index = extension->id() == extension_misc::kWebStoreAppId ? |
| 168 -2 : prefs->GetNextAppLaunchIndex(0); | 169 -2 : prefs->GetNextAppLaunchIndex(0); |
| 169 prefs->SetAppLaunchIndex(extension->id(), app_launch_index); | 170 prefs->SetAppLaunchIndex(extension->id(), app_launch_index); |
| 170 } | 171 } |
| 171 value->SetInteger("app_launch_index", app_launch_index); | 172 value->SetInteger("app_launch_index", app_launch_index); |
| 172 | 173 |
| 173 int page_index = prefs->GetPageIndex(extension->id()); | 174 EnsureAppHasPageIndex(service, extension->id()); |
| 174 if (page_index < 0) { | 175 value->SetInteger("page_index", prefs->GetPageIndex(extension->id())); |
| 175 // Make sure every app has a page index (some predate the page index). | |
| 176 // The webstore app should be on the first page. | |
| 177 page_index = extension->id() == extension_misc::kWebStoreAppId ? | |
| 178 0 : prefs->GetNaturalAppPageIndex(); | |
| 179 prefs->SetPageIndex(extension->id(), page_index); | |
| 180 } | |
| 181 value->SetInteger("page_index", page_index); | |
| 182 } | 176 } |
| 183 | 177 |
| 184 WebUIMessageHandler* AppLauncherHandler::Attach(WebUI* web_ui) { | 178 WebUIMessageHandler* AppLauncherHandler::Attach(WebUI* web_ui) { |
| 185 registrar_.Add(this, chrome::NOTIFICATION_APP_INSTALLED_TO_NTP, | 179 registrar_.Add(this, chrome::NOTIFICATION_APP_INSTALLED_TO_NTP, |
| 186 content::Source<TabContents>(web_ui->tab_contents())); | 180 content::Source<TabContents>(web_ui->tab_contents())); |
| 187 return WebUIMessageHandler::Attach(web_ui); | 181 return WebUIMessageHandler::Attach(web_ui); |
| 188 } | 182 } |
| 189 | 183 |
| 190 void AppLauncherHandler::RegisterMessages() { | 184 void AppLauncherHandler::RegisterMessages() { |
| 185 web_ui_->RegisterMessageCallback("deleteAppsPage", |
| 186 base::Bind(&AppLauncherHandler::HandleDeleteAppsPage, |
| 187 base::Unretained(this))); |
| 191 web_ui_->RegisterMessageCallback("getApps", | 188 web_ui_->RegisterMessageCallback("getApps", |
| 192 base::Bind(&AppLauncherHandler::HandleGetApps, | 189 base::Bind(&AppLauncherHandler::HandleGetApps, |
| 193 base::Unretained(this))); | 190 base::Unretained(this))); |
| 194 web_ui_->RegisterMessageCallback("launchApp", | 191 web_ui_->RegisterMessageCallback("launchApp", |
| 195 base::Bind(&AppLauncherHandler::HandleLaunchApp, | 192 base::Bind(&AppLauncherHandler::HandleLaunchApp, |
| 196 base::Unretained(this))); | 193 base::Unretained(this))); |
| 197 web_ui_->RegisterMessageCallback("setLaunchType", | 194 web_ui_->RegisterMessageCallback("setLaunchType", |
| 198 base::Bind(&AppLauncherHandler::HandleSetLaunchType, | 195 base::Bind(&AppLauncherHandler::HandleSetLaunchType, |
| 199 base::Unretained(this))); | 196 base::Unretained(this))); |
| 200 web_ui_->RegisterMessageCallback("uninstallApp", | 197 web_ui_->RegisterMessageCallback("uninstallApp", |
| 201 base::Bind(&AppLauncherHandler::HandleUninstallApp, | 198 base::Bind(&AppLauncherHandler::HandleUninstallApp, |
| 202 base::Unretained(this))); | 199 base::Unretained(this))); |
| 203 web_ui_->RegisterMessageCallback("hideAppsPromo", | 200 web_ui_->RegisterMessageCallback("hideAppsPromo", |
| 204 base::Bind(&AppLauncherHandler::HandleHideAppsPromo, | 201 base::Bind(&AppLauncherHandler::HandleHideAppsPromo, |
| 205 base::Unretained(this))); | 202 base::Unretained(this))); |
| 206 web_ui_->RegisterMessageCallback("createAppShortcut", | 203 web_ui_->RegisterMessageCallback("createAppShortcut", |
| 207 base::Bind(&AppLauncherHandler::HandleCreateAppShortcut, | 204 base::Bind(&AppLauncherHandler::HandleCreateAppShortcut, |
| 208 base::Unretained(this))); | 205 base::Unretained(this))); |
| 209 web_ui_->RegisterMessageCallback("reorderApps", | 206 web_ui_->RegisterMessageCallback("reorderApps", |
| 210 base::Bind(&AppLauncherHandler::HandleReorderApps, | 207 base::Bind(&AppLauncherHandler::HandleReorderApps, |
| 211 base::Unretained(this))); | 208 base::Unretained(this))); |
| 212 web_ui_->RegisterMessageCallback("setPageIndex", | 209 web_ui_->RegisterMessageCallback("setPageIndex", |
| 213 base::Bind(&AppLauncherHandler::HandleSetPageIndex, | 210 base::Bind(&AppLauncherHandler::HandleSetPageIndex, |
| 214 base::Unretained(this))); | 211 base::Unretained(this))); |
| 215 web_ui_->RegisterMessageCallback("promoSeen", | 212 web_ui_->RegisterMessageCallback("promoSeen", |
| 216 base::Bind(&AppLauncherHandler::HandlePromoSeen, | 213 base::Bind(&AppLauncherHandler::HandlePromoSeen, |
| 217 base::Unretained(this))); | 214 base::Unretained(this))); |
| 218 web_ui_->RegisterMessageCallback("saveAppPageName", | 215 web_ui_->RegisterMessageCallback("saveAppsPageName", |
| 219 base::Bind(&AppLauncherHandler::HandleSaveAppPageName, | 216 base::Bind(&AppLauncherHandler::HandleSaveAppsPageName, |
| 220 base::Unretained(this))); | 217 base::Unretained(this))); |
| 221 web_ui_->RegisterMessageCallback("generateAppForLink", | 218 web_ui_->RegisterMessageCallback("generateAppForLink", |
| 222 base::Bind(&AppLauncherHandler::HandleGenerateAppForLink, | 219 base::Bind(&AppLauncherHandler::HandleGenerateAppForLink, |
| 223 base::Unretained(this))); | 220 base::Unretained(this))); |
| 224 web_ui_->RegisterMessageCallback("recordAppLaunchByURL", | 221 web_ui_->RegisterMessageCallback("recordAppLaunchByURL", |
| 225 base::Bind(&AppLauncherHandler::HandleRecordAppLaunchByURL, | 222 base::Bind(&AppLauncherHandler::HandleRecordAppLaunchByURL, |
| 226 base::Unretained(this))); | 223 base::Unretained(this))); |
| 227 web_ui_->RegisterMessageCallback("closeNotification", | 224 web_ui_->RegisterMessageCallback("closeNotification", |
| 228 base::Bind(&AppLauncherHandler::HandleNotificationClose, | 225 base::Bind(&AppLauncherHandler::HandleNotificationClose, |
| 229 base::Unretained(this))); | 226 base::Unretained(this))); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 content::Details<UnloadedExtensionInfo>(details)->extension; | 283 content::Details<UnloadedExtensionInfo>(details)->extension; |
| 287 if (!extension->is_app()) | 284 if (!extension->is_app()) |
| 288 return; | 285 return; |
| 289 | 286 |
| 290 scoped_ptr<DictionaryValue> app_info(GetAppInfo(extension)); | 287 scoped_ptr<DictionaryValue> app_info(GetAppInfo(extension)); |
| 291 scoped_ptr<base::FundamentalValue> uninstall_value( | 288 scoped_ptr<base::FundamentalValue> uninstall_value( |
| 292 Value::CreateBooleanValue( | 289 Value::CreateBooleanValue( |
| 293 content::Details<UnloadedExtensionInfo>(details)->reason == | 290 content::Details<UnloadedExtensionInfo>(details)->reason == |
| 294 extension_misc::UNLOAD_REASON_UNINSTALL)); | 291 extension_misc::UNLOAD_REASON_UNINSTALL)); |
| 295 if (app_info.get()) { | 292 if (app_info.get()) { |
| 293 scoped_ptr<base::FundamentalValue> from_page( |
| 294 Value::CreateBooleanValue(uninstall_from_page_)); |
| 296 web_ui_->CallJavascriptFunction( | 295 web_ui_->CallJavascriptFunction( |
| 297 "ntp4.appRemoved", *app_info, *uninstall_value); | 296 "ntp4.appRemoved", *app_info, *uninstall_value, *from_page); |
| 298 } | 297 } |
| 299 break; | 298 break; |
| 300 } | 299 } |
| 301 case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED: | 300 case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED: { |
| 302 // The promo may not load until a couple seconds after the first NTP view, | 301 DictionaryValue pages; |
| 303 // so we listen for the load notification and notify the NTP when ready. | 302 const ExtensionSet* extensions = extension_service_->extensions(); |
| 304 case chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED: | 303 ExtensionPrefs* prefs = extension_service_->extension_prefs(); |
| 305 // TODO(estade): try to get rid of this inefficient operation. | 304 for (ExtensionSet::const_iterator it = extensions->begin(); |
| 305 it != extensions->end(); ++it) { |
| 306 if (!IsAppExcludedFromList(*it)) { |
| 307 std::string page_index = |
| 308 base::IntToString(prefs->GetPageIndex((*it)->id())); |
| 309 if (!pages.HasKey(page_index)) |
| 310 pages.Set(page_index, new DictionaryValue()); |
| 311 DictionaryValue* page; |
| 312 CHECK(pages.GetDictionary(page_index, &page)); |
| 313 page->SetString( |
| 314 base::IntToString(prefs->GetAppLaunchIndex((*it)->id())), |
| 315 (*it)->id()); |
| 316 } |
| 317 } |
| 318 web_ui_->CallJavascriptFunction("ntp4.appsReordered", pages); |
| 319 break; |
| 320 } |
| 321 case chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED: { |
| 322 // The promo may not load until a couple seconds after the first NTP view, |
| 323 // so we listen for the load notification and notify the NTP when ready. |
| 306 HandleGetApps(NULL); | 324 HandleGetApps(NULL); |
| 307 break; | 325 break; |
| 326 } |
| 308 case chrome::NOTIFICATION_PREF_CHANGED: { | 327 case chrome::NOTIFICATION_PREF_CHANGED: { |
| 309 DictionaryValue dictionary; | 328 DictionaryValue dictionary; |
| 310 FillAppDictionary(&dictionary); | 329 FillAppDictionary(&dictionary); |
| 311 web_ui_->CallJavascriptFunction("appsPrefChangeCallback", dictionary); | 330 web_ui_->CallJavascriptFunction("appsPrefChangeCallback", dictionary); |
| 312 break; | 331 break; |
| 313 } | 332 } |
| 314 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: { | 333 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: { |
| 315 CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr(); | 334 CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr(); |
| 316 if (!Profile::FromWebUI(web_ui_)->IsSameProfile(crx_installer->profile())) | 335 if (!Profile::FromWebUI(web_ui_)->IsSameProfile(crx_installer->profile())) |
| 317 return; | 336 return; |
| 318 // Fall Through. | 337 // Fall Through. |
| 319 } | 338 } |
| 320 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: { | 339 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: { |
| 321 attempted_bookmark_app_install_ = false; | 340 attempted_bookmark_app_install_ = false; |
| 322 break; | 341 break; |
| 323 } | 342 } |
| 324 default: | 343 default: |
| 325 NOTREACHED(); | 344 NOTREACHED(); |
| 326 } | 345 } |
| 327 } | 346 } |
| 328 | 347 |
| 348 // static |
| 349 void AppLauncherHandler::EnsureAppHasPageIndex(ExtensionService* service, |
| 350 const std::string& id) { |
| 351 if (service->extension_prefs()->GetPageIndex(id) < 0) { |
| 352 // Make sure every app has a page index (some predate the page index). |
| 353 // The webstore app should be on the first page. |
| 354 int page_index = id == extension_misc::kWebStoreAppId ? |
| 355 0 : service->extension_prefs()->GetNaturalAppPageIndex(); |
| 356 service->extension_prefs()->SetPageIndex(id, page_index); |
| 357 } |
| 358 } |
| 359 |
| 329 void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) { | 360 void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) { |
| 330 // CreateAppInfo and ClearPageIndex can change the extension prefs. | 361 // CreateAppInfo and ClearPageIndex can change the extension prefs. |
| 331 AutoReset<bool> auto_reset(&ignore_changes_, true); | 362 AutoReset<bool> auto_reset(&ignore_changes_, true); |
| 332 | 363 |
| 333 ListValue* list = new ListValue(); | 364 ListValue* list = new ListValue(); |
| 334 const ExtensionSet* extensions = extension_service_->extensions(); | 365 const ExtensionSet* extensions = extension_service_->extensions(); |
| 335 ExtensionSet::const_iterator it; | 366 ExtensionSet::const_iterator it; |
| 336 for (it = extensions->begin(); it != extensions->end(); ++it) { | 367 for (it = extensions->begin(); it != extensions->end(); ++it) { |
| 337 const Extension* extension = *it; | 368 const Extension* extension = *it; |
| 338 if (!IsAppExcludedFromList(extension)) { | 369 if (!IsAppExcludedFromList(extension)) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 extension_service_->apps_promo()->ShouldShowAppLauncher( | 425 extension_service_->apps_promo()->ShouldShowAppLauncher( |
| 395 extension_service_->GetAppIds())); | 426 extension_service_->GetAppIds())); |
| 396 | 427 |
| 397 PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs(); | 428 PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs(); |
| 398 const ListValue* app_page_names = prefs->GetList(prefs::kNTPAppPageNames); | 429 const ListValue* app_page_names = prefs->GetList(prefs::kNTPAppPageNames); |
| 399 if (!app_page_names || !app_page_names->GetSize()) { | 430 if (!app_page_names || !app_page_names->GetSize()) { |
| 400 ListPrefUpdate update(prefs, prefs::kNTPAppPageNames); | 431 ListPrefUpdate update(prefs, prefs::kNTPAppPageNames); |
| 401 ListValue* list = update.Get(); | 432 ListValue* list = update.Get(); |
| 402 list->Set(0, Value::CreateStringValue( | 433 list->Set(0, Value::CreateStringValue( |
| 403 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME))); | 434 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME))); |
| 404 dictionary->Set("appPageNames", | 435 dictionary->Set("appsPageNames", |
| 405 static_cast<ListValue*>(list->DeepCopy())); | 436 static_cast<ListValue*>(list->DeepCopy())); |
| 406 } else { | 437 } else { |
| 407 dictionary->Set("appPageNames", | 438 dictionary->Set("appsPageNames", |
| 408 static_cast<ListValue*>(app_page_names->DeepCopy())); | 439 static_cast<ListValue*>(app_page_names->DeepCopy())); |
| 409 } | 440 } |
| 410 } | 441 } |
| 411 | 442 |
| 412 DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) { | 443 DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) { |
| 413 AppNotificationManager* notification_manager = | 444 AppNotificationManager* notification_manager = |
| 414 extension_service_->app_notification_manager(); | 445 extension_service_->app_notification_manager(); |
| 415 DictionaryValue* app_info = new DictionaryValue(); | 446 DictionaryValue* app_info = new DictionaryValue(); |
| 416 // CreateAppInfo can change the extension prefs. | 447 // CreateAppInfo can change the extension prefs. |
| 417 AutoReset<bool> auto_reset(&ignore_changes_, true); | 448 AutoReset<bool> auto_reset(&ignore_changes_, true); |
| 418 CreateAppInfo(extension, | 449 CreateAppInfo(extension, |
| 419 notification_manager->GetLast(extension->id()), | 450 notification_manager->GetLast(extension->id()), |
| 420 extension_service_, | 451 extension_service_, |
| 421 app_info); | 452 app_info); |
| 422 return app_info; | 453 return app_info; |
| 423 } | 454 } |
| 424 | 455 |
| 425 void AppLauncherHandler::FillPromoDictionary(DictionaryValue* dictionary) { | 456 void AppLauncherHandler::FillPromoDictionary(DictionaryValue* dictionary) { |
| 426 AppsPromo::PromoData data = AppsPromo::GetPromo(); | 457 AppsPromo::PromoData data = AppsPromo::GetPromo(); |
| 427 dictionary->SetString("promoHeader", data.header); | 458 dictionary->SetString("promoHeader", data.header); |
| 428 dictionary->SetString("promoButton", data.button); | 459 dictionary->SetString("promoButton", data.button); |
| 429 dictionary->SetString("promoLink", data.link.spec()); | 460 dictionary->SetString("promoLink", data.link.spec()); |
| 430 dictionary->SetString("promoLogo", data.logo.spec()); | 461 dictionary->SetString("promoLogo", data.logo.spec()); |
| 431 dictionary->SetString("promoExpire", data.expire); | 462 dictionary->SetString("promoExpire", data.expire); |
| 432 } | 463 } |
| 433 | 464 |
| 465 void AppLauncherHandler::HandleDeleteAppsPage(const ListValue* args) { |
| 466 double page_index_double; |
| 467 CHECK(args->GetDouble(0, &page_index_double) && page_index_double >= 0); |
| 468 size_t page_index = static_cast<size_t>(page_index_double); |
| 469 |
| 470 AutoReset<bool> auto_reset(&ignore_changes_, true); |
| 471 |
| 472 DeleteAppsPageRange(page_index, 1); |
| 473 } |
| 474 |
| 475 void AppLauncherHandler::CleanupAfterUninstall() { |
| 476 uninstall_from_page_ = false; |
| 477 extension_id_prompting_ = ""; |
| 478 } |
| 479 |
| 480 void AppLauncherHandler::CondenseAppsPages() { |
| 481 std::vector<bool> has_apps; |
| 482 const ExtensionSet* extensions = extension_service_->extensions(); |
| 483 for (ExtensionSet::const_iterator it = extensions->begin(); |
| 484 it != extensions->end(); ++it) { |
| 485 if (!IsAppExcludedFromList(*it)) { |
| 486 EnsureAppHasPageIndex(extension_service_, (*it)->id()); |
| 487 size_t page_index = |
| 488 extension_service_->extension_prefs()->GetPageIndex((*it)->id()); |
| 489 if (has_apps.size() < page_index + 1) |
| 490 has_apps.resize(page_index + 1); |
| 491 has_apps[page_index] = true; |
| 492 } |
| 493 } |
| 494 |
| 495 // Delete empty ranges of apps pages. |
| 496 int first_empty = -1; |
| 497 for (size_t i = 0; i < has_apps.size(); ++i) { |
| 498 if (!has_apps[i]) { |
| 499 if (first_empty == -1) |
| 500 first_empty = i; |
| 501 } else if (first_empty != -1) { |
| 502 DeleteAppsPageRange(first_empty, i - first_empty); |
| 503 has_apps.erase(has_apps.begin() + first_empty, has_apps.begin() + i); |
| 504 i -= (i - first_empty); |
| 505 first_empty = -1; |
| 506 } |
| 507 } |
| 508 // Make sure there are no pending empty apps pages at the end of our list. |
| 509 CHECK_EQ(first_empty, -1); |
| 510 } |
| 511 |
| 512 void AppLauncherHandler::DeleteAppsPageRange(size_t index, size_t how_many) { |
| 513 // Delete the apps page name from our prefs. |
| 514 PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs(); |
| 515 ListPrefUpdate update(prefs, prefs::kNTPAppPageNames); |
| 516 ListValue* list = update.Get(); |
| 517 |
| 518 // Index checking is done within list->Remove() and will return false if an |
| 519 // index to remove is negative or larger than the size of the list. This is |
| 520 // intentionally left un-CHECK()-ed in the case that there's a skew between |
| 521 // the list pref size and the last page index of all the apps. |
| 522 for (size_t i = 0; i < how_many; ++i) |
| 523 list->Remove(index, NULL); |
| 524 |
| 525 // Move apps that were on a page past the one we're deleting to their newly |
| 526 // adjusted page index. |
| 527 ExtensionPrefs* ext_prefs = extension_service_->extension_prefs(); |
| 528 const ExtensionSet* extensions = extension_service_->extensions(); |
| 529 for (ExtensionSet::const_iterator it = extensions->begin(); |
| 530 it != extensions->end(); ++it) { |
| 531 // Ignore extensions and the cloud print app (but handle CWS app). |
| 532 if (!IsAppExcludedFromList(*it)) { |
| 533 size_t apps_page_index = |
| 534 static_cast<size_t>(ext_prefs->GetPageIndex((*it)->id())); |
| 535 // Don't delete pages with apps still on them. |
| 536 CHECK(apps_page_index < index || apps_page_index >= (index + how_many)); |
| 537 if (apps_page_index >= (index + how_many)) |
| 538 ext_prefs->SetPageIndex((*it)->id(), apps_page_index - how_many); |
| 539 } |
| 540 } |
| 541 } |
| 542 |
| 434 void AppLauncherHandler::HandleGetApps(const ListValue* args) { | 543 void AppLauncherHandler::HandleGetApps(const ListValue* args) { |
| 435 DictionaryValue dictionary; | 544 DictionaryValue dictionary; |
| 436 | 545 |
| 437 // Tell the client whether to show the promo for this view. We don't do this | 546 // Tell the client whether to show the promo for this view. We don't do this |
| 438 // in the case of PREF_CHANGED because: | 547 // in the case of PREF_CHANGED because: |
| 439 // | 548 // |
| 440 // a) At that point in time, depending on the pref that changed, it can look | 549 // a) At that point in time, depending on the pref that changed, it can look |
| 441 // like the set of apps installed has changed, and we will mark the promo | 550 // like the set of apps installed has changed, and we will mark the promo |
| 442 // expired. | 551 // expired. |
| 443 // b) Conceptually, it doesn't really make sense to count a | 552 // b) Conceptually, it doesn't really make sense to count a |
| (...skipping 10 matching lines...) Expand all Loading... |
| 454 } | 563 } |
| 455 | 564 |
| 456 // If the default apps have just expired (user viewed them too many times with | 565 // If the default apps have just expired (user viewed them too many times with |
| 457 // no interaction), then we uninstall them and focus the recent sites section. | 566 // no interaction), then we uninstall them and focus the recent sites section. |
| 458 if (apps_promo_just_expired) { | 567 if (apps_promo_just_expired) { |
| 459 ignore_changes_ = true; | 568 ignore_changes_ = true; |
| 460 UninstallDefaultApps(); | 569 UninstallDefaultApps(); |
| 461 ignore_changes_ = false; | 570 ignore_changes_ = false; |
| 462 } | 571 } |
| 463 | 572 |
| 573 CondenseAppsPages(); |
| 464 SetAppToBeHighlighted(); | 574 SetAppToBeHighlighted(); |
| 465 FillAppDictionary(&dictionary); | 575 FillAppDictionary(&dictionary); |
| 466 web_ui_->CallJavascriptFunction("getAppsCallback", dictionary); | 576 web_ui_->CallJavascriptFunction("getAppsCallback", dictionary); |
| 467 | 577 |
| 468 // First time we get here we set up the observer so that we can tell update | 578 // First time we get here we set up the observer so that we can tell update |
| 469 // the apps as they change. | 579 // the apps as they change. |
| 470 if (!has_loaded_apps_) { | 580 if (!has_loaded_apps_) { |
| 471 pref_change_registrar_.Init( | 581 pref_change_registrar_.Init( |
| 472 extension_service_->extension_prefs()->pref_service()); | 582 extension_service_->extension_prefs()->pref_service()); |
| 473 pref_change_registrar_.Add(ExtensionPrefs::kExtensionsPref, this); | 583 pref_change_registrar_.Add(ExtensionPrefs::kExtensionsPref, this); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 if (!extension_id_prompting_.empty()) | 707 if (!extension_id_prompting_.empty()) |
| 598 return; // Only one prompt at a time. | 708 return; // Only one prompt at a time. |
| 599 | 709 |
| 600 extension_id_prompting_ = extension_id; | 710 extension_id_prompting_ = extension_id; |
| 601 | 711 |
| 602 bool dont_confirm = false; | 712 bool dont_confirm = false; |
| 603 if (args->GetBoolean(1, &dont_confirm) && dont_confirm) { | 713 if (args->GetBoolean(1, &dont_confirm) && dont_confirm) { |
| 604 AutoReset<bool> auto_reset(&ignore_changes_, true); | 714 AutoReset<bool> auto_reset(&ignore_changes_, true); |
| 605 ExtensionUninstallAccepted(); | 715 ExtensionUninstallAccepted(); |
| 606 } else { | 716 } else { |
| 717 // We don't use an AutoReset<bool> here as the uninstall dialog runs in a |
| 718 // different thread so it's not sync. |
| 719 uninstall_from_page_ = true; |
| 607 GetExtensionUninstallDialog()->ConfirmUninstall(extension); | 720 GetExtensionUninstallDialog()->ConfirmUninstall(extension); |
| 608 } | 721 } |
| 609 } | 722 } |
| 610 | 723 |
| 611 void AppLauncherHandler::HandleHideAppsPromo(const ListValue* args) { | 724 void AppLauncherHandler::HandleHideAppsPromo(const ListValue* args) { |
| 612 // If the user has intentionally hidden the promotion, we'll uninstall all the | 725 // If the user has intentionally hidden the promotion, we'll uninstall all the |
| 613 // default apps (we know the user hasn't installed any apps on their own at | 726 // default apps (we know the user hasn't installed any apps on their own at |
| 614 // this point, or the promotion wouldn't have been shown). | 727 // this point, or the promotion wouldn't have been shown). |
| 615 // TODO(estade): this isn't used right now as we sort out the future of the | 728 // TODO(estade): this isn't used right now as we sort out the future of the |
| 616 // apps promo on ntp4. | 729 // apps promo on ntp4. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 extension_service_->extension_prefs()->SetPageIndex(extension_id, | 780 extension_service_->extension_prefs()->SetPageIndex(extension_id, |
| 668 static_cast<int>(page_index)); | 781 static_cast<int>(page_index)); |
| 669 } | 782 } |
| 670 | 783 |
| 671 void AppLauncherHandler::HandlePromoSeen(const ListValue* args) { | 784 void AppLauncherHandler::HandlePromoSeen(const ListValue* args) { |
| 672 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, | 785 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, |
| 673 extension_misc::PROMO_SEEN, | 786 extension_misc::PROMO_SEEN, |
| 674 extension_misc::PROMO_BUCKET_BOUNDARY); | 787 extension_misc::PROMO_BUCKET_BOUNDARY); |
| 675 } | 788 } |
| 676 | 789 |
| 677 void AppLauncherHandler::HandleSaveAppPageName(const ListValue* args) { | 790 void AppLauncherHandler::HandleSaveAppsPageName(const ListValue* args) { |
| 678 string16 name; | 791 string16 name; |
| 679 CHECK(args->GetString(0, &name)); | 792 CHECK(args->GetString(0, &name)); |
| 680 | 793 |
| 681 double page_index; | 794 double page_index_double; |
| 682 CHECK(args->GetDouble(1, &page_index)); | 795 CHECK(args->GetDouble(1, &page_index_double)); |
| 683 | 796 |
| 684 AutoReset<bool> auto_reset(&ignore_changes_, true); | 797 AutoReset<bool> auto_reset(&ignore_changes_, true); |
| 685 PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs(); | 798 PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs(); |
| 686 ListPrefUpdate update(prefs, prefs::kNTPAppPageNames); | 799 ListPrefUpdate update(prefs, prefs::kNTPAppPageNames); |
| 687 ListValue* list = update.Get(); | 800 ListValue* list = update.Get(); |
| 688 list->Set(static_cast<size_t>(page_index), Value::CreateStringValue(name)); | 801 size_t page_index = static_cast<size_t>(page_index_double); |
| 802 // Though it's valid to set items of a list at a non-existent positive index |
| 803 // (that's greater than the current length), this is not desired in this case |
| 804 // as it creates null values in the middle of the list. Instead, only allow a |
| 805 // save to act as an append when the page being saved is exactly equal to the |
| 806 // length of the list. |
| 807 CHECK(page_index <= list->GetSize()); |
| 808 list->Set(page_index, Value::CreateStringValue(name)); |
| 689 } | 809 } |
| 690 | 810 |
| 691 void AppLauncherHandler::HandleGenerateAppForLink(const ListValue* args) { | 811 void AppLauncherHandler::HandleGenerateAppForLink(const ListValue* args) { |
| 692 std::string url; | 812 std::string url; |
| 693 CHECK(args->GetString(0, &url)); | 813 CHECK(args->GetString(0, &url)); |
| 694 GURL launch_url(url); | 814 GURL launch_url(url); |
| 695 | 815 |
| 696 string16 title; | 816 string16 title; |
| 697 CHECK(args->GetString(1, &title)); | 817 CHECK(args->GetString(1, &title)); |
| 698 | 818 |
| 699 double page_index; | 819 double page_index; |
| 700 CHECK(args->GetDouble(2, &page_index)); | 820 CHECK(args->GetDouble(2, &page_index)); |
| 701 | 821 |
| 822 // TODO(dbeam): Handle third argument (app_launch_index) and pass through |
| 823 // the installation process. |
| 824 |
| 702 Profile* profile = Profile::FromWebUI(web_ui_); | 825 Profile* profile = Profile::FromWebUI(web_ui_); |
| 703 FaviconService* favicon_service = | 826 FaviconService* favicon_service = |
| 704 profile->GetFaviconService(Profile::EXPLICIT_ACCESS); | 827 profile->GetFaviconService(Profile::EXPLICIT_ACCESS); |
| 705 if (!favicon_service) { | 828 if (!favicon_service) { |
| 706 LOG(ERROR) << "No favicon service"; | 829 LOG(ERROR) << "No favicon service"; |
| 707 return; | 830 return; |
| 708 } | 831 } |
| 709 | 832 |
| 710 scoped_ptr<AppInstallInfo> install_info(new AppInstallInfo()); | 833 scoped_ptr<AppInstallInfo> install_info(new AppInstallInfo()); |
| 711 install_info->is_bookmark_app = true; | 834 install_info->is_bookmark_app = true; |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 | 1007 |
| 885 // The extension can be uninstalled in another window while the UI was | 1008 // The extension can be uninstalled in another window while the UI was |
| 886 // showing. Do nothing in that case. | 1009 // showing. Do nothing in that case. |
| 887 const Extension* extension = | 1010 const Extension* extension = |
| 888 extension_service_->GetExtensionById(extension_id_prompting_, true); | 1011 extension_service_->GetExtensionById(extension_id_prompting_, true); |
| 889 if (!extension) | 1012 if (!extension) |
| 890 return; | 1013 return; |
| 891 | 1014 |
| 892 extension_service_->UninstallExtension(extension_id_prompting_, | 1015 extension_service_->UninstallExtension(extension_id_prompting_, |
| 893 false /* external_uninstall */, NULL); | 1016 false /* external_uninstall */, NULL); |
| 894 | 1017 CleanupAfterUninstall(); |
| 895 extension_id_prompting_ = ""; | |
| 896 } | 1018 } |
| 897 | 1019 |
| 898 void AppLauncherHandler::ExtensionUninstallCanceled() { | 1020 void AppLauncherHandler::ExtensionUninstallCanceled() { |
| 899 extension_id_prompting_ = ""; | 1021 CleanupAfterUninstall(); |
| 900 } | 1022 } |
| 901 | 1023 |
| 902 void AppLauncherHandler::InstallUIProceed() { | 1024 void AppLauncherHandler::InstallUIProceed() { |
| 903 // Do the re-enable work here. | 1025 // Do the re-enable work here. |
| 904 DCHECK(!extension_id_prompting_.empty()); | 1026 DCHECK(!extension_id_prompting_.empty()); |
| 905 | 1027 |
| 906 // The extension can be uninstalled in another window while the UI was | 1028 // The extension can be uninstalled in another window while the UI was |
| 907 // showing. Do nothing in that case. | 1029 // showing. Do nothing in that case. |
| 908 const Extension* extension = | 1030 const Extension* extension = |
| 909 extension_service_->GetExtensionById(extension_id_prompting_, true); | 1031 extension_service_->GetExtensionById(extension_id_prompting_, true); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 954 | 1076 |
| 955 void AppLauncherHandler::UninstallDefaultApps() { | 1077 void AppLauncherHandler::UninstallDefaultApps() { |
| 956 AppsPromo* apps_promo = extension_service_->apps_promo(); | 1078 AppsPromo* apps_promo = extension_service_->apps_promo(); |
| 957 const ExtensionIdSet& app_ids = apps_promo->old_default_apps(); | 1079 const ExtensionIdSet& app_ids = apps_promo->old_default_apps(); |
| 958 for (ExtensionIdSet::const_iterator iter = app_ids.begin(); | 1080 for (ExtensionIdSet::const_iterator iter = app_ids.begin(); |
| 959 iter != app_ids.end(); ++iter) { | 1081 iter != app_ids.end(); ++iter) { |
| 960 if (extension_service_->GetExtensionById(*iter, true)) | 1082 if (extension_service_->GetExtensionById(*iter, true)) |
| 961 extension_service_->UninstallExtension(*iter, false, NULL); | 1083 extension_service_->UninstallExtension(*iter, false, NULL); |
| 962 } | 1084 } |
| 963 } | 1085 } |
| OLD | NEW |