// Copyright (c) 2006-2008 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_DOM_UI_CHROME_URL_DATA_MANAGER_H_ #define CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_ #include #include #include "base/task.h" #include "base/ref_counted_memory.h" class DictionaryValue; class FilePath; class GURL; class MessageLoop; class URLRequest; class URLRequestChromeJob; class URLRequestJob; // 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. class ChromeURLDataManager { public: ChromeURLDataManager(); ~ChromeURLDataManager(); typedef int RequestID; // A DataSource is an object that can answer requests for data // asynchronously. It should live on a thread that outlives the IO thread // (in particular, the UI thread). // An implementation of DataSource should handle calls to StartDataRequest() // by starting its (implementation-specific) asynchronous request for // the data, then call SendResponse() to notify class DataSource : public base::RefCountedThreadSafe { public: // See source_name_ and message_loop_ below for docs on these parameters. DataSource(const std::string& source_name, MessageLoop* message_loop) : source_name_(source_name), message_loop_(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 // not be satisfied. virtual void StartDataRequest(const std::string& path, bool is_off_the_record, int request_id) = 0; // Return the mimetype that should be sent with this response, or empty // string to specify no mime type. virtual std::string GetMimeType(const std::string& path) const = 0; // Report that a request has resulted in the data |bytes|. // If the request can't be satisfied, pass NULL for |bytes| to indicate // the request is over. virtual void SendResponse(int request_id, RefCountedMemory* bytes); // Returns the MessageLoop on which the DataSource wishes to have // StartDataRequest called to handle the request for |path|. If the // DataSource does not care which thread StartDataRequest is called on, // this should return NULL. The default implementation always returns // message_loop_, which generally results in processing on the UI thread. // It may be beneficial to return NULL for requests that are safe to handle // directly on the IO thread. This can improve performance by satisfying // such requests more rapidly when there is a large amount of UI thread // contention. virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) const; const std::string& source_name() const { return source_name_; } static void SetFontAndTextDirection(DictionaryValue* localized_strings); protected: friend class base::RefCountedThreadSafe; virtual ~DataSource() {} private: // 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. const std::string source_name_; // The MessageLoop for the thread where this DataSource lives. // Used to send messages to the DataSource. MessageLoop* message_loop_; }; // 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 source); // 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); static URLRequestJob* Factory(URLRequest* request, const std::string& scheme); private: friend class URLRequestChromeJob; // Parse a URL into the components used to resolve its request. static void URLToRequest(const GURL& url, std::string* source, std::string* path); // 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); // 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); // 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; // Sent by Request::SendResponse. void DataAvailable(RequestID request_id, scoped_refptr bytes); // File sources of data, keyed by source name (e.g. "inspector"). typedef std::map FileSourceMap; FileSourceMap file_sources_; // Custom sources of data, keyed by source path (e.g. "favicon"). typedef std::map > 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 PendingRequestMap; PendingRequestMap pending_requests_; // The ID we'll use for the next request we receive. RequestID next_request_id_; }; // Since we have a single global ChromeURLDataManager, we don't need to // grab a reference to it when creating Tasks involving it. template <> struct RunnableMethodTraits { void RetainCallee(ChromeURLDataManager* manager) {} void ReleaseCallee(ChromeURLDataManager* manager) {} }; // 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_