| 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 <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/i18n/rtl.h" | 12 #include "base/i18n/rtl.h" |
| 13 #include "base/metrics/field_trial.h" | 13 #include "base/metrics/field_trial.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/prefs/pref_service.h" | 15 #include "base/prefs/pref_service.h" |
| 16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 17 #include "base/values.h" | 17 #include "base/values.h" |
| 18 #include "chrome/browser/extensions/app_notification.h" | |
| 19 #include "chrome/browser/extensions/app_notification_manager.h" | |
| 20 #include "chrome/browser/extensions/crx_installer.h" | 18 #include "chrome/browser/extensions/crx_installer.h" |
| 21 #include "chrome/browser/extensions/extension_prefs.h" | 19 #include "chrome/browser/extensions/extension_prefs.h" |
| 22 #include "chrome/browser/extensions/extension_service.h" | 20 #include "chrome/browser/extensions/extension_service.h" |
| 23 #include "chrome/browser/extensions/extension_sorting.h" | 21 #include "chrome/browser/extensions/extension_sorting.h" |
| 24 #include "chrome/browser/extensions/extension_system.h" | 22 #include "chrome/browser/extensions/extension_system.h" |
| 25 #include "chrome/browser/extensions/management_policy.h" | 23 #include "chrome/browser/extensions/management_policy.h" |
| 26 #include "chrome/browser/favicon/favicon_service_factory.h" | 24 #include "chrome/browser/favicon/favicon_service_factory.h" |
| 27 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 25 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 28 #include "chrome/browser/profiles/profile.h" | 26 #include "chrome/browser/profiles/profile.h" |
| 29 #include "chrome/browser/ui/browser_finder.h" | 27 #include "chrome/browser/ui/browser_finder.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 | 80 |
| 83 AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service) | 81 AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service) |
| 84 : extension_service_(extension_service), | 82 : extension_service_(extension_service), |
| 85 ignore_changes_(false), | 83 ignore_changes_(false), |
| 86 attempted_bookmark_app_install_(false), | 84 attempted_bookmark_app_install_(false), |
| 87 has_loaded_apps_(false) { | 85 has_loaded_apps_(false) { |
| 88 } | 86 } |
| 89 | 87 |
| 90 AppLauncherHandler::~AppLauncherHandler() {} | 88 AppLauncherHandler::~AppLauncherHandler() {} |
| 91 | 89 |
| 92 // Serializes |notification| into a new DictionaryValue which the caller then | |
| 93 // owns. | |
| 94 static DictionaryValue* SerializeNotification( | |
| 95 const extensions::AppNotification& notification) { | |
| 96 DictionaryValue* dictionary = new DictionaryValue(); | |
| 97 dictionary->SetString("title", notification.title()); | |
| 98 dictionary->SetString("body", notification.body()); | |
| 99 if (!notification.link_url().is_empty()) { | |
| 100 dictionary->SetString("linkUrl", notification.link_url().spec()); | |
| 101 dictionary->SetString("linkText", notification.link_text()); | |
| 102 } | |
| 103 return dictionary; | |
| 104 } | |
| 105 | |
| 106 void AppLauncherHandler::CreateAppInfo( | 90 void AppLauncherHandler::CreateAppInfo( |
| 107 const Extension* extension, | 91 const Extension* extension, |
| 108 const extensions::AppNotification* notification, | |
| 109 ExtensionService* service, | 92 ExtensionService* service, |
| 110 DictionaryValue* value) { | 93 DictionaryValue* value) { |
| 111 value->Clear(); | 94 value->Clear(); |
| 112 | 95 |
| 113 // The Extension class 'helpfully' wraps bidi control characters that | 96 // The Extension class 'helpfully' wraps bidi control characters that |
| 114 // impede our ability to determine directionality. | 97 // impede our ability to determine directionality. |
| 115 string16 name = UTF8ToUTF16(extension->name()); | 98 string16 name = UTF8ToUTF16(extension->name()); |
| 116 base::i18n::UnadjustStringForLocaleDirection(&name); | 99 base::i18n::UnadjustStringForLocaleDirection(&name); |
| 117 NewTabUI::SetUrlTitleAndDirection(value, name, extension->GetFullLaunchURL()); | 100 NewTabUI::SetUrlTitleAndDirection(value, name, extension->GetFullLaunchURL()); |
| 118 | 101 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 144 value->SetInteger("launch_container", extension->launch_container()); | 127 value->SetInteger("launch_container", extension->launch_container()); |
| 145 ExtensionPrefs* prefs = service->extension_prefs(); | 128 ExtensionPrefs* prefs = service->extension_prefs(); |
| 146 value->SetInteger("launch_type", | 129 value->SetInteger("launch_type", |
| 147 prefs->GetLaunchType(extension, | 130 prefs->GetLaunchType(extension, |
| 148 ExtensionPrefs::LAUNCH_DEFAULT)); | 131 ExtensionPrefs::LAUNCH_DEFAULT)); |
| 149 value->SetBoolean("is_component", | 132 value->SetBoolean("is_component", |
| 150 extension->location() == extensions::Manifest::COMPONENT); | 133 extension->location() == extensions::Manifest::COMPONENT); |
| 151 value->SetBoolean("is_webstore", | 134 value->SetBoolean("is_webstore", |
| 152 extension->id() == extension_misc::kWebStoreAppId); | 135 extension->id() == extension_misc::kWebStoreAppId); |
| 153 | 136 |
| 154 if (extension->HasAPIPermission( | |
| 155 extensions::APIPermission::kAppNotifications)) { | |
| 156 value->SetBoolean("notifications_disabled", | |
| 157 prefs->IsAppNotificationDisabled(extension->id())); | |
| 158 } | |
| 159 | |
| 160 if (notification) | |
| 161 value->Set("notification", SerializeNotification(*notification)); | |
| 162 | |
| 163 ExtensionSorting* sorting = prefs->extension_sorting(); | 137 ExtensionSorting* sorting = prefs->extension_sorting(); |
| 164 syncer::StringOrdinal page_ordinal = sorting->GetPageOrdinal(extension->id()); | 138 syncer::StringOrdinal page_ordinal = sorting->GetPageOrdinal(extension->id()); |
| 165 if (!page_ordinal.IsValid()) { | 139 if (!page_ordinal.IsValid()) { |
| 166 // Make sure every app has a page ordinal (some predate the page ordinal). | 140 // Make sure every app has a page ordinal (some predate the page ordinal). |
| 167 // The webstore app should be on the first page. | 141 // The webstore app should be on the first page. |
| 168 page_ordinal = extension->id() == extension_misc::kWebStoreAppId ? | 142 page_ordinal = extension->id() == extension_misc::kWebStoreAppId ? |
| 169 sorting->CreateFirstAppPageOrdinal() : | 143 sorting->CreateFirstAppPageOrdinal() : |
| 170 sorting->GetNaturalAppPageOrdinal(); | 144 sorting->GetNaturalAppPageOrdinal(); |
| 171 sorting->SetPageOrdinal(extension->id(), page_ordinal); | 145 sorting->SetPageOrdinal(extension->id(), page_ordinal); |
| 172 } | 146 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 base::Unretained(this))); | 188 base::Unretained(this))); |
| 215 web_ui()->RegisterMessageCallback("saveAppPageName", | 189 web_ui()->RegisterMessageCallback("saveAppPageName", |
| 216 base::Bind(&AppLauncherHandler::HandleSaveAppPageName, | 190 base::Bind(&AppLauncherHandler::HandleSaveAppPageName, |
| 217 base::Unretained(this))); | 191 base::Unretained(this))); |
| 218 web_ui()->RegisterMessageCallback("generateAppForLink", | 192 web_ui()->RegisterMessageCallback("generateAppForLink", |
| 219 base::Bind(&AppLauncherHandler::HandleGenerateAppForLink, | 193 base::Bind(&AppLauncherHandler::HandleGenerateAppForLink, |
| 220 base::Unretained(this))); | 194 base::Unretained(this))); |
| 221 web_ui()->RegisterMessageCallback("recordAppLaunchByURL", | 195 web_ui()->RegisterMessageCallback("recordAppLaunchByURL", |
| 222 base::Bind(&AppLauncherHandler::HandleRecordAppLaunchByUrl, | 196 base::Bind(&AppLauncherHandler::HandleRecordAppLaunchByUrl, |
| 223 base::Unretained(this))); | 197 base::Unretained(this))); |
| 224 web_ui()->RegisterMessageCallback("closeNotification", | |
| 225 base::Bind(&AppLauncherHandler::HandleNotificationClose, | |
| 226 base::Unretained(this))); | |
| 227 web_ui()->RegisterMessageCallback("setNotificationsDisabled", | |
| 228 base::Bind(&AppLauncherHandler::HandleSetNotificationsDisabled, | |
| 229 base::Unretained(this))); | |
| 230 } | 198 } |
| 231 | 199 |
| 232 void AppLauncherHandler::Observe(int type, | 200 void AppLauncherHandler::Observe(int type, |
| 233 const content::NotificationSource& source, | 201 const content::NotificationSource& source, |
| 234 const content::NotificationDetails& details) { | 202 const content::NotificationDetails& details) { |
| 235 if (type == chrome::NOTIFICATION_APP_INSTALLED_TO_NTP) { | 203 if (type == chrome::NOTIFICATION_APP_INSTALLED_TO_NTP) { |
| 236 highlight_app_id_ = *content::Details<const std::string>(details).ptr(); | 204 highlight_app_id_ = *content::Details<const std::string>(details).ptr(); |
| 237 if (has_loaded_apps_) | 205 if (has_loaded_apps_) |
| 238 SetAppToBeHighlighted(); | 206 SetAppToBeHighlighted(); |
| 239 return; | 207 return; |
| 240 } | 208 } |
| 241 | 209 |
| 242 if (ignore_changes_ || !has_loaded_apps_) | 210 if (ignore_changes_ || !has_loaded_apps_) |
| 243 return; | 211 return; |
| 244 | 212 |
| 245 switch (type) { | 213 switch (type) { |
| 246 case chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED: { | |
| 247 const std::string& id = | |
| 248 *content::Details<const std::string>(details).ptr(); | |
| 249 const extensions::AppNotification* notification = | |
| 250 extension_service_->app_notification_manager()->GetLast(id); | |
| 251 base::StringValue id_value(id); | |
| 252 if (notification) { | |
| 253 scoped_ptr<DictionaryValue> notification_value( | |
| 254 SerializeNotification(*notification)); | |
| 255 web_ui()->CallJavascriptFunction("ntp.appNotificationChanged", | |
| 256 id_value, *notification_value.get()); | |
| 257 } else { | |
| 258 web_ui()->CallJavascriptFunction("ntp.appNotificationChanged", | |
| 259 id_value); | |
| 260 } | |
| 261 break; | |
| 262 } | |
| 263 | |
| 264 case chrome::NOTIFICATION_EXTENSION_LOADED: { | 214 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| 265 const Extension* extension = | 215 const Extension* extension = |
| 266 content::Details<const Extension>(details).ptr(); | 216 content::Details<const Extension>(details).ptr(); |
| 267 if (!extension->is_app()) | 217 if (!extension->is_app()) |
| 268 return; | 218 return; |
| 269 | 219 |
| 270 scoped_ptr<DictionaryValue> app_info(GetAppInfo(extension)); | 220 scoped_ptr<DictionaryValue> app_info(GetAppInfo(extension)); |
| 271 if (app_info.get()) { | 221 if (app_info.get()) { |
| 272 visible_apps_.insert(extension->id()); | 222 visible_apps_.insert(extension->id()); |
| 273 | 223 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 break; | 255 break; |
| 306 } | 256 } |
| 307 case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED: { | 257 case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED: { |
| 308 const std::string* id = | 258 const std::string* id = |
| 309 content::Details<const std::string>(details).ptr(); | 259 content::Details<const std::string>(details).ptr(); |
| 310 if (id) { | 260 if (id) { |
| 311 const Extension* extension = | 261 const Extension* extension = |
| 312 extension_service_->GetExtensionById(*id, false); | 262 extension_service_->GetExtensionById(*id, false); |
| 313 DictionaryValue app_info; | 263 DictionaryValue app_info; |
| 314 CreateAppInfo(extension, | 264 CreateAppInfo(extension, |
| 315 NULL, | |
| 316 extension_service_, | 265 extension_service_, |
| 317 &app_info); | 266 &app_info); |
| 318 web_ui()->CallJavascriptFunction("ntp.appMoved", app_info); | 267 web_ui()->CallJavascriptFunction("ntp.appMoved", app_info); |
| 319 } else { | 268 } else { |
| 320 HandleGetApps(NULL); | 269 HandleGetApps(NULL); |
| 321 } | 270 } |
| 322 break; | 271 break; |
| 323 } | 272 } |
| 324 // The promo may not load until a couple seconds after the first NTP view, | 273 // The promo may not load until a couple seconds after the first NTP view, |
| 325 // so we listen for the load notification and notify the NTP when ready. | 274 // so we listen for the load notification and notify the NTP when ready. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME))); | 333 l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME))); |
| 385 dictionary->Set("appPageNames", | 334 dictionary->Set("appPageNames", |
| 386 static_cast<ListValue*>(list->DeepCopy())); | 335 static_cast<ListValue*>(list->DeepCopy())); |
| 387 } else { | 336 } else { |
| 388 dictionary->Set("appPageNames", | 337 dictionary->Set("appPageNames", |
| 389 static_cast<ListValue*>(app_page_names->DeepCopy())); | 338 static_cast<ListValue*>(app_page_names->DeepCopy())); |
| 390 } | 339 } |
| 391 } | 340 } |
| 392 | 341 |
| 393 DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) { | 342 DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) { |
| 394 extensions::AppNotificationManager* notification_manager = | |
| 395 extension_service_->app_notification_manager(); | |
| 396 DictionaryValue* app_info = new DictionaryValue(); | 343 DictionaryValue* app_info = new DictionaryValue(); |
| 397 // CreateAppInfo can change the extension prefs. | 344 // CreateAppInfo can change the extension prefs. |
| 398 base::AutoReset<bool> auto_reset(&ignore_changes_, true); | 345 base::AutoReset<bool> auto_reset(&ignore_changes_, true); |
| 399 CreateAppInfo(extension, | 346 CreateAppInfo(extension, |
| 400 notification_manager->GetLast(extension->id()), | |
| 401 extension_service_, | 347 extension_service_, |
| 402 app_info); | 348 app_info); |
| 403 return app_info; | 349 return app_info; |
| 404 } | 350 } |
| 405 | 351 |
| 406 void AppLauncherHandler::HandleGetApps(const ListValue* args) { | 352 void AppLauncherHandler::HandleGetApps(const ListValue* args) { |
| 407 DictionaryValue dictionary; | 353 DictionaryValue dictionary; |
| 408 | 354 |
| 409 // Tell the client whether to show the promo for this view. We don't do this | 355 // Tell the client whether to show the promo for this view. We don't do this |
| 410 // in the case of PREF_CHANGED because: | 356 // in the case of PREF_CHANGED because: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 // the apps as they change. | 392 // the apps as they change. |
| 447 if (!has_loaded_apps_) { | 393 if (!has_loaded_apps_) { |
| 448 base::Closure callback = base::Bind( | 394 base::Closure callback = base::Bind( |
| 449 &AppLauncherHandler::OnPreferenceChanged, | 395 &AppLauncherHandler::OnPreferenceChanged, |
| 450 base::Unretained(this)); | 396 base::Unretained(this)); |
| 451 pref_change_registrar_.Init( | 397 pref_change_registrar_.Init( |
| 452 extension_service_->extension_prefs()->pref_service()); | 398 extension_service_->extension_prefs()->pref_service()); |
| 453 pref_change_registrar_.Add(ExtensionPrefs::kExtensionsPref, callback); | 399 pref_change_registrar_.Add(ExtensionPrefs::kExtensionsPref, callback); |
| 454 pref_change_registrar_.Add(prefs::kNtpAppPageNames, callback); | 400 pref_change_registrar_.Add(prefs::kNtpAppPageNames, callback); |
| 455 | 401 |
| 456 registrar_.Add(this, chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED, | |
| 457 content::Source<Profile>(profile)); | |
| 458 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | 402 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
| 459 content::Source<Profile>(profile)); | 403 content::Source<Profile>(profile)); |
| 460 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 404 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 461 content::Source<Profile>(profile)); | 405 content::Source<Profile>(profile)); |
| 462 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED, | 406 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED, |
| 463 content::Source<ExtensionSorting>( | 407 content::Source<ExtensionSorting>( |
| 464 extension_service_->extension_prefs()->extension_sorting())); | 408 extension_service_->extension_prefs()->extension_sorting())); |
| 465 registrar_.Add(this, chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED, | 409 registrar_.Add(this, chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED, |
| 466 content::Source<Profile>(profile)); | 410 content::Source<Profile>(profile)); |
| 467 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, | 411 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 double source; | 655 double source; |
| 712 CHECK(args->GetDouble(1, &source)); | 656 CHECK(args->GetDouble(1, &source)); |
| 713 | 657 |
| 714 extension_misc::AppLaunchBucket bucket = | 658 extension_misc::AppLaunchBucket bucket = |
| 715 static_cast<extension_misc::AppLaunchBucket>(static_cast<int>(source)); | 659 static_cast<extension_misc::AppLaunchBucket>(static_cast<int>(source)); |
| 716 CHECK(source < extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); | 660 CHECK(source < extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); |
| 717 | 661 |
| 718 RecordAppLaunchByUrl(Profile::FromWebUI(web_ui()), url, bucket); | 662 RecordAppLaunchByUrl(Profile::FromWebUI(web_ui()), url, bucket); |
| 719 } | 663 } |
| 720 | 664 |
| 721 void AppLauncherHandler::HandleNotificationClose(const ListValue* args) { | |
| 722 std::string extension_id; | |
| 723 CHECK(args->GetString(0, &extension_id)); | |
| 724 | |
| 725 const Extension* extension = extension_service_->GetExtensionById( | |
| 726 extension_id, true); | |
| 727 if (!extension) | |
| 728 return; | |
| 729 | |
| 730 UMA_HISTOGRAM_COUNTS("AppNotification.NTPNotificationClosed", 1); | |
| 731 | |
| 732 extensions::AppNotificationManager* notification_manager = | |
| 733 extension_service_->app_notification_manager(); | |
| 734 notification_manager->ClearAll(extension_id); | |
| 735 } | |
| 736 | |
| 737 void AppLauncherHandler::HandleSetNotificationsDisabled( | |
| 738 const ListValue* args) { | |
| 739 std::string extension_id; | |
| 740 bool disabled = false; | |
| 741 CHECK(args->GetString(0, &extension_id)); | |
| 742 CHECK(args->GetBoolean(1, &disabled)); | |
| 743 | |
| 744 const Extension* extension = extension_service_->GetExtensionById( | |
| 745 extension_id, true); | |
| 746 if (!extension) | |
| 747 return; | |
| 748 extension_service_->SetAppNotificationDisabled(extension_id, disabled); | |
| 749 } | |
| 750 | |
| 751 void AppLauncherHandler::OnFaviconForApp( | 665 void AppLauncherHandler::OnFaviconForApp( |
| 752 scoped_ptr<AppInstallInfo> install_info, | 666 scoped_ptr<AppInstallInfo> install_info, |
| 753 const history::FaviconImageResult& image_result) { | 667 const history::FaviconImageResult& image_result) { |
| 754 scoped_ptr<WebApplicationInfo> web_app(new WebApplicationInfo()); | 668 scoped_ptr<WebApplicationInfo> web_app(new WebApplicationInfo()); |
| 755 web_app->is_bookmark_app = install_info->is_bookmark_app; | 669 web_app->is_bookmark_app = install_info->is_bookmark_app; |
| 756 web_app->title = install_info->title; | 670 web_app->title = install_info->title; |
| 757 web_app->app_url = install_info->app_url; | 671 web_app->app_url = install_info->app_url; |
| 758 web_app->urls.push_back(install_info->app_url); | 672 web_app->urls.push_back(install_info->app_url); |
| 759 | 673 |
| 760 if (!image_result.image.IsEmpty()) { | 674 if (!image_result.image.IsEmpty()) { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 ExtensionUninstallDialog* AppLauncherHandler::GetExtensionUninstallDialog() { | 811 ExtensionUninstallDialog* AppLauncherHandler::GetExtensionUninstallDialog() { |
| 898 if (!extension_uninstall_dialog_.get()) { | 812 if (!extension_uninstall_dialog_.get()) { |
| 899 Browser* browser = chrome::FindBrowserWithWebContents( | 813 Browser* browser = chrome::FindBrowserWithWebContents( |
| 900 web_ui()->GetWebContents()); | 814 web_ui()->GetWebContents()); |
| 901 extension_uninstall_dialog_.reset( | 815 extension_uninstall_dialog_.reset( |
| 902 ExtensionUninstallDialog::Create(extension_service_->profile(), | 816 ExtensionUninstallDialog::Create(extension_service_->profile(), |
| 903 browser, this)); | 817 browser, this)); |
| 904 } | 818 } |
| 905 return extension_uninstall_dialog_.get(); | 819 return extension_uninstall_dialog_.get(); |
| 906 } | 820 } |
| OLD | NEW |