| 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/extensions/extension_webstore_private_api.h" | 5 #include "chrome/browser/extensions/extension_webstore_private_api.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| 11 #include "base/values.h" | 11 #include "base/values.h" |
| 12 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/extensions/crx_installer.h" | 13 #include "chrome/browser/extensions/crx_installer.h" |
| 14 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 14 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
| 15 #include "chrome/browser/extensions/extension_install_dialog.h" | 15 #include "chrome/browser/extensions/extension_install_dialog.h" |
| 16 #include "chrome/browser/extensions/extension_prefs.h" | 16 #include "chrome/browser/extensions/extension_prefs.h" |
| 17 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/net/gaia/token_service.h" | 18 #include "chrome/browser/net/gaia/token_service.h" |
| 19 #include "chrome/browser/profiles/profile_manager.h" | 19 #include "chrome/browser/profiles/profile_manager.h" |
| 20 #include "chrome/browser/sync/profile_sync_service.h" | 20 #include "chrome/browser/sync/profile_sync_service.h" |
| 21 #include "chrome/common/chrome_notification_types.h" | 21 #include "chrome/common/chrome_notification_types.h" |
| 22 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" |
| 23 #include "chrome/common/pref_names.h" |
| 23 #include "chrome/common/extensions/extension_constants.h" | 24 #include "chrome/common/extensions/extension_constants.h" |
| 24 #include "chrome/common/extensions/extension_error_utils.h" | 25 #include "chrome/common/extensions/extension_error_utils.h" |
| 25 #include "chrome/common/extensions/extension_l10n_util.h" | 26 #include "chrome/common/extensions/extension_l10n_util.h" |
| 26 #include "chrome/common/net/gaia/gaia_constants.h" | 27 #include "chrome/common/net/gaia/gaia_constants.h" |
| 27 #include "content/browser/tab_contents/tab_contents.h" | 28 #include "content/browser/tab_contents/tab_contents.h" |
| 28 #include "content/common/notification_details.h" | 29 #include "content/common/notification_details.h" |
| 29 #include "content/common/notification_source.h" | 30 #include "content/common/notification_source.h" |
| 30 #include "grit/chromium_strings.h" | 31 #include "grit/chromium_strings.h" |
| 31 #include "grit/generated_resources.h" | 32 #include "grit/generated_resources.h" |
| 32 #include "ui/base/l10n/l10n_util.h" | 33 #include "ui/base/l10n/l10n_util.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 47 const char kInvalidIconUrlError[] = "Invalid icon url"; | 48 const char kInvalidIconUrlError[] = "Invalid icon url"; |
| 48 const char kInvalidIdError[] = "Invalid id"; | 49 const char kInvalidIdError[] = "Invalid id"; |
| 49 const char kInvalidManifestError[] = "Invalid manifest"; | 50 const char kInvalidManifestError[] = "Invalid manifest"; |
| 50 const char kNoPreviousBeginInstallError[] = | 51 const char kNoPreviousBeginInstallError[] = |
| 51 "* does not match a previous call to beginInstall"; | 52 "* does not match a previous call to beginInstall"; |
| 52 const char kUserCancelledError[] = "User cancelled install"; | 53 const char kUserCancelledError[] = "User cancelled install"; |
| 53 const char kUserGestureRequiredError[] = | 54 const char kUserGestureRequiredError[] = |
| 54 "This function must be called during a user gesture"; | 55 "This function must be called during a user gesture"; |
| 55 | 56 |
| 56 ProfileSyncService* test_sync_service = NULL; | 57 ProfileSyncService* test_sync_service = NULL; |
| 57 BrowserSignin* test_signin = NULL; | |
| 58 bool ignore_user_gesture_for_tests = false; | 58 bool ignore_user_gesture_for_tests = false; |
| 59 | 59 |
| 60 // A flag used for BeginInstallWithManifest::SetAutoConfirmForTests. | 60 // A flag used for BeginInstallWithManifest::SetAutoConfirmForTests. |
| 61 enum AutoConfirmForTest { | 61 enum AutoConfirmForTest { |
| 62 DO_NOT_SKIP = 0, | 62 DO_NOT_SKIP = 0, |
| 63 PROCEED, | 63 PROCEED, |
| 64 ABORT | 64 ABORT |
| 65 }; | 65 }; |
| 66 AutoConfirmForTest auto_confirm_for_tests = DO_NOT_SKIP; | 66 AutoConfirmForTest auto_confirm_for_tests = DO_NOT_SKIP; |
| 67 | 67 |
| 68 | 68 |
| 69 // Returns either the test sync service, or the real one from |profile|. | 69 // Returns either the test sync service, or the real one from |profile|. |
| 70 ProfileSyncService* GetSyncService(Profile* profile) { | 70 ProfileSyncService* GetSyncService(Profile* profile) { |
| 71 if (test_sync_service) | 71 if (test_sync_service) |
| 72 return test_sync_service; | 72 return test_sync_service; |
| 73 else | 73 else |
| 74 return profile->GetProfileSyncService(); | 74 return profile->GetProfileSyncService(); |
| 75 } | 75 } |
| 76 | 76 |
| 77 BrowserSignin* GetBrowserSignin(Profile* profile) { | |
| 78 if (test_signin) | |
| 79 return test_signin; | |
| 80 else | |
| 81 return profile->GetBrowserSignin(); | |
| 82 } | |
| 83 | |
| 84 bool IsWebStoreURL(Profile* profile, const GURL& url) { | 77 bool IsWebStoreURL(Profile* profile, const GURL& url) { |
| 85 ExtensionService* service = profile->GetExtensionService(); | 78 ExtensionService* service = profile->GetExtensionService(); |
| 86 const Extension* store = service->GetWebStoreApp(); | 79 const Extension* store = service->GetWebStoreApp(); |
| 87 if (!store) { | 80 if (!store) { |
| 88 NOTREACHED(); | 81 NOTREACHED(); |
| 89 return false; | 82 return false; |
| 90 } | 83 } |
| 91 return (service->GetExtensionByWebExtent(url) == store); | 84 return (service->GetExtensionByWebExtent(url) == store); |
| 92 } | 85 } |
| 93 | 86 |
| 94 // Helper to create a dictionary with login and token properties set from | 87 // Helper to create a dictionary with login and token properties set from |
| 95 // the appropriate values in the passed-in |profile|. | 88 // the appropriate values in the passed-in |profile|. |
| 96 DictionaryValue* CreateLoginResult(Profile* profile) { | 89 DictionaryValue* CreateLoginResult(Profile* profile) { |
| 97 DictionaryValue* dictionary = new DictionaryValue(); | 90 DictionaryValue* dictionary = new DictionaryValue(); |
| 98 std::string username = GetBrowserSignin(profile)->GetSignedInUsername(); | 91 std::string username = profile->GetPrefs()->GetString( |
| 92 prefs::kGoogleServicesUsername); |
| 99 dictionary->SetString(kLoginKey, username); | 93 dictionary->SetString(kLoginKey, username); |
| 100 if (!username.empty()) { | 94 if (!username.empty()) { |
| 101 CommandLine* cmdline = CommandLine::ForCurrentProcess(); | 95 CommandLine* cmdline = CommandLine::ForCurrentProcess(); |
| 102 TokenService* token_service = profile->GetTokenService(); | 96 TokenService* token_service = profile->GetTokenService(); |
| 103 if (cmdline->HasSwitch(switches::kAppsGalleryReturnTokens) && | 97 if (cmdline->HasSwitch(switches::kAppsGalleryReturnTokens) && |
| 104 token_service->HasTokenForService(GaiaConstants::kGaiaService)) { | 98 token_service->HasTokenForService(GaiaConstants::kGaiaService)) { |
| 105 dictionary->SetString(kTokenKey, | 99 dictionary->SetString(kTokenKey, |
| 106 token_service->GetTokenForService( | 100 token_service->GetTokenForService( |
| 107 GaiaConstants::kGaiaService)); | 101 GaiaConstants::kGaiaService)); |
| 108 } | 102 } |
| 109 } | 103 } |
| 110 return dictionary; | 104 return dictionary; |
| 111 } | 105 } |
| 112 | 106 |
| 113 } // namespace | 107 } // namespace |
| 114 | 108 |
| 115 // static | 109 // static |
| 116 void WebstorePrivateApi::SetTestingProfileSyncService( | 110 void WebstorePrivateApi::SetTestingProfileSyncService( |
| 117 ProfileSyncService* service) { | 111 ProfileSyncService* service) { |
| 118 test_sync_service = service; | 112 test_sync_service = service; |
| 119 } | 113 } |
| 120 | 114 |
| 121 // static | 115 // static |
| 122 void WebstorePrivateApi::SetTestingBrowserSignin(BrowserSignin* signin) { | |
| 123 test_signin = signin; | |
| 124 } | |
| 125 | |
| 126 // static | |
| 127 void BeginInstallFunction::SetIgnoreUserGestureForTests(bool ignore) { | 116 void BeginInstallFunction::SetIgnoreUserGestureForTests(bool ignore) { |
| 128 ignore_user_gesture_for_tests = ignore; | 117 ignore_user_gesture_for_tests = ignore; |
| 129 } | 118 } |
| 130 | 119 |
| 131 bool BeginInstallFunction::RunImpl() { | 120 bool BeginInstallFunction::RunImpl() { |
| 132 if (!IsWebStoreURL(profile_, source_url())) | 121 if (!IsWebStoreURL(profile_, source_url())) |
| 133 return false; | 122 return false; |
| 134 | 123 |
| 135 std::string id; | 124 std::string id; |
| 136 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id)); | 125 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id)); |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 bool SetStoreLoginFunction::RunImpl() { | 442 bool SetStoreLoginFunction::RunImpl() { |
| 454 if (!IsWebStoreURL(profile_, source_url())) | 443 if (!IsWebStoreURL(profile_, source_url())) |
| 455 return false; | 444 return false; |
| 456 std::string login; | 445 std::string login; |
| 457 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &login)); | 446 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &login)); |
| 458 ExtensionService* service = profile_->GetExtensionService(); | 447 ExtensionService* service = profile_->GetExtensionService(); |
| 459 ExtensionPrefs* prefs = service->extension_prefs(); | 448 ExtensionPrefs* prefs = service->extension_prefs(); |
| 460 prefs->SetWebStoreLogin(login); | 449 prefs->SetWebStoreLogin(login); |
| 461 return true; | 450 return true; |
| 462 } | 451 } |
| 463 | |
| 464 PromptBrowserLoginFunction::PromptBrowserLoginFunction() | |
| 465 : waiting_for_token_(false) {} | |
| 466 | |
| 467 PromptBrowserLoginFunction::~PromptBrowserLoginFunction() { | |
| 468 } | |
| 469 | |
| 470 bool PromptBrowserLoginFunction::RunImpl() { | |
| 471 if (!IsWebStoreURL(profile_, source_url())) | |
| 472 return false; | |
| 473 | |
| 474 std::string preferred_email; | |
| 475 if (args_->GetSize() > 0) { | |
| 476 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &preferred_email)); | |
| 477 } | |
| 478 | |
| 479 Profile* profile = profile_->GetOriginalProfile(); | |
| 480 | |
| 481 // Login can currently only be invoked tab-modal. Since this is | |
| 482 // coming from the webstore, we should always have a tab, but check | |
| 483 // just in case. | |
| 484 TabContents* tab = dispatcher()->delegate()->GetAssociatedTabContents(); | |
| 485 if (!tab) | |
| 486 return false; | |
| 487 | |
| 488 // We return the result asynchronously, so we addref to keep ourself alive. | |
| 489 // Matched with a Release in OnLoginSuccess() and OnLoginFailure(). | |
| 490 AddRef(); | |
| 491 | |
| 492 // Start listening for notifications about the token. | |
| 493 TokenService* token_service = profile->GetTokenService(); | |
| 494 registrar_.Add(this, | |
| 495 chrome::NOTIFICATION_TOKEN_AVAILABLE, | |
| 496 Source<TokenService>(token_service)); | |
| 497 registrar_.Add(this, | |
| 498 chrome::NOTIFICATION_TOKEN_REQUEST_FAILED, | |
| 499 Source<TokenService>(token_service)); | |
| 500 | |
| 501 GetBrowserSignin(profile)->RequestSignin(tab, | |
| 502 ASCIIToUTF16(preferred_email), | |
| 503 GetLoginMessage(), | |
| 504 this); | |
| 505 | |
| 506 // The response will be sent asynchronously in OnLoginSuccess/OnLoginFailure. | |
| 507 return true; | |
| 508 } | |
| 509 | |
| 510 string16 PromptBrowserLoginFunction::GetLoginMessage() { | |
| 511 using l10n_util::GetStringUTF16; | |
| 512 using l10n_util::GetStringFUTF16; | |
| 513 | |
| 514 // TODO(johnnyg): This would be cleaner as an HTML template. | |
| 515 // http://crbug.com/60216 | |
| 516 string16 message; | |
| 517 message = ASCIIToUTF16("<p>") | |
| 518 + GetStringUTF16(IDS_WEB_STORE_LOGIN_INTRODUCTION_1) | |
| 519 + ASCIIToUTF16("</p>"); | |
| 520 message = message + ASCIIToUTF16("<p>") | |
| 521 + GetStringFUTF16(IDS_WEB_STORE_LOGIN_INTRODUCTION_2, | |
| 522 GetStringUTF16(IDS_PRODUCT_NAME)) | |
| 523 + ASCIIToUTF16("</p>"); | |
| 524 return message; | |
| 525 } | |
| 526 | |
| 527 void PromptBrowserLoginFunction::OnLoginSuccess() { | |
| 528 // Ensure that apps are synced. | |
| 529 // - If the user has already setup sync, we add Apps to the current types. | |
| 530 // - If not, we create a new set which is just Apps. | |
| 531 ProfileSyncService* service = GetSyncService(profile_->GetOriginalProfile()); | |
| 532 syncable::ModelTypeSet types; | |
| 533 if (service->HasSyncSetupCompleted()) | |
| 534 service->GetPreferredDataTypes(&types); | |
| 535 types.insert(syncable::APPS); | |
| 536 service->ChangePreferredDataTypes(types); | |
| 537 service->SetSyncSetupCompleted(); | |
| 538 | |
| 539 // We'll finish up in Observe() when the token is ready. | |
| 540 waiting_for_token_ = true; | |
| 541 } | |
| 542 | |
| 543 void PromptBrowserLoginFunction::OnLoginFailure( | |
| 544 const GoogleServiceAuthError& error) { | |
| 545 SendResponse(false); | |
| 546 // Matches the AddRef in RunImpl(). | |
| 547 Release(); | |
| 548 } | |
| 549 | |
| 550 void PromptBrowserLoginFunction::Observe(int type, | |
| 551 const NotificationSource& source, | |
| 552 const NotificationDetails& details) { | |
| 553 // Make sure this notification is for the service we are interested in. | |
| 554 std::string service; | |
| 555 if (type == chrome::NOTIFICATION_TOKEN_AVAILABLE) { | |
| 556 TokenService::TokenAvailableDetails* available = | |
| 557 Details<TokenService::TokenAvailableDetails>(details).ptr(); | |
| 558 service = available->service(); | |
| 559 } else if (type == chrome::NOTIFICATION_TOKEN_REQUEST_FAILED) { | |
| 560 TokenService::TokenRequestFailedDetails* failed = | |
| 561 Details<TokenService::TokenRequestFailedDetails>(details).ptr(); | |
| 562 service = failed->service(); | |
| 563 } else { | |
| 564 NOTREACHED(); | |
| 565 } | |
| 566 | |
| 567 if (service != GaiaConstants::kGaiaService) { | |
| 568 return; | |
| 569 } | |
| 570 | |
| 571 DCHECK(waiting_for_token_); | |
| 572 | |
| 573 result_.reset(CreateLoginResult(profile_->GetOriginalProfile())); | |
| 574 SendResponse(true); | |
| 575 | |
| 576 // Matches the AddRef in RunImpl(). | |
| 577 Release(); | |
| 578 } | |
| OLD | NEW |