Commit c852197e authored by rockot@chromium.org's avatar rockot@chromium.org

OAuth2 support for Webstore downloads.

This patch does three related things:

1. Plumbs an optional IdentityProvider through 
ExtensionUpdater / ExtensionDownloader.

2. Adds support in ExtensionDownloader for OAuth2 token-
based authentication to protected Webstore download URLs,
using the optional IdentityProvider as its account ID and 
token source. Bonus points for general cleanup of the 
credential iteration code in ExtensionDownloader.

3. Wires up Chrome's ExtensionDownloader (via
ExtensionService) with a ProfileIdentityProvider so that
it may authenticate as the Chrome-signed-in user via OAuth2.

BUG=376553,122763

Review URL: https://codereview.chromium.org/434493002

Cr-Commit-Position: refs/heads/master@{#288261}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288261 0039d316-1c4b-4281-b951-d872f2087c98
parent 93b41658
...@@ -210,7 +210,7 @@ void ExternalCache::CheckCache() { ...@@ -210,7 +210,7 @@ void ExternalCache::CheckCache() {
// If request_context_ is missing we can't download anything. // If request_context_ is missing we can't download anything.
if (!downloader_ && request_context_) { if (!downloader_ && request_context_) {
downloader_.reset( downloader_.reset(
new extensions::ExtensionDownloader(this, request_context_)); new extensions::ExtensionDownloader(this, request_context_, NULL));
} }
cached_extensions_->Clear(); cached_extensions_->Clear();
......
...@@ -36,9 +36,13 @@ ...@@ -36,9 +36,13 @@
#include "chrome/browser/extensions/shared_module_service.h" #include "chrome/browser/extensions/shared_module_service.h"
#include "chrome/browser/extensions/updater/extension_cache.h" #include "chrome/browser/extensions/updater/extension_cache.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_identity_provider.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
#include "chrome/browser/ui/webui/favicon_source.h" #include "chrome/browser/ui/webui/favicon_source.h"
#include "chrome/browser/ui/webui/ntp/thumbnail_source.h" #include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/browser/ui/webui/theme_source.h" #include "chrome/browser/ui/webui/theme_source.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/common/crash_keys.h" #include "chrome/common/crash_keys.h"
...@@ -47,6 +51,7 @@ ...@@ -47,6 +51,7 @@
#include "chrome/common/extensions/manifest_url_handler.h" #include "chrome/common/extensions/manifest_url_handler.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
#include "components/signin/core/browser/signin_manager.h"
#include "components/startup_metric_utils/startup_metric_utils.h" #include "components/startup_metric_utils/startup_metric_utils.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
...@@ -113,6 +118,15 @@ namespace { ...@@ -113,6 +118,15 @@ namespace {
// Wait this many seconds after an extensions becomes idle before updating it. // Wait this many seconds after an extensions becomes idle before updating it.
const int kUpdateIdleDelay = 5; const int kUpdateIdleDelay = 5;
#if defined(ENABLE_EXTENSIONS)
scoped_ptr<IdentityProvider> CreateWebstoreIdentityProvider(Profile* profile) {
return make_scoped_ptr<IdentityProvider>(new ProfileIdentityProvider(
SigninManagerFactory::GetForProfile(profile),
ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
LoginUIServiceFactory::GetForProfile(profile)));
}
#endif // defined(ENABLE_EXTENSIONS)
} // namespace } // namespace
// ExtensionService. // ExtensionService.
...@@ -312,7 +326,8 @@ ExtensionService::ExtensionService(Profile* profile, ...@@ -312,7 +326,8 @@ ExtensionService::ExtensionService(Profile* profile,
profile->GetPrefs(), profile->GetPrefs(),
profile, profile,
update_frequency, update_frequency,
extensions::ExtensionCache::GetInstance())); extensions::ExtensionCache::GetInstance(),
CreateWebstoreIdentityProvider(profile_)));
} }
#endif #endif
......
...@@ -23,9 +23,12 @@ ...@@ -23,9 +23,12 @@
#include "chrome/browser/extensions/updater/request_queue.h" #include "chrome/browser/extensions/updater/request_queue.h"
#include "chrome/common/extensions/update_manifest.h" #include "chrome/common/extensions/update_manifest.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "google_apis/gaia/oauth2_token_service.h"
#include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_fetcher_delegate.h"
#include "url/gurl.h" #include "url/gurl.h"
class IdentityProvider;
namespace net { namespace net {
class URLFetcher; class URLFetcher;
class URLRequestContextGetter; class URLRequestContextGetter;
...@@ -44,17 +47,23 @@ struct UpdateDetails { ...@@ -44,17 +47,23 @@ struct UpdateDetails {
class ExtensionCache; class ExtensionCache;
class ExtensionUpdaterTest; class ExtensionUpdaterTest;
class WebstoreOAuth2TokenProvider;
// A class that checks for updates of a given list of extensions, and downloads // A class that checks for updates of a given list of extensions, and downloads
// the crx file when updates are found. It uses a |ExtensionDownloaderDelegate| // the crx file when updates are found. It uses a |ExtensionDownloaderDelegate|
// that takes ownership of the downloaded crx files, and handles events during // that takes ownership of the downloaded crx files, and handles events during
// the update check. // the update check.
class ExtensionDownloader : public net::URLFetcherDelegate { class ExtensionDownloader
: public net::URLFetcherDelegate,
public OAuth2TokenService::Consumer {
public: public:
// |delegate| is stored as a raw pointer and must outlive the // |delegate| is stored as a raw pointer and must outlive the
// ExtensionDownloader. // ExtensionDownloader. |webstore_identity_provider| may be NULL if this
// ExtensionDownloader does not need OAuth2 support; if not NULL, the
// given IdentityProvider must outlive this ExtensionDownloader.
ExtensionDownloader(ExtensionDownloaderDelegate* delegate, ExtensionDownloader(ExtensionDownloaderDelegate* delegate,
net::URLRequestContextGetter* request_context); net::URLRequestContextGetter* request_context,
IdentityProvider* webstore_identity_provider);
virtual ~ExtensionDownloader(); virtual ~ExtensionDownloader();
// Adds |extension| to the list of extensions to check for updates. // Adds |extension| to the list of extensions to check for updates.
...@@ -130,8 +139,18 @@ class ExtensionDownloader : public net::URLFetcherDelegate { ...@@ -130,8 +139,18 @@ class ExtensionDownloader : public net::URLFetcherDelegate {
std::string version; std::string version;
std::set<int> request_ids; std::set<int> request_ids;
// Indicates whether or not the fetch is known to require credentials. enum CredentialsMode {
bool is_protected; CREDENTIALS_NONE = 0,
CREDENTIALS_OAUTH2_TOKEN,
CREDENTIALS_COOKIES,
};
// Indicates the type of credentials to include with this fetch.
CredentialsMode credentials;
// Counts the number of times OAuth2 authentication has been attempted for
// this fetch.
int oauth2_attempt_count;
}; };
// Helper for AddExtension() and AddPendingExtension(). // Helper for AddExtension() and AddPendingExtension().
...@@ -204,6 +223,20 @@ class ExtensionDownloader : public net::URLFetcherDelegate { ...@@ -204,6 +223,20 @@ class ExtensionDownloader : public net::URLFetcherDelegate {
const base::FilePath& crx_path, const base::FilePath& crx_path,
bool file_ownership_passed); bool file_ownership_passed);
// Potentially updates an ExtensionFetch's authentication state and returns
// |true| if the fetch should be retried. Returns |false| if the failure was
// not related to authentication, leaving the ExtensionFetch data unmodified.
bool IterateFetchCredentialsAfterFailure(ExtensionFetch* fetch,
const net::URLRequestStatus& status,
int response_code);
// OAuth2TokenService::Consumer implementation.
virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) OVERRIDE;
virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) OVERRIDE;
// The delegate that receives the crx files downloaded by the // The delegate that receives the crx files downloaded by the
// ExtensionDownloader, and that fills in optional ping and update url data. // ExtensionDownloader, and that fills in optional ping and update url data.
ExtensionDownloaderDelegate* delegate_; ExtensionDownloaderDelegate* delegate_;
...@@ -240,6 +273,17 @@ class ExtensionDownloader : public net::URLFetcherDelegate { ...@@ -240,6 +273,17 @@ class ExtensionDownloader : public net::URLFetcherDelegate {
// Cache for .crx files. // Cache for .crx files.
ExtensionCache* extension_cache_; ExtensionCache* extension_cache_;
// An IdentityProvider which may be used for authentication on protected
// download requests. May be NULL.
IdentityProvider* identity_provider_;
// A Webstore download-scoped access token for the |identity_provider_|'s
// active account, if any.
std::string access_token_;
// A pending token fetch request.
scoped_ptr<OAuth2TokenService::Request> access_token_request_;
DISALLOW_COPY_AND_ASSIGN(ExtensionDownloader); DISALLOW_COPY_AND_ASSIGN(ExtensionDownloader);
}; };
......
...@@ -129,21 +129,27 @@ struct ExtensionUpdater::ThrottleInfo { ...@@ -129,21 +129,27 @@ struct ExtensionUpdater::ThrottleInfo {
Time check_start; Time check_start;
}; };
ExtensionUpdater::ExtensionUpdater(ExtensionServiceInterface* service, ExtensionUpdater::ExtensionUpdater(
ExtensionPrefs* extension_prefs, ExtensionServiceInterface* service,
PrefService* prefs, ExtensionPrefs* extension_prefs,
Profile* profile, PrefService* prefs,
int frequency_seconds, Profile* profile,
ExtensionCache* cache) int frequency_seconds,
ExtensionCache* cache,
scoped_ptr<IdentityProvider> webstore_identity_provider)
: alive_(false), : alive_(false),
weak_ptr_factory_(this), weak_ptr_factory_(this),
service_(service), frequency_seconds_(frequency_seconds), service_(service),
will_check_soon_(false), extension_prefs_(extension_prefs), frequency_seconds_(frequency_seconds),
prefs_(prefs), profile_(profile), will_check_soon_(false),
extension_prefs_(extension_prefs),
prefs_(prefs),
profile_(profile),
next_request_id_(0), next_request_id_(0),
extension_registry_observer_(this), extension_registry_observer_(this),
crx_install_is_running_(false), crx_install_is_running_(false),
extension_cache_(cache) { extension_cache_(cache),
webstore_identity_provider_(webstore_identity_provider.release()) {
DCHECK_GE(frequency_seconds_, 5); DCHECK_GE(frequency_seconds_, 5);
DCHECK_LE(frequency_seconds_, kMaxUpdateFrequencySeconds); DCHECK_LE(frequency_seconds_, kMaxUpdateFrequencySeconds);
#if defined(NDEBUG) #if defined(NDEBUG)
...@@ -338,7 +344,9 @@ void ExtensionUpdater::CheckNow(const CheckParams& params) { ...@@ -338,7 +344,9 @@ void ExtensionUpdater::CheckNow(const CheckParams& params) {
if (!downloader_.get()) { if (!downloader_.get()) {
downloader_.reset( downloader_.reset(
new ExtensionDownloader(this, profile_->GetRequestContext())); new ExtensionDownloader(this,
profile_->GetRequestContext(),
webstore_identity_provider_.get()));
} }
// Add fetch records for extensions that should be fetched by an update URL. // Add fetch records for extensions that should be fetched by an update URL.
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
#include "extensions/browser/extension_registry_observer.h" #include "extensions/browser/extension_registry_observer.h"
#include "google_apis/gaia/identity_provider.h"
#include "url/gurl.h" #include "url/gurl.h"
class ExtensionServiceInterface; class ExtensionServiceInterface;
...@@ -87,7 +88,8 @@ class ExtensionUpdater : public ExtensionDownloaderDelegate, ...@@ -87,7 +88,8 @@ class ExtensionUpdater : public ExtensionDownloaderDelegate,
PrefService* prefs, PrefService* prefs,
Profile* profile, Profile* profile,
int frequency_seconds, int frequency_seconds,
ExtensionCache* cache); ExtensionCache* cache,
scoped_ptr<IdentityProvider> identity_provider);
virtual ~ExtensionUpdater(); virtual ~ExtensionUpdater();
...@@ -270,6 +272,9 @@ class ExtensionUpdater : public ExtensionDownloaderDelegate, ...@@ -270,6 +272,9 @@ class ExtensionUpdater : public ExtensionDownloaderDelegate,
ExtensionCache* extension_cache_; ExtensionCache* extension_cache_;
// Provided to the ExtensionDownloader to enable OAuth2 support.
scoped_ptr<IdentityProvider> webstore_identity_provider_;
// Keeps track of when an extension tried to update itself, so we can throttle // Keeps track of when an extension tried to update itself, so we can throttle
// checks to prevent too many requests from being made. // checks to prevent too many requests from being made.
std::map<std::string, ThrottleInfo> throttle_info_; std::map<std::string, ThrottleInfo> throttle_info_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment