// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_POLICY_CORE_COMMON_CLOUD_EXTERNAL_POLICY_DATA_FETCHER_H_ #define COMPONENTS_POLICY_CORE_COMMON_CLOUD_EXTERNAL_POLICY_DATA_FETCHER_H_ #include <map> #include <set> #include <string> #include "base/basictypes.h" #include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "components/policy/policy_export.h" #include "net/url_request/url_fetcher_delegate.h" #include "url/gurl.h" namespace base { class SequencedTaskRunner; } namespace net { class URLFetcher; class URLRequestContextGetter; } namespace policy { class ExternalPolicyDataFetcherBackend; // This class handles network fetch jobs for the ExternalPolicyDataUpdater by // forwarding them to an ExternalPolicyDataFetcherBackend running on a different // thread. This is necessary because the ExternalPolicyDataUpdater runs on a // background thread where network I/O is not allowed. // The class can be instantiated on any thread but from then on, it must be // accessed and destroyed on the background thread that the // ExternalPolicyDataUpdater runs on only. class POLICY_EXPORT ExternalPolicyDataFetcher { public: // The result of a fetch job. enum Result { // Successful fetch. SUCCESS, // The connection was interrupted. CONNECTION_INTERRUPTED, // Another network error occurred. NETWORK_ERROR, // Problem at the server. SERVER_ERROR, // Client error. CLIENT_ERROR, // Any other type of HTTP failure. HTTP_ERROR, // Received data exceeds maximum allowed size. MAX_SIZE_EXCEEDED, }; // Encapsulates the metadata for a fetch job. struct Job; // Callback invoked when a fetch job finishes. If the fetch was successful, // the Result is SUCCESS and the scoped_ptr contains the retrieved data. // Otherwise, Result indicates the type of error that occurred and the // scoped_ptr is NULL. typedef base::Callback<void(Result, scoped_ptr<std::string>)> FetchCallback; // |task_runner| represents the background thread that |this| runs on. // |backend| is used to perform network I/O. It will be dereferenced and // accessed via |io_task_runner| only. ExternalPolicyDataFetcher( scoped_refptr<base::SequencedTaskRunner> task_runner, scoped_refptr<base::SequencedTaskRunner> io_task_runner, const base::WeakPtr<ExternalPolicyDataFetcherBackend>& backend); ~ExternalPolicyDataFetcher(); // Fetch data from |url| and invoke |callback| with the result. See the // documentation of FetchCallback and Result for more details. If a fetch // should be retried after an error, it is the caller's responsibility to call // StartJob() again. Returns an opaque job identifier. Ownership of the job // identifier is retained by |this|. Job* StartJob(const GURL& url, int64 max_size, const FetchCallback& callback); // Cancel the fetch job identified by |job|. The job is canceled silently, // without invoking the |callback| that was passed to StartJob(). void CancelJob(Job* job); private: // Callback invoked when a fetch job finishes in the |backend_|. void OnJobFinished(const FetchCallback& callback, Job* job, Result result, scoped_ptr<std::string> data); // Task runner representing the thread that |this| runs on. scoped_refptr<base::SequencedTaskRunner> task_runner_; // Task runner representing the thread on which the |backend_| runs and // performs network I/O. scoped_refptr<base::SequencedTaskRunner> io_task_runner_; // The |backend_| is used to perform network I/O. It may be dereferenced and // accessed via |io_task_runner_| only. base::WeakPtr<ExternalPolicyDataFetcherBackend> backend_; // Set that owns all currently running Jobs. typedef std::set<Job*> JobSet; JobSet jobs_; base::WeakPtrFactory<ExternalPolicyDataFetcher> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ExternalPolicyDataFetcher); }; // This class handles network I/O for one or more ExternalPolicyDataFetchers. It // can be instantiated on any thread that is allowed to reference // URLRequestContextGetters (in Chrome, these are the UI and IO threads) and // CreateFrontend() may be called from the same thread after instantiation. From // then on, it must be accessed and destroyed on the thread that handles network // I/O only (in Chrome, this is the IO thread). class POLICY_EXPORT ExternalPolicyDataFetcherBackend : public net::URLFetcherDelegate { public: // Callback invoked when a fetch job finishes. If the fetch was successful, // the Result is SUCCESS and the scoped_ptr contains the retrieved data. // Otherwise, Result indicates the type of error that occurred and the // scoped_ptr is NULL. typedef base::Callback<void(ExternalPolicyDataFetcher::Job*, ExternalPolicyDataFetcher::Result, scoped_ptr<std::string>)> FetchCallback; // |io_task_runner_| represents the thread that handles network I/O and that // |this| runs on. |request_context| is used to construct URLFetchers. ExternalPolicyDataFetcherBackend( scoped_refptr<base::SequencedTaskRunner> io_task_runner, scoped_refptr<net::URLRequestContextGetter> request_context); virtual ~ExternalPolicyDataFetcherBackend(); // Create an ExternalPolicyDataFetcher that allows fetch jobs to be started // from the thread represented by |task_runner|. scoped_ptr<ExternalPolicyDataFetcher> CreateFrontend( scoped_refptr<base::SequencedTaskRunner> task_runner); // Start a fetch job defined by |job|. The caller retains ownership of |job| // and must ensure that it remains valid until the job ends, CancelJob() is // called or |this| is destroyed. void StartJob(ExternalPolicyDataFetcher::Job* job); // Cancel the fetch job defined by |job| and invoke |callback| to confirm. void CancelJob(ExternalPolicyDataFetcher::Job* job, const base::Closure& callback); // net::URLFetcherDelegate: virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; virtual void OnURLFetchDownloadProgress(const net::URLFetcher* source, int64 current, int64 total) OVERRIDE; private: scoped_refptr<base::SequencedTaskRunner> io_task_runner_; scoped_refptr<net::URLRequestContextGetter> request_context_; // A monotonically increasing fetch ID. Used to identify fetches in tests. int last_fetch_id_; // Map that owns the net::URLFetchers for all currently running jobs and maps // from these to the corresponding Job. typedef std::map<net::URLFetcher*, ExternalPolicyDataFetcher::Job*> JobMap; JobMap job_map_; base::WeakPtrFactory<ExternalPolicyDataFetcherBackend> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ExternalPolicyDataFetcherBackend); }; } // namespace policy #endif // COMPONENTS_POLICY_CORE_COMMON_CLOUD_EXTERNAL_POLICY_DATA_FETCHER_H_