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

Unified 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: adding back erroneously removed ; Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/webui/ntp/app_launcher_handler.cc
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index d0b075db106d60b779bef20b5b5e4abacb3bfc34..03b1ebea1a74fc2df1aa6b24fd3a47439a77bc26 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -72,7 +72,8 @@ AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service)
: extension_service_(extension_service),
ignore_changes_(false),
attempted_bookmark_app_install_(false),
- has_loaded_apps_(false) {
+ has_loaded_apps_(false),
+ uninstall_from_page_(false) {
}
AppLauncherHandler::~AppLauncherHandler() {}
@@ -165,15 +166,8 @@ void AppLauncherHandler::CreateAppInfo(const Extension* extension,
}
value->SetInteger("app_launch_index", app_launch_index);
- int page_index = prefs->GetPageIndex(extension->id());
- if (page_index < 0) {
- // Make sure every app has a page index (some predate the page index).
- // The webstore app should be on the first page.
- page_index = extension->id() == extension_misc::kWebStoreAppId ?
- 0 : prefs->GetNaturalAppPageIndex();
- prefs->SetPageIndex(extension->id(), page_index);
- }
- value->SetInteger("page_index", page_index);
+ EnsureAppHasPageIndex(service, extension->id());
+ value->SetInteger("page_index", prefs->GetPageIndex(extension->id()));
}
WebUIMessageHandler* AppLauncherHandler::Attach(WebUI* web_ui) {
@@ -183,6 +177,9 @@ WebUIMessageHandler* AppLauncherHandler::Attach(WebUI* web_ui) {
}
void AppLauncherHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("deleteAppsPage",
+ base::Bind(&AppLauncherHandler::HandleDeleteAppsPage,
+ base::Unretained(this)));
web_ui_->RegisterMessageCallback("getApps",
base::Bind(&AppLauncherHandler::HandleGetApps,
base::Unretained(this)));
@@ -210,8 +207,8 @@ void AppLauncherHandler::RegisterMessages() {
web_ui_->RegisterMessageCallback("promoSeen",
base::Bind(&AppLauncherHandler::HandlePromoSeen,
base::Unretained(this)));
- web_ui_->RegisterMessageCallback("saveAppPageName",
- base::Bind(&AppLauncherHandler::HandleSaveAppPageName,
+ web_ui_->RegisterMessageCallback("saveAppsPageName",
+ base::Bind(&AppLauncherHandler::HandleSaveAppsPageName,
base::Unretained(this)));
web_ui_->RegisterMessageCallback("generateAppForLink",
base::Bind(&AppLauncherHandler::HandleGenerateAppForLink,
@@ -289,18 +286,41 @@ void AppLauncherHandler::Observe(int type,
content::Details<UnloadedExtensionInfo>(details)->reason ==
extension_misc::UNLOAD_REASON_UNINSTALL));
if (app_info.get()) {
+ scoped_ptr<base::FundamentalValue>
+ from_page(Value::CreateBooleanValue(uninstall_from_page_));
web_ui_->CallJavascriptFunction(
- "ntp4.appRemoved", *app_info, *uninstall_value);
+ "ntp4.appRemoved", *app_info, *uninstall_value, *from_page);
+ uninstall_from_page_ = false;
+ }
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED: {
+ DictionaryValue pages;
+ const ExtensionList* extensions = extension_service_->extensions();
+ ExtensionPrefs* prefs = extension_service_->extension_prefs();
+ for (ExtensionList::const_iterator it = extensions->begin();
+ it != extensions->end(); ++it) {
+ if (!IsAppExcludedFromList(*it)) {
+ std::string page_index =
+ base::IntToString(prefs->GetPageIndex((*it)->id()));
+ if (!pages.HasKey(page_index))
+ pages.Set(page_index, new DictionaryValue());
+ DictionaryValue* page;
+ CHECK(pages.GetDictionary(page_index, &page));
+ page->SetString(
+ base::IntToString(prefs->GetAppLaunchIndex((*it)->id())),
+ (*it)->id());
+ }
}
+ web_ui_->CallJavascriptFunction("ntp4.appsReordered", pages);
break;
}
- case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED:
- // The promo may not load until a couple seconds after the first NTP view,
- // so we listen for the load notification and notify the NTP when ready.
- case chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED:
- // TODO(estade): try to get rid of this inefficient operation.
+ case chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED: {
+ // The promo may not load until a couple seconds after the first NTP view,
+ // so we listen for the load notification and notify the NTP when ready.
HandleGetApps(NULL);
break;
+ }
case chrome::NOTIFICATION_PREF_CHANGED: {
DictionaryValue dictionary;
FillAppDictionary(&dictionary);
@@ -322,6 +342,18 @@ void AppLauncherHandler::Observe(int type,
}
}
+// static
+void AppLauncherHandler::EnsureAppHasPageIndex(ExtensionService* service,
+ const std::string& id) {
+ if (service->extension_prefs()->GetPageIndex(id) < 0) {
+ // Make sure every app has a page index (some predate the page index).
+ // The webstore app should be on the first page.
+ int page_index = id == extension_misc::kWebStoreAppId ?
+ 0 : service->extension_prefs()->GetNaturalAppPageIndex();
+ service->extension_prefs()->SetPageIndex(id, page_index);
+ }
+}
+
void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) {
// CreateAppInfo and ClearPageIndex can change the extension prefs.
AutoReset<bool> auto_reset(&ignore_changes_, true);
@@ -396,10 +428,10 @@ void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) {
ListValue* list = update.Get();
list->Set(0, Value::CreateStringValue(
l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME)));
- dictionary->Set("appPageNames",
+ dictionary->Set("appsPageNames",
static_cast<ListValue*>(list->DeepCopy()));
} else {
- dictionary->Set("appPageNames",
+ dictionary->Set("appsPageNames",
static_cast<ListValue*>(app_page_names->DeepCopy()));
}
}
@@ -426,6 +458,79 @@ void AppLauncherHandler::FillPromoDictionary(DictionaryValue* dictionary) {
dictionary->SetString("promoExpire", data.expire);
}
+void AppLauncherHandler::HandleDeleteAppsPage(const ListValue* args) {
+ double page_index_double;
+ CHECK(args->GetDouble(0, &page_index_double) && page_index_double >= 0);
+ size_t page_index = static_cast<size_t>(page_index_double);
+
+ AutoReset<bool> auto_reset(&ignore_changes_, true);
+
+ DeleteAppsPageRange(page_index, 1);
+}
+
+void AppLauncherHandler::CondenseAppsPages() {
+ std::vector<bool> has_apps;
+ const ExtensionList* extensions = extension_service_->extensions();
+ for (ExtensionList::const_iterator it = extensions->begin();
+ it != extensions->end(); ++it) {
+ if (!IsAppExcludedFromList(*it)) {
+ EnsureAppHasPageIndex(extension_service_, (*it)->id());
+ size_t page_index =
+ extension_service_->extension_prefs()->GetPageIndex((*it)->id());
+ if (has_apps.size() < page_index + 1)
+ has_apps.resize(page_index + 1);
+ has_apps[page_index] = true;
+ }
+ }
+
+ // Delete empty ranges of apps pages.
+ int first_empty = -1;
+ for (size_t i = 0; i < has_apps.size(); ++i) {
+ if (!has_apps[i]) {
+ if (first_empty == -1)
+ first_empty = i;
+ } else if (first_empty != -1) {
+ DeleteAppsPageRange(first_empty, i - first_empty);
+ has_apps.erase(has_apps.begin() + first_empty, has_apps.begin() + i);
+ i -= (i - first_empty);
+ first_empty = -1;
+ }
+ }
+ // Make sure there are no pending empty apps pages at the end of our list.
+ CHECK_EQ(first_empty, -1);
+}
+
+void AppLauncherHandler::DeleteAppsPageRange(size_t index, size_t how_many) {
+ // Delete the apps page name from our prefs.
+ PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs();
+ ListPrefUpdate update(prefs, prefs::kNTPAppPageNames);
+ ListValue* list = update.Get();
+
+ // Index checking is done within list->Remove() and will return false if an
+ // index to remove is negative or larger than the size of the list. This is
+ // intentionally left un-CHECK()-ed in the case that there's a skew between
+ // the list pref size and the last page index of all the apps.
+ for (size_t i = 0; i < how_many; ++i)
+ list->Remove(index, NULL);
+
+ // Move apps that were on a page past the one we're deleting to their newly
+ // adjusted page index.
+ ExtensionPrefs* ext_prefs = extension_service_->extension_prefs();
+ const ExtensionList* extensions = extension_service_->extensions();
+ for (ExtensionList::const_iterator it = extensions->begin();
+ it != extensions->end(); ++it) {
+ // Ignore extensions and the cloud print app (but handle CWS app).
+ if (!IsAppExcludedFromList(*it)) {
+ size_t apps_page_index =
+ static_cast<size_t>(ext_prefs->GetPageIndex((*it)->id()));
+ // Don't delete pages with apps still on them.
+ CHECK(apps_page_index < index || apps_page_index >= (index + how_many));
+ if (apps_page_index >= (index + how_many))
+ ext_prefs->SetPageIndex((*it)->id(), apps_page_index - how_many);
+ }
+ }
+}
+
void AppLauncherHandler::HandleGetApps(const ListValue* args) {
DictionaryValue dictionary;
@@ -456,6 +561,7 @@ void AppLauncherHandler::HandleGetApps(const ListValue* args) {
ignore_changes_ = false;
}
+ CondenseAppsPages();
SetAppToBeHighlighted();
FillAppDictionary(&dictionary);
web_ui_->CallJavascriptFunction("getAppsCallback", dictionary);
@@ -617,6 +723,9 @@ void AppLauncherHandler::HandleUninstallApp(const ListValue* args) {
AutoReset<bool> auto_reset(&ignore_changes_, true);
ExtensionUninstallAccepted();
} else {
+ // We don't use an AutoReset<bool> here as the uninstall dialog runs in a
+ // different thread so it's not sync.
+ uninstall_from_page_ = true;
GetExtensionUninstallDialog()->ConfirmUninstall(extension);
}
}
@@ -687,7 +796,7 @@ void AppLauncherHandler::HandlePromoSeen(const ListValue* args) {
extension_misc::PROMO_BUCKET_BOUNDARY);
}
-void AppLauncherHandler::HandleSaveAppPageName(const ListValue* args) {
+void AppLauncherHandler::HandleSaveAppsPageName(const ListValue* args) {
string16 name;
CHECK(args->GetString(0, &name));

Powered by Google App Engine
This is Rietveld 408576698