| // 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 CHROME_BROWSER_POLICY_CLOUD_EXTERNAL_POLICY_DATA_FETCHER_H_ |
| #define CHROME_BROWSER_POLICY_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 "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 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 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 // CHROME_BROWSER_POLICY_CLOUD_EXTERNAL_POLICY_DATA_FETCHER_H_ |