| Index: chrome/browser/dom_ui/chrome_url_data_manager.h
|
| ===================================================================
|
| --- chrome/browser/dom_ui/chrome_url_data_manager.h (revision 74394)
|
| +++ chrome/browser/dom_ui/chrome_url_data_manager.h (working copy)
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2011 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.
|
|
|
| @@ -9,35 +9,45 @@
|
| #include <map>
|
| #include <string>
|
|
|
| -#include "base/singleton.h"
|
| #include "base/task.h"
|
| #include "base/ref_counted.h"
|
| #include "chrome/browser/browser_thread.h"
|
|
|
| +class ChromeURLDataManagerBackend;
|
| class DictionaryValue;
|
| class FilePath;
|
| -class GURL;
|
| class MessageLoop;
|
| +class Profile;
|
| class RefCountedMemory;
|
| -class URLRequestChromeJob;
|
|
|
| -namespace net {
|
| -class URLRequest;
|
| -class URLRequestJob;
|
| -} // namespace net
|
| -
|
| // To serve dynamic data off of chrome: URLs, implement the
|
| // ChromeURLDataManager::DataSource interface and register your handler
|
| -// with AddDataSource.
|
| -
|
| -// ChromeURLDataManager lives on the IO thread, so any interfacing with
|
| -// it from the UI thread needs to go through an InvokeLater.
|
| +// with AddDataSource. DataSources must be added on the UI thread (they are also
|
| +// deleted on the UI thread). Internally the DataSources are maintained by
|
| +// ChromeURLDataManagerBackend, see it for details.
|
| class ChromeURLDataManager {
|
| public:
|
| - // Returns the singleton instance.
|
| - static ChromeURLDataManager* GetInstance();
|
| + class DataSource;
|
|
|
| - typedef int RequestID;
|
| + // Trait used to handle deleting a DataSource. Deletion happens on the UI
|
| + // thread.
|
| + //
|
| + // Implementation note: the normal shutdown sequence is for the UI loop to
|
| + // stop pumping events then the IO loop and thread are stopped. When the
|
| + // DataSources are no longer referenced (which happens when IO thread stops)
|
| + // they get added to the UI message loop for deletion. But because the UI loop
|
| + // has stopped by the time this happens the DataSources would be leaked.
|
| + //
|
| + // To make sure DataSources are properly deleted ChromeURLDataManager manages
|
| + // deletion of the DataSources. When a DataSource is no longer referenced it
|
| + // is added to |data_sources_| and a task is posted to the UI thread to handle
|
| + // the actual deletion. During shutdown |DeleteDataSources| is invoked so that
|
| + // all pending DataSources are properly deleted.
|
| + struct DeleteDataSource {
|
| + static void Destruct(const DataSource* data_source) {
|
| + ChromeURLDataManager::DeleteDataSource(data_source);
|
| + }
|
| + };
|
|
|
| // A DataSource is an object that can answer requests for data
|
| // asynchronously. DataSources are collectively owned with refcounting smart
|
| @@ -49,11 +59,10 @@
|
| // StartDataRequest() by starting its (implementation-specific) asynchronous
|
| // request for the data, then call SendResponse() to notify.
|
| class DataSource : public base::RefCountedThreadSafe<
|
| - DataSource, BrowserThread::DeleteOnUIThread> {
|
| + DataSource, DeleteDataSource> {
|
| public:
|
| // See source_name_ and message_loop_ below for docs on these parameters.
|
| - DataSource(const std::string& source_name,
|
| - MessageLoop* message_loop);
|
| + DataSource(const std::string& source_name, MessageLoop* message_loop);
|
|
|
| // Sent by the DataManager to request data at |path|. The source should
|
| // call SendResponse() when the data is available or if the request could
|
| @@ -88,13 +97,18 @@
|
| static void SetFontAndTextDirection(DictionaryValue* localized_strings);
|
|
|
| protected:
|
| - friend class base::RefCountedThreadSafe<DataSource>;
|
| - friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
|
| - friend class DeleteTask<DataSource>;
|
| -
|
| virtual ~DataSource();
|
|
|
| private:
|
| + friend class ChromeURLDataManagerBackend;
|
| + friend class ChromeURLDataManager;
|
| + friend class DeleteTask<DataSource>;
|
| +
|
| + // SendResponse invokes this on the IO thread. Notifies the backend to
|
| + // handle the actual work of sending the data.
|
| + virtual void SendResponseOnIOThread(int request_id,
|
| + scoped_refptr<RefCountedMemory> bytes);
|
| +
|
| // The name of this source.
|
| // E.g., for favicons, this could be "favicon", which results in paths for
|
| // specific resources like "favicon/34" getting sent to this source.
|
| @@ -103,89 +117,57 @@
|
| // The MessageLoop for the thread where this DataSource lives.
|
| // Used to send messages to the DataSource.
|
| MessageLoop* message_loop_;
|
| +
|
| + // This field is set and maintained by ChromeURLDataManagerBackend. It is
|
| + // set when the DataSource is added, and unset if the DataSource is removed.
|
| + // A DataSource can be removed in two ways: the ChromeURLDataManagerBackend
|
| + // is deleted, or another DataSource is registered with the same
|
| + // name. backend_ should only be accessed on the IO thread.
|
| + // This reference can't be via a scoped_refptr else there would be a cycle
|
| + // between the backend and data source.
|
| + ChromeURLDataManagerBackend* backend_;
|
| };
|
|
|
| - // Add a DataSource to the collection of data sources.
|
| - // Because we don't track users of a given path, we can't know when it's
|
| - // safe to remove them, so the added source effectively leaks.
|
| - // This could be improved in the future but currently the users of this
|
| - // interface are conceptually permanent registration anyway.
|
| - // Adding a second DataSource with the same name clobbers the first.
|
| - // NOTE: Calling this from threads other the IO thread must be done via
|
| - // InvokeLater.
|
| - void AddDataSource(scoped_refptr<DataSource> source);
|
| - // Called during shutdown, before destruction of |BrowserThread|.
|
| - void RemoveDataSourceForTest(const char* source_name); // For unit tests.
|
| - void RemoveAllDataSources(); // For the browser.
|
| + explicit ChromeURLDataManager(Profile* profile);
|
| + ~ChromeURLDataManager();
|
|
|
| - // Add/remove a path from the collection of file sources.
|
| - // A file source acts like a file:// URL to the specified path.
|
| - // Calling this from threads other the IO thread must be done via
|
| - // InvokeLater.
|
| - void AddFileSource(const std::string& source_name, const FilePath& path);
|
| - void RemoveFileSource(const std::string& source_name);
|
| + // Adds a DataSource to the collection of data sources. This *must* be invoked
|
| + // on the UI thread.
|
| + //
|
| + // If |AddDataSource| is called more than once for a particular name it will
|
| + // release the old |DataSource|, most likely resulting in it getting deleted
|
| + // as there are no other references to it. |DataSource| uses the
|
| + // |DeleteOnUIThread| trait to insure that the destructor is called on the UI
|
| + // thread. This is necessary as some |DataSource|s notably |FileIconSource|
|
| + // and |WebUIFavIconSource|, have members that will DCHECK if they are not
|
| + // destructed in the same thread as they are constructed (the UI thread).
|
| + void AddDataSource(DataSource* source);
|
|
|
| - static net::URLRequestJob* Factory(net::URLRequest* request,
|
| - const std::string& scheme);
|
| + // Deletes any data sources no longer referenced. This is normally invoked
|
| + // for you, but can be invoked to force deletion (such as during shutdown).
|
| + static void DeleteDataSources();
|
|
|
| private:
|
| - friend class URLRequestChromeJob;
|
| - friend struct DefaultSingletonTraits<ChromeURLDataManager>;
|
| + typedef std::vector<const ChromeURLDataManager::DataSource*> DataSources;
|
|
|
| - ChromeURLDataManager();
|
| - ~ChromeURLDataManager();
|
| + // If invoked on the UI thread the DataSource is deleted immediatlye,
|
| + // otherwise it is added to |data_sources_| and a task is scheduled to handle
|
| + // deletion on the UI thread. See note abouve DeleteDataSource for more info.
|
| + static void DeleteDataSource(const DataSource* data_source);
|
|
|
| - // Parse a URL into the components used to resolve its request.
|
| - static void URLToRequest(const GURL& url,
|
| - std::string* source,
|
| - std::string* path);
|
| + // Returns true if |data_source| is scheduled for deletion (|DeleteDataSource|
|
| + // was invoked).
|
| + static bool IsScheduledForDeletion(const DataSource* data_source);
|
|
|
| - // Translate a chrome resource URL into a local file path if there is one.
|
| - // Returns false if there is no file handler for this URL
|
| - static bool URLToFilePath(const GURL& url, FilePath* file_path);
|
| + Profile* profile_;
|
|
|
| - // Called by the job when it's starting up.
|
| - // Returns false if |url| is not a URL managed by this object.
|
| - bool StartRequest(const GURL& url, URLRequestChromeJob* job);
|
| - // Remove a request from the list of pending requests.
|
| - void RemoveRequest(URLRequestChromeJob* job);
|
| + // Lock used when accessing |data_sources_|.
|
| + static base::Lock delete_lock_;
|
|
|
| - // Returns true if the job exists in |pending_requests_|. False otherwise.
|
| - // Called by ~URLRequestChromeJob to verify that |pending_requests_| is kept
|
| - // up to date.
|
| - bool HasPendingJob(URLRequestChromeJob* job) const;
|
| + // |data_sources_| that are no longer referenced and scheduled for deletion.
|
| + static DataSources* data_sources_;
|
|
|
| - // Sent by Request::SendResponse.
|
| - void DataAvailable(RequestID request_id,
|
| - scoped_refptr<RefCountedMemory> bytes);
|
| -
|
| - // File sources of data, keyed by source name (e.g. "inspector").
|
| - typedef std::map<std::string, FilePath> FileSourceMap;
|
| - FileSourceMap file_sources_;
|
| -
|
| - // Custom sources of data, keyed by source path (e.g. "favicon").
|
| - typedef std::map<std::string, scoped_refptr<DataSource> > DataSourceMap;
|
| - DataSourceMap data_sources_;
|
| -
|
| - // All pending URLRequestChromeJobs, keyed by ID of the request.
|
| - // URLRequestChromeJob calls into this object when it's constructed and
|
| - // destructed to ensure that the pointers in this map remain valid.
|
| - typedef std::map<RequestID, URLRequestChromeJob*> PendingRequestMap;
|
| - PendingRequestMap pending_requests_;
|
| -
|
| - // The ID we'll use for the next request we receive.
|
| - RequestID next_request_id_;
|
| + DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManager);
|
| };
|
|
|
| -// Since we have a single global ChromeURLDataManager, we don't need to
|
| -// grab a reference to it when creating Tasks involving it.
|
| -DISABLE_RUNNABLE_METHOD_REFCOUNT(ChromeURLDataManager);
|
| -
|
| -// Register our special URL handler under our special URL scheme.
|
| -// Must be done once at startup.
|
| -void RegisterURLRequestChromeJob();
|
| -
|
| -// Undoes the registration done by RegisterURLRequestChromeJob.
|
| -void UnregisterURLRequestChromeJob();
|
| -
|
| #endif // CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_
|
|
|