Home | History | Annotate | Download | only in declarative
      1 // Copyright (c) 2012 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_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_H__
      6 #define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_H__
      7 
      8 #include <map>
      9 #include <set>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/callback_forward.h"
     14 #include "base/compiler_specific.h"
     15 #include "base/gtest_prod_util.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/memory/weak_ptr.h"
     18 #include "chrome/common/extensions/api/events.h"
     19 #include "content/public/browser/browser_thread.h"
     20 #include "content/public/browser/notification_observer.h"
     21 #include "content/public/browser/notification_registrar.h"
     22 #include "extensions/common/one_shot_event.h"
     23 
     24 class Profile;
     25 
     26 namespace base {
     27 class Value;
     28 }  // namespace base
     29 
     30 namespace extensions {
     31 
     32 class RulesCacheDelegate;
     33 
     34 // A base class for RulesRegistries that takes care of storing the
     35 // RulesRegistry::Rule objects. It contains all the methods that need to run on
     36 // the registry thread; methods that need to run on the UI thread are separated
     37 // in the RulesCacheDelegate object.
     38 class RulesRegistry : public base::RefCountedThreadSafe<RulesRegistry> {
     39  public:
     40   typedef extensions::api::events::Rule Rule;
     41   struct WebViewKey {
     42     int embedder_process_id;
     43     int webview_instance_id;
     44     WebViewKey(int embedder_process_id, int webview_instance_id)
     45         : embedder_process_id(embedder_process_id),
     46           webview_instance_id(webview_instance_id) {}
     47     bool operator<(const WebViewKey& other) const {
     48       return embedder_process_id < other.embedder_process_id ||
     49           ((embedder_process_id == other.embedder_process_id) &&
     50            (webview_instance_id < other.webview_instance_id));
     51     }
     52   };
     53 
     54   enum Defaults { DEFAULT_PRIORITY = 100 };
     55   // After the RulesCacheDelegate object (the part of the registry which runs on
     56   // the UI thread) is created, a pointer to it is passed to |*ui_part|.
     57   // In tests, |profile| and |ui_part| can be NULL (at the same time). In that
     58   // case the storage functionality disabled (no RulesCacheDelegate object
     59   // created).
     60   RulesRegistry(Profile* profile,
     61                 const std::string& event_name,
     62                 content::BrowserThread::ID owner_thread,
     63                 RulesCacheDelegate* cache_delegate,
     64                 const WebViewKey& webview_key);
     65 
     66   const OneShotEvent& ready() const {
     67     return ready_;
     68   }
     69 
     70   // RulesRegistry implementation:
     71 
     72   // Registers |rules|, owned by |extension_id| to this RulesRegistry.
     73   // If a concrete RuleRegistry does not support some of the rules,
     74   // it may ignore them.
     75   //
     76   // |rules| is a list of Rule instances following the definition of the
     77   // declarative extension APIs. It is guaranteed that each rule in |rules| has
     78   // a unique name within the scope of |extension_id| that has not been
     79   // registered before, unless it has been removed again.
     80   // The ownership of rules remains with the caller.
     81   //
     82   // Returns an empty string if the function is successful or an error
     83   // message otherwise.
     84   //
     85   // IMPORTANT: This function is atomic. Either all rules that are deemed
     86   // relevant are added or none.
     87   std::string AddRules(
     88       const std::string& extension_id,
     89       const std::vector<linked_ptr<RulesRegistry::Rule> >& rules);
     90 
     91   // Unregisters all rules listed in |rule_identifiers| and owned by
     92   // |extension_id| from this RulesRegistry.
     93   // Some or all IDs in |rule_identifiers| may not be stored in this
     94   // RulesRegistry and are ignored.
     95   //
     96   // Returns an empty string if the function is successful or an error
     97   // message otherwise.
     98   //
     99   // IMPORTANT: This function is atomic. Either all rules that are deemed
    100   // relevant are removed or none.
    101   std::string RemoveRules(
    102       const std::string& extension_id,
    103       const std::vector<std::string>& rule_identifiers);
    104 
    105   // Same as RemoveAllRules but acts on all rules owned by |extension_id|.
    106   std::string RemoveAllRules(const std::string& extension_id);
    107 
    108   // Returns all rules listed in |rule_identifiers| and owned by |extension_id|
    109   // registered in this RuleRegistry. Entries in |rule_identifiers| that
    110   // are unknown are ignored.
    111   //
    112   // The returned rules are stored in |out|. Ownership is passed to the caller.
    113   void GetRules(const std::string& extension_id,
    114                 const std::vector<std::string>& rule_identifiers,
    115                 std::vector<linked_ptr<RulesRegistry::Rule> >* out);
    116 
    117   // Same as GetRules but returns all rules owned by |extension_id|.
    118   void GetAllRules(const std::string& extension_id,
    119                    std::vector<linked_ptr<RulesRegistry::Rule> >* out);
    120 
    121   // Called to notify the RulesRegistry that the extension availability has
    122   // changed, so that the registry can update which rules are active.
    123   void OnExtensionUnloaded(const std::string& extension_id);
    124   void OnExtensionUninstalled(const std::string& extension_id);
    125   void OnExtensionLoaded(const std::string& extension_id);
    126 
    127   // Returns the number of entries in used_rule_identifiers_ for leak detection.
    128   // Every ExtensionId counts as one entry, even if it contains no rules.
    129   size_t GetNumberOfUsedRuleIdentifiersForTesting() const;
    130 
    131   // Returns the RulesCacheDelegate. This is used for testing.
    132   RulesCacheDelegate* rules_cache_delegate_for_testing() const {
    133     return cache_delegate_.get();
    134   }
    135 
    136   // Returns the profile where the rules registry lives.
    137   Profile* profile() const { return profile_; }
    138 
    139   // Returns the ID of the thread on which the rules registry lives.
    140   // It is safe to call this function from any thread.
    141   content::BrowserThread::ID owner_thread() const { return owner_thread_; }
    142 
    143   // The name of the event with which rules are registered.
    144   const std::string& event_name() const { return event_name_; }
    145 
    146   // The key that identifies the webview (or tabs) in which these rules apply.
    147   // If the rules apply to the main browser, then this returns the tuple (0, 0).
    148   const WebViewKey& webview_key() const {
    149     return webview_key_;
    150   }
    151 
    152  protected:
    153   virtual ~RulesRegistry();
    154 
    155   // The precondition for calling this method is that all rules have unique IDs.
    156   // AddRules establishes this precondition and calls into this method.
    157   // Stored rules already meet this precondition and so they avoid calling
    158   // CheckAndFillInOptionalRules for improved performance.
    159   //
    160   // Returns an empty string if the function is successful or an error
    161   // message otherwise.
    162   std::string AddRulesNoFill(
    163       const std::string& extension_id,
    164       const std::vector<linked_ptr<RulesRegistry::Rule> >& rules);
    165 
    166   // These functions need to apply the rules to the browser, while the base
    167   // class will handle defaulting empty fields before calling *Impl, and will
    168   // automatically cache the rules and re-call *Impl on browser startup.
    169   virtual std::string AddRulesImpl(
    170       const std::string& extension_id,
    171       const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) = 0;
    172   virtual std::string RemoveRulesImpl(
    173       const std::string& extension_id,
    174       const std::vector<std::string>& rule_identifiers) = 0;
    175   virtual std::string RemoveAllRulesImpl(
    176       const std::string& extension_id) = 0;
    177 
    178  private:
    179   friend class base::RefCountedThreadSafe<RulesRegistry>;
    180   friend class RulesCacheDelegate;
    181 
    182   typedef std::string ExtensionId;
    183   typedef std::string RuleId;
    184   typedef std::pair<ExtensionId, RuleId> RulesDictionaryKey;
    185   typedef std::map<RulesDictionaryKey, linked_ptr<RulesRegistry::Rule> >
    186       RulesDictionary;
    187   enum ProcessChangedRulesState {
    188     // ProcessChangedRules can never be called, |cache_delegate_| is NULL.
    189     NEVER_PROCESS,
    190     // A task to call ProcessChangedRules is scheduled for future execution.
    191     SCHEDULED_FOR_PROCESSING,
    192     // No task to call ProcessChangedRules is scheduled yet, but it is possible
    193     // to schedule one.
    194     NOT_SCHEDULED_FOR_PROCESSING
    195   };
    196   typedef std::map<ExtensionId, ProcessChangedRulesState> ProcessStateMap;
    197 
    198   base::WeakPtr<RulesRegistry> GetWeakPtr() {
    199     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    200     return weak_ptr_factory_.GetWeakPtr();
    201   }
    202 
    203   // Common processing after extension's rules have changed.
    204   void ProcessChangedRules(const std::string& extension_id);
    205 
    206   // Calls ProcessChangedRules if
    207   // |process_changed_rules_requested_(extension_id)| ==
    208   // NOT_SCHEDULED_FOR_PROCESSING.
    209   void MaybeProcessChangedRules(const std::string& extension_id);
    210 
    211   // This method implements the functionality of RemoveAllRules, except for not
    212   // calling MaybeProcessChangedRules. That way updating the rules store and
    213   // extension prefs is avoided. This method is called when an extension is
    214   // uninstalled, that way there is no clash with the preferences being wiped.
    215   std::string RemoveAllRulesNoStoreUpdate(const std::string& extension_id);
    216 
    217   void MarkReady(base::Time storage_init_time);
    218 
    219   // Deserialize the rules from the given Value object and add them to the
    220   // RulesRegistry.
    221   void DeserializeAndAddRules(const std::string& extension_id,
    222                               scoped_ptr<base::Value> rules);
    223 
    224   // The profile to which this rules registry belongs.
    225   Profile* profile_;
    226 
    227   // The ID of the thread on which the rules registry lives.
    228   const content::BrowserThread::ID owner_thread_;
    229 
    230   // The name of the event with which rules are registered.
    231   const std::string event_name_;
    232 
    233   // The key that identifies the context in which these rules apply.
    234   WebViewKey webview_key_;
    235 
    236   RulesDictionary rules_;
    237 
    238   // Signaled when we have finished reading from storage for all extensions that
    239   // are loaded on startup.
    240   OneShotEvent ready_;
    241 
    242   // The factory needs to be declared before |cache_delegate_|, so that it can
    243   // produce a pointer as a construction argument for |cache_delegate_|.
    244   base::WeakPtrFactory<RulesRegistry> weak_ptr_factory_;
    245 
    246   // |cache_delegate_| is owned by the registry service. If |cache_delegate_| is
    247   // NULL, then the storage functionality is disabled (this is used in tests).
    248   // This registry cannot own |cache_delegate_| because during the time after
    249   // rules registry service shuts down on UI thread, and the registry is
    250   // destroyed on its thread, the use of the |cache_delegate_| would not be
    251   // safe. The registry only ever associates with one RulesCacheDelegate
    252   // instance.
    253   base::WeakPtr<RulesCacheDelegate> cache_delegate_;
    254 
    255   ProcessStateMap process_changed_rules_requested_;
    256 
    257   // Returns whether any existing rule is registered with identifier |rule_id|
    258   // for extension |extension_id|.
    259   bool IsUniqueId(const std::string& extension_id,
    260                   const std::string& rule_id) const;
    261 
    262   // Creates an ID that is unique within the scope of|extension_id|.
    263   std::string GenerateUniqueId(const std::string& extension_id);
    264 
    265   // Verifies that all |rules| have unique IDs or initializes them with
    266   // unique IDs if they don't have one. In case of duplicate IDs, this function
    267   // returns a non-empty error message.
    268   std::string CheckAndFillInOptionalRules(
    269     const std::string& extension_id,
    270     const std::vector<linked_ptr<RulesRegistry::Rule> >& rules);
    271 
    272   // Initializes the priority fields in case they have not been set.
    273   void FillInOptionalPriorities(
    274       const std::vector<linked_ptr<RulesRegistry::Rule> >& rules);
    275 
    276   // Removes all |identifiers| of |extension_id| from |used_rule_identifiers_|.
    277   void RemoveUsedRuleIdentifiers(const std::string& extension_id,
    278                                  const std::vector<std::string>& identifiers);
    279 
    280   // Same as RemoveUsedRuleIdentifiers but operates on all rules of
    281   // |extension_id|.
    282   void RemoveAllUsedRuleIdentifiers(const std::string& extension_id);
    283 
    284   typedef std::string RuleIdentifier;
    285   typedef std::map<ExtensionId, std::set<RuleIdentifier> > RuleIdentifiersMap;
    286   RuleIdentifiersMap used_rule_identifiers_;
    287   int last_generated_rule_identifier_id_;
    288 
    289   DISALLOW_COPY_AND_ASSIGN(RulesRegistry);
    290 };
    291 
    292 }  // namespace extensions
    293 
    294 #endif  // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_H__
    295