1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ 6 #define CHROME_BROWSER_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ 7 #pragma once 8 9 #include <string> 10 11 #include "base/memory/ref_counted.h" 12 #include "base/task.h" 13 #include "content/browser/browser_thread.h" 14 15 class ChromeURLDataManagerBackend; 16 class DictionaryValue; 17 class FilePath; 18 class MessageLoop; 19 class Profile; 20 class RefCountedMemory; 21 22 // To serve dynamic data off of chrome: URLs, implement the 23 // ChromeURLDataManager::DataSource interface and register your handler 24 // with AddDataSource. DataSources must be added on the UI thread (they are also 25 // deleted on the UI thread). Internally the DataSources are maintained by 26 // ChromeURLDataManagerBackend, see it for details. 27 class ChromeURLDataManager { 28 public: 29 class DataSource; 30 31 // Trait used to handle deleting a DataSource. Deletion happens on the UI 32 // thread. 33 // 34 // Implementation note: the normal shutdown sequence is for the UI loop to 35 // stop pumping events then the IO loop and thread are stopped. When the 36 // DataSources are no longer referenced (which happens when IO thread stops) 37 // they get added to the UI message loop for deletion. But because the UI loop 38 // has stopped by the time this happens the DataSources would be leaked. 39 // 40 // To make sure DataSources are properly deleted ChromeURLDataManager manages 41 // deletion of the DataSources. When a DataSource is no longer referenced it 42 // is added to |data_sources_| and a task is posted to the UI thread to handle 43 // the actual deletion. During shutdown |DeleteDataSources| is invoked so that 44 // all pending DataSources are properly deleted. 45 struct DeleteDataSource { DestructDeleteDataSource46 static void Destruct(const DataSource* data_source) { 47 ChromeURLDataManager::DeleteDataSource(data_source); 48 } 49 }; 50 51 // A DataSource is an object that can answer requests for data 52 // asynchronously. DataSources are collectively owned with refcounting smart 53 // pointers and should never be deleted on the IO thread, since their calls 54 // are handled almost always on the UI thread and there's a possibility of a 55 // data race. The |DeleteDataSource| trait above is used to enforce this. 56 // 57 // An implementation of DataSource should handle calls to 58 // StartDataRequest() by starting its (implementation-specific) asynchronous 59 // request for the data, then call SendResponse() to notify. 60 class DataSource : public base::RefCountedThreadSafe< 61 DataSource, DeleteDataSource> { 62 public: 63 // See source_name_ and message_loop_ below for docs on these parameters. 64 DataSource(const std::string& source_name, MessageLoop* message_loop); 65 66 // Sent by the DataManager to request data at |path|. The source should 67 // call SendResponse() when the data is available or if the request could 68 // not be satisfied. 69 virtual void StartDataRequest(const std::string& path, 70 bool is_incognito, 71 int request_id) = 0; 72 73 // Return the mimetype that should be sent with this response, or empty 74 // string to specify no mime type. 75 virtual std::string GetMimeType(const std::string& path) const = 0; 76 77 // Report that a request has resulted in the data |bytes|. 78 // If the request can't be satisfied, pass NULL for |bytes| to indicate 79 // the request is over. 80 virtual void SendResponse(int request_id, RefCountedMemory* bytes); 81 82 // Returns the MessageLoop on which the DataSource wishes to have 83 // StartDataRequest called to handle the request for |path|. If the 84 // DataSource does not care which thread StartDataRequest is called on, 85 // this should return NULL. The default implementation always returns 86 // message_loop_, which generally results in processing on the UI thread. 87 // It may be beneficial to return NULL for requests that are safe to handle 88 // directly on the IO thread. This can improve performance by satisfying 89 // such requests more rapidly when there is a large amount of UI thread 90 // contention. 91 virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) 92 const; 93 source_name()94 const std::string& source_name() const { return source_name_; } 95 96 // Returns true if this DataSource should replace an existing DataSource 97 // with the same name that has already been registered. The default is 98 // true. 99 // 100 // WARNING: this is invoked on the IO thread. 101 // 102 // TODO: nuke this and convert all callers to not replace. 103 virtual bool ShouldReplaceExistingSource() const; 104 105 static void SetFontAndTextDirection(DictionaryValue* localized_strings); 106 107 protected: 108 virtual ~DataSource(); 109 110 private: 111 friend class ChromeURLDataManagerBackend; 112 friend class ChromeURLDataManager; 113 friend class DeleteTask<DataSource>; 114 115 // SendResponse invokes this on the IO thread. Notifies the backend to 116 // handle the actual work of sending the data. 117 virtual void SendResponseOnIOThread(int request_id, 118 scoped_refptr<RefCountedMemory> bytes); 119 120 // The name of this source. 121 // E.g., for favicons, this could be "favicon", which results in paths for 122 // specific resources like "favicon/34" getting sent to this source. 123 const std::string source_name_; 124 125 // The MessageLoop for the thread where this DataSource lives. 126 // Used to send messages to the DataSource. 127 MessageLoop* message_loop_; 128 129 // This field is set and maintained by ChromeURLDataManagerBackend. It is 130 // set when the DataSource is added, and unset if the DataSource is removed. 131 // A DataSource can be removed in two ways: the ChromeURLDataManagerBackend 132 // is deleted, or another DataSource is registered with the same 133 // name. backend_ should only be accessed on the IO thread. 134 // This reference can't be via a scoped_refptr else there would be a cycle 135 // between the backend and data source. 136 ChromeURLDataManagerBackend* backend_; 137 }; 138 139 explicit ChromeURLDataManager(Profile* profile); 140 ~ChromeURLDataManager(); 141 142 // Adds a DataSource to the collection of data sources. This *must* be invoked 143 // on the UI thread. 144 // 145 // If |AddDataSource| is called more than once for a particular name it will 146 // release the old |DataSource|, most likely resulting in it getting deleted 147 // as there are no other references to it. |DataSource| uses the 148 // |DeleteOnUIThread| trait to insure that the destructor is called on the UI 149 // thread. This is necessary as some |DataSource|s notably |FileIconSource| 150 // and |FaviconSource|, have members that will DCHECK if they are not 151 // destructed in the same thread as they are constructed (the UI thread). 152 void AddDataSource(DataSource* source); 153 154 // Deletes any data sources no longer referenced. This is normally invoked 155 // for you, but can be invoked to force deletion (such as during shutdown). 156 static void DeleteDataSources(); 157 158 private: 159 typedef std::vector<const ChromeURLDataManager::DataSource*> DataSources; 160 161 // If invoked on the UI thread the DataSource is deleted immediatlye, 162 // otherwise it is added to |data_sources_| and a task is scheduled to handle 163 // deletion on the UI thread. See note abouve DeleteDataSource for more info. 164 static void DeleteDataSource(const DataSource* data_source); 165 166 // Returns true if |data_source| is scheduled for deletion (|DeleteDataSource| 167 // was invoked). 168 static bool IsScheduledForDeletion(const DataSource* data_source); 169 170 Profile* profile_; 171 172 // Lock used when accessing |data_sources_|. 173 static base::Lock delete_lock_; 174 175 // |data_sources_| that are no longer referenced and scheduled for deletion. 176 static DataSources* data_sources_; 177 178 DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManager); 179 }; 180 181 #endif // CHROME_BROWSER_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ 182