Home | History | Annotate | Download | only in webui
      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 {
     46     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 
     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