OLD | NEW |
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 <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/i18n/rtl.h" | 13 #include "base/i18n/rtl.h" |
14 #include "base/metrics/field_trial.h" | 14 #include "base/metrics/field_trial.h" |
15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
16 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
17 #include "base/string_split.h" | 17 #include "base/string_split.h" |
18 #include "base/string_util.h" | 18 #include "base/string_util.h" |
19 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
20 #include "base/values.h" | 20 #include "base/values.h" |
21 #include "chrome/browser/extensions/app_notification.h" | 21 #include "chrome/browser/extensions/app_notification.h" |
22 #include "chrome/browser/extensions/app_notification_manager.h" | 22 #include "chrome/browser/extensions/app_notification_manager.h" |
23 #include "chrome/browser/extensions/apps_promo.h" | |
24 #include "chrome/browser/extensions/crx_installer.h" | 23 #include "chrome/browser/extensions/crx_installer.h" |
25 #include "chrome/browser/extensions/extension_prefs.h" | 24 #include "chrome/browser/extensions/extension_prefs.h" |
26 #include "chrome/browser/extensions/extension_service.h" | 25 #include "chrome/browser/extensions/extension_service.h" |
27 #include "chrome/browser/extensions/extension_sorting.h" | 26 #include "chrome/browser/extensions/extension_sorting.h" |
28 #include "chrome/browser/extensions/extension_system.h" | 27 #include "chrome/browser/extensions/extension_system.h" |
29 #include "chrome/browser/prefs/pref_service.h" | 28 #include "chrome/browser/prefs/pref_service.h" |
30 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 29 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
31 #include "chrome/browser/profiles/profile.h" | 30 #include "chrome/browser/profiles/profile.h" |
32 #include "chrome/browser/ui/browser_finder.h" | 31 #include "chrome/browser/ui/browser_finder.h" |
33 #include "chrome/browser/ui/browser_tabstrip.h" | 32 #include "chrome/browser/ui/browser_tabstrip.h" |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 base::Unretained(this))); | 206 base::Unretained(this))); |
208 web_ui()->RegisterMessageCallback("createAppShortcut", | 207 web_ui()->RegisterMessageCallback("createAppShortcut", |
209 base::Bind(&AppLauncherHandler::HandleCreateAppShortcut, | 208 base::Bind(&AppLauncherHandler::HandleCreateAppShortcut, |
210 base::Unretained(this))); | 209 base::Unretained(this))); |
211 web_ui()->RegisterMessageCallback("reorderApps", | 210 web_ui()->RegisterMessageCallback("reorderApps", |
212 base::Bind(&AppLauncherHandler::HandleReorderApps, | 211 base::Bind(&AppLauncherHandler::HandleReorderApps, |
213 base::Unretained(this))); | 212 base::Unretained(this))); |
214 web_ui()->RegisterMessageCallback("setPageIndex", | 213 web_ui()->RegisterMessageCallback("setPageIndex", |
215 base::Bind(&AppLauncherHandler::HandleSetPageIndex, | 214 base::Bind(&AppLauncherHandler::HandleSetPageIndex, |
216 base::Unretained(this))); | 215 base::Unretained(this))); |
217 web_ui()->RegisterMessageCallback("promoSeen", | |
218 base::Bind(&AppLauncherHandler::HandlePromoSeen, | |
219 base::Unretained(this))); | |
220 web_ui()->RegisterMessageCallback("saveAppPageName", | 216 web_ui()->RegisterMessageCallback("saveAppPageName", |
221 base::Bind(&AppLauncherHandler::HandleSaveAppPageName, | 217 base::Bind(&AppLauncherHandler::HandleSaveAppPageName, |
222 base::Unretained(this))); | 218 base::Unretained(this))); |
223 web_ui()->RegisterMessageCallback("generateAppForLink", | 219 web_ui()->RegisterMessageCallback("generateAppForLink", |
224 base::Bind(&AppLauncherHandler::HandleGenerateAppForLink, | 220 base::Bind(&AppLauncherHandler::HandleGenerateAppForLink, |
225 base::Unretained(this))); | 221 base::Unretained(this))); |
226 web_ui()->RegisterMessageCallback("recordAppLaunchByURL", | 222 web_ui()->RegisterMessageCallback("recordAppLaunchByURL", |
227 base::Bind(&AppLauncherHandler::HandleRecordAppLaunchByURL, | 223 base::Bind(&AppLauncherHandler::HandleRecordAppLaunchByURL, |
228 base::Unretained(this))); | 224 base::Unretained(this))); |
229 web_ui()->RegisterMessageCallback("closeNotification", | 225 web_ui()->RegisterMessageCallback("closeNotification", |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 dictionary->SetBoolean("disableAppWindowLaunch", true); | 376 dictionary->SetBoolean("disableAppWindowLaunch", true); |
381 dictionary->SetBoolean("disableCreateAppShortcut", true); | 377 dictionary->SetBoolean("disableCreateAppShortcut", true); |
382 #endif | 378 #endif |
383 | 379 |
384 #if defined(OS_CHROMEOS) | 380 #if defined(OS_CHROMEOS) |
385 // Making shortcut does not make sense on ChromeOS because it does not have | 381 // Making shortcut does not make sense on ChromeOS because it does not have |
386 // a desktop. | 382 // a desktop. |
387 dictionary->SetBoolean("disableCreateAppShortcut", true); | 383 dictionary->SetBoolean("disableCreateAppShortcut", true); |
388 #endif | 384 #endif |
389 | 385 |
390 dictionary->SetBoolean( | |
391 "showLauncher", | |
392 extension_service_->apps_promo()->ShouldShowAppLauncher( | |
393 extension_service_->GetAppIds())); | |
394 | |
395 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); | 386 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); |
396 const ListValue* app_page_names = prefs->GetList(prefs::kNtpAppPageNames); | 387 const ListValue* app_page_names = prefs->GetList(prefs::kNtpAppPageNames); |
397 if (!app_page_names || !app_page_names->GetSize()) { | 388 if (!app_page_names || !app_page_names->GetSize()) { |
398 ListPrefUpdate update(prefs, prefs::kNtpAppPageNames); | 389 ListPrefUpdate update(prefs, prefs::kNtpAppPageNames); |
399 ListValue* list = update.Get(); | 390 ListValue* list = update.Get(); |
400 list->Set(0, Value::CreateStringValue( | 391 list->Set(0, Value::CreateStringValue( |
401 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME))); | 392 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME))); |
402 dictionary->Set("appPageNames", | 393 dictionary->Set("appPageNames", |
403 static_cast<ListValue*>(list->DeepCopy())); | 394 static_cast<ListValue*>(list->DeepCopy())); |
404 } else { | 395 } else { |
405 dictionary->Set("appPageNames", | 396 dictionary->Set("appPageNames", |
406 static_cast<ListValue*>(app_page_names->DeepCopy())); | 397 static_cast<ListValue*>(app_page_names->DeepCopy())); |
407 } | 398 } |
408 } | 399 } |
409 | 400 |
410 DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) { | 401 DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) { |
411 extensions::AppNotificationManager* notification_manager = | 402 extensions::AppNotificationManager* notification_manager = |
412 extension_service_->app_notification_manager(); | 403 extension_service_->app_notification_manager(); |
413 DictionaryValue* app_info = new DictionaryValue(); | 404 DictionaryValue* app_info = new DictionaryValue(); |
414 // CreateAppInfo can change the extension prefs. | 405 // CreateAppInfo can change the extension prefs. |
415 AutoReset<bool> auto_reset(&ignore_changes_, true); | 406 AutoReset<bool> auto_reset(&ignore_changes_, true); |
416 CreateAppInfo(extension, | 407 CreateAppInfo(extension, |
417 notification_manager->GetLast(extension->id()), | 408 notification_manager->GetLast(extension->id()), |
418 extension_service_, | 409 extension_service_, |
419 app_info); | 410 app_info); |
420 return app_info; | 411 return app_info; |
421 } | 412 } |
422 | 413 |
423 void AppLauncherHandler::FillPromoDictionary(DictionaryValue* dictionary) { | |
424 AppsPromo::PromoData data = AppsPromo::GetPromo(); | |
425 dictionary->SetString("promoHeader", data.header); | |
426 dictionary->SetString("promoButton", data.button); | |
427 dictionary->SetString("promoLink", data.link.spec()); | |
428 dictionary->SetString("promoLogo", data.logo.spec()); | |
429 dictionary->SetString("promoExpire", data.expire); | |
430 } | |
431 | |
432 void AppLauncherHandler::HandleGetApps(const ListValue* args) { | 414 void AppLauncherHandler::HandleGetApps(const ListValue* args) { |
433 DictionaryValue dictionary; | 415 DictionaryValue dictionary; |
434 | 416 |
435 // Tell the client whether to show the promo for this view. We don't do this | 417 // Tell the client whether to show the promo for this view. We don't do this |
436 // in the case of PREF_CHANGED because: | 418 // in the case of PREF_CHANGED because: |
437 // | 419 // |
438 // a) At that point in time, depending on the pref that changed, it can look | 420 // a) At that point in time, depending on the pref that changed, it can look |
439 // like the set of apps installed has changed, and we will mark the promo | 421 // like the set of apps installed has changed, and we will mark the promo |
440 // expired. | 422 // expired. |
441 // b) Conceptually, it doesn't really make sense to count a | 423 // b) Conceptually, it doesn't really make sense to count a |
442 // prefchange-triggered refresh as a promo 'view'. | 424 // prefchange-triggered refresh as a promo 'view'. |
443 AppsPromo* apps_promo = extension_service_->apps_promo(); | |
444 Profile* profile = Profile::FromWebUI(web_ui()); | 425 Profile* profile = Profile::FromWebUI(web_ui()); |
445 bool apps_promo_just_expired = false; | |
446 if (apps_promo->ShouldShowPromo(extension_service_->GetAppIds(), | |
447 &apps_promo_just_expired)) { | |
448 dictionary.SetBoolean("showPromo", true); | |
449 FillPromoDictionary(&dictionary); | |
450 } else { | |
451 dictionary.SetBoolean("showPromo", false); | |
452 } | |
453 | |
454 // If the default apps have just expired (user viewed them too many times with | |
455 // no interaction), then we uninstall them and focus the recent sites section. | |
456 if (apps_promo_just_expired) { | |
457 ignore_changes_ = true; | |
458 UninstallDefaultApps(); | |
459 ignore_changes_ = false; | |
460 } | |
461 | 426 |
462 // The first time we load the apps we must add all current app to the list | 427 // The first time we load the apps we must add all current app to the list |
463 // of apps visible on the NTP. | 428 // of apps visible on the NTP. |
464 if (!has_loaded_apps_) { | 429 if (!has_loaded_apps_) { |
465 const ExtensionSet* extensions = extension_service_->extensions(); | 430 const ExtensionSet* extensions = extension_service_->extensions(); |
466 for (ExtensionSet::const_iterator it = extensions->begin(); | 431 for (ExtensionSet::const_iterator it = extensions->begin(); |
467 it != extensions->end(); ++it) { | 432 it != extensions->end(); ++it) { |
468 visible_apps_.insert((*it)->id()); | 433 visible_apps_.insert((*it)->id()); |
469 } | 434 } |
470 | 435 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 PromptToEnableApp(extension_id); | 501 PromptToEnableApp(extension_id); |
537 return; | 502 return; |
538 } | 503 } |
539 | 504 |
540 Profile* profile = extension_service_->profile(); | 505 Profile* profile = extension_service_->profile(); |
541 | 506 |
542 WindowOpenDisposition disposition = args->GetSize() > 3 ? | 507 WindowOpenDisposition disposition = args->GetSize() > 3 ? |
543 web_ui_util::GetDispositionFromClick(args, 3) : CURRENT_TAB; | 508 web_ui_util::GetDispositionFromClick(args, 3) : CURRENT_TAB; |
544 if (extension_id != extension_misc::kWebStoreAppId) { | 509 if (extension_id != extension_misc::kWebStoreAppId) { |
545 RecordAppLaunchByID(launch_bucket); | 510 RecordAppLaunchByID(launch_bucket); |
546 extension_service_->apps_promo()->ExpireDefaultApps(); | |
547 } else { | 511 } else { |
548 RecordWebStoreLaunch(url.find("chrome-ntp-promo") != std::string::npos); | 512 RecordWebStoreLaunch(); |
549 } | 513 } |
550 | 514 |
551 if (disposition == NEW_FOREGROUND_TAB || disposition == NEW_BACKGROUND_TAB || | 515 if (disposition == NEW_FOREGROUND_TAB || disposition == NEW_BACKGROUND_TAB || |
552 disposition == NEW_WINDOW) { | 516 disposition == NEW_WINDOW) { |
553 // TODO(jamescook): Proper support for background tabs. | 517 // TODO(jamescook): Proper support for background tabs. |
554 LaunchParams params(profile, extension, | 518 LaunchParams params(profile, extension, |
555 disposition == NEW_WINDOW ? | 519 disposition == NEW_WINDOW ? |
556 extension_misc::LAUNCH_WINDOW : | 520 extension_misc::LAUNCH_WINDOW : |
557 extension_misc::LAUNCH_TAB, | 521 extension_misc::LAUNCH_TAB, |
558 disposition); | 522 disposition); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 CHECK(args->GetDouble(1, &page_index)); | 651 CHECK(args->GetDouble(1, &page_index)); |
688 const StringOrdinal& page_ordinal = | 652 const StringOrdinal& page_ordinal = |
689 extension_sorting->PageIntegerAsStringOrdinal( | 653 extension_sorting->PageIntegerAsStringOrdinal( |
690 static_cast<size_t>(page_index)); | 654 static_cast<size_t>(page_index)); |
691 | 655 |
692 // Don't update the page; it already knows the apps have been reordered. | 656 // Don't update the page; it already knows the apps have been reordered. |
693 AutoReset<bool> auto_reset(&ignore_changes_, true); | 657 AutoReset<bool> auto_reset(&ignore_changes_, true); |
694 extension_sorting->SetPageOrdinal(extension_id, page_ordinal); | 658 extension_sorting->SetPageOrdinal(extension_id, page_ordinal); |
695 } | 659 } |
696 | 660 |
697 void AppLauncherHandler::HandlePromoSeen(const ListValue* args) { | |
698 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, | |
699 extension_misc::PROMO_SEEN, | |
700 extension_misc::PROMO_BUCKET_BOUNDARY); | |
701 } | |
702 | |
703 void AppLauncherHandler::HandleSaveAppPageName(const ListValue* args) { | 661 void AppLauncherHandler::HandleSaveAppPageName(const ListValue* args) { |
704 string16 name; | 662 string16 name; |
705 CHECK(args->GetString(0, &name)); | 663 CHECK(args->GetString(0, &name)); |
706 | 664 |
707 double page_index; | 665 double page_index; |
708 CHECK(args->GetDouble(1, &page_index)); | 666 CHECK(args->GetDouble(1, &page_index)); |
709 | 667 |
710 AutoReset<bool> auto_reset(&ignore_changes_, true); | 668 AutoReset<bool> auto_reset(&ignore_changes_, true); |
711 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); | 669 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); |
712 ListPrefUpdate update(prefs, prefs::kNtpAppPageNames); | 670 ListPrefUpdate update(prefs, prefs::kNtpAppPageNames); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 } | 801 } |
844 | 802 |
845 // static | 803 // static |
846 void AppLauncherHandler::RecordAppLaunchType( | 804 void AppLauncherHandler::RecordAppLaunchType( |
847 extension_misc::AppLaunchBucket bucket) { | 805 extension_misc::AppLaunchBucket bucket) { |
848 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram, bucket, | 806 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram, bucket, |
849 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); | 807 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); |
850 } | 808 } |
851 | 809 |
852 // static | 810 // static |
853 void AppLauncherHandler::RecordWebStoreLaunch(bool promo_active) { | 811 void AppLauncherHandler::RecordWebStoreLaunch() { |
854 RecordAppLaunchType(extension_misc::APP_LAUNCH_NTP_WEBSTORE); | 812 RecordAppLaunchType(extension_misc::APP_LAUNCH_NTP_WEBSTORE); |
855 | |
856 if (!promo_active) return; | |
857 | |
858 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, | |
859 extension_misc::PROMO_LAUNCH_WEB_STORE, | |
860 extension_misc::PROMO_BUCKET_BOUNDARY); | |
861 } | 813 } |
862 | 814 |
863 // static | 815 // static |
864 void AppLauncherHandler::RecordAppLaunchByID( | 816 void AppLauncherHandler::RecordAppLaunchByID( |
865 extension_misc::AppLaunchBucket bucket) { | 817 extension_misc::AppLaunchBucket bucket) { |
866 CHECK(bucket != extension_misc::APP_LAUNCH_BUCKET_INVALID); | 818 CHECK(bucket != extension_misc::APP_LAUNCH_BUCKET_INVALID); |
867 | 819 |
868 RecordAppLaunchType(bucket); | 820 RecordAppLaunchType(bucket); |
869 } | 821 } |
870 | 822 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 | 939 |
988 ExtensionInstallPrompt* AppLauncherHandler::GetExtensionInstallPrompt() { | 940 ExtensionInstallPrompt* AppLauncherHandler::GetExtensionInstallPrompt() { |
989 if (!extension_install_ui_.get()) { | 941 if (!extension_install_ui_.get()) { |
990 Browser* browser = browser::FindBrowserWithWebContents( | 942 Browser* browser = browser::FindBrowserWithWebContents( |
991 web_ui()->GetWebContents()); | 943 web_ui()->GetWebContents()); |
992 extension_install_ui_.reset( | 944 extension_install_ui_.reset( |
993 chrome::CreateExtensionInstallPromptWithBrowser(browser)); | 945 chrome::CreateExtensionInstallPromptWithBrowser(browser)); |
994 } | 946 } |
995 return extension_install_ui_.get(); | 947 return extension_install_ui_.get(); |
996 } | 948 } |
997 | |
998 void AppLauncherHandler::UninstallDefaultApps() { | |
999 AppsPromo* apps_promo = extension_service_->apps_promo(); | |
1000 const extensions::ExtensionIdSet& app_ids = apps_promo->old_default_apps(); | |
1001 for (extensions::ExtensionIdSet::const_iterator iter = app_ids.begin(); | |
1002 iter != app_ids.end(); ++iter) { | |
1003 if (extension_service_->GetExtensionById(*iter, true)) | |
1004 extension_service_->UninstallExtension(*iter, false, NULL); | |
1005 } | |
1006 } | |
OLD | NEW |