summaryrefslogtreecommitdiffstats
path: root/chrome/browser/webui/chrome_url_data_manager.h
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/webui/chrome_url_data_manager.h')
-rw-r--r--chrome/browser/webui/chrome_url_data_manager.h183
1 files changed, 183 insertions, 0 deletions
diff --git a/chrome/browser/webui/chrome_url_data_manager.h b/chrome/browser/webui/chrome_url_data_manager.h
new file mode 100644
index 0000000..be4cab0
--- /dev/null
+++ b/chrome/browser/webui/chrome_url_data_manager.h
@@ -0,0 +1,183 @@
+// 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.
+
+#ifndef CHROME_BROWSER_WEBUI_CHROME_URL_DATA_MANAGER_H_
+#define CHROME_BROWSER_WEBUI_CHROME_URL_DATA_MANAGER_H_
+#pragma once
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/ref_counted.h"
+#include "base/task.h"
+#include "chrome/browser/browser_thread.h"
+
+class ChromeURLDataManagerBackend;
+class DictionaryValue;
+class FilePath;
+class MessageLoop;
+class Profile;
+class RefCountedMemory;
+
+// To serve dynamic data off of chrome: URLs, implement the
+// ChromeURLDataManager::DataSource interface and register your handler
+// 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:
+ class DataSource;
+
+ // 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
+ // pointers and should never be deleted on the IO thread, since their calls
+ // are handled almost always on the UI thread and there's a possibility of a
+ // data race. The |DeleteOnUIThread| trait is used to enforce this.
+ //
+ // 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<
+ DataSource, DeleteDataSource> {
+ public:
+ // See source_name_ and message_loop_ below for docs on these parameters.
+ 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
+ // 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:
+ 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.
+ const std::string source_name_;
+
+ // 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_;
+ };
+
+ explicit ChromeURLDataManager(Profile* profile);
+ ~ChromeURLDataManager();
+
+ // 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);
+
+ // Returns true if a DataSource has been added with the given name.
+ bool IsRegistered(const std::string& name);
+
+ // 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:
+ typedef std::vector<const ChromeURLDataManager::DataSource*> DataSources;
+
+ // 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);
+
+ // Returns true if |data_source| is scheduled for deletion (|DeleteDataSource|
+ // was invoked).
+ static bool IsScheduledForDeletion(const DataSource* data_source);
+
+ Profile* profile_;
+
+ // Names of the DataSources that have been registered.
+ // By caching this rather than accessing ChromeURLDataManagerBackend we avoid
+ // a delay between when AddDataSource is invoked and when the IO thread
+ // processes it.
+ std::set<std::string> registered_source_names_;
+
+ // Lock used when accessing |data_sources_|.
+ static base::Lock delete_lock_;
+
+ // |data_sources_| that are no longer referenced and scheduled for deletion.
+ static DataSources* data_sources_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManager);
+};
+
+#endif // CHROME_BROWSER_WEBUI_CHROME_URL_DATA_MANAGER_H_