Home | History | Annotate | Download | only in activity_log
      1 // Copyright 2013 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_ACTIVITY_LOG_ACTIVITY_LOG_POLICY_H_
      6 #define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_POLICY_H_
      7 
      8 #include <map>
      9 #include <set>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/bind.h"
     14 #include "base/bind_helpers.h"
     15 #include "base/callback.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/values.h"
     18 #include "chrome/browser/extensions/activity_log/activity_actions.h"
     19 #include "chrome/browser/extensions/activity_log/activity_database.h"
     20 #include "chrome/common/extensions/api/activity_log_private.h"
     21 #include "content/public/browser/browser_thread.h"
     22 #include "url/gurl.h"
     23 
     24 class Profile;
     25 class GURL;
     26 
     27 namespace base {
     28 class FilePath;
     29 }
     30 
     31 namespace extensions {
     32 
     33 class Extension;
     34 
     35 // An abstract class for processing and summarizing activity log data.
     36 // Subclasses will generally store data in an SQLite database (the
     37 // ActivityLogDatabasePolicy subclass includes some helper methods to assist
     38 // with this case), but this is not absolutely required.
     39 //
     40 // Implementations should support:
     41 // (1) Receiving Actions to process, and summarizing, compression, and storing
     42 //     these as appropriate.
     43 // (2) Reading Actions back from storage.
     44 // (3) Cleaning of URLs
     45 //
     46 // Implementations based on a database should likely implement
     47 // ActivityDatabase::Delegate, which provides hooks on database events and
     48 // allows the database to periodically request that actions (which the policy
     49 // is responsible for queueing) be flushed to storage.
     50 //
     51 // Since every policy implementation might summarize data differently, the
     52 // database implementation is policy-specific and therefore completely
     53 // encapsulated in the policy class.  All the member functions can be called
     54 // on the UI thread.
     55 class ActivityLogPolicy {
     56  public:
     57   enum PolicyType {
     58     POLICY_FULLSTREAM,
     59     POLICY_COUNTS,
     60     POLICY_INVALID,
     61   };
     62 
     63   // Parameters are the profile and the thread that will be used to execute
     64   // the callback when ReadData is called.
     65   // TODO(felt,dbabic)  Since only ReadData uses thread_id, it would be
     66   // cleaner to pass thread_id as a param of ReadData directly.
     67   explicit ActivityLogPolicy(Profile* profile);
     68 
     69   // Instead of a public destructor, ActivityLogPolicy objects have a Close()
     70   // method which will cause the object to be deleted (but may do so on another
     71   // thread or in a deferred fashion).
     72   virtual void Close() = 0;
     73 
     74   // Updates the internal state of the model summarizing actions and possibly
     75   // writes to the database.  Implements the default policy storing internal
     76   // state to memory every 5 min.
     77   virtual void ProcessAction(scoped_refptr<Action> action) = 0;
     78 
     79   // For unit testing only.
     80   void SetClockForTesting(scoped_ptr<base::Clock> clock);
     81 
     82   // A collection of methods that are useful for implementing policies.  These
     83   // are all static methods; the ActivityLogPolicy::Util class cannot be
     84   // instantiated.  This is nested within ActivityLogPolicy to make calling
     85   // these methods more convenient from within a policy, but they are public.
     86   class Util {
     87    public:
     88     // A collection of API calls, used to specify whitelists for argument
     89     // filtering.
     90     typedef std::set<std::pair<Action::ActionType, std::string> > ApiSet;
     91 
     92     // Serialize a Value as a JSON string.  Returns an empty string if value is
     93     // null.
     94     static std::string Serialize(const base::Value* value);
     95 
     96     // Removes potentially privacy-sensitive data that should not be logged.
     97     // This should generally be called on an Action before logging, unless
     98     // debugging flags are enabled.  Modifies the Action object in place; if
     99     // the action might be shared with other users, it is up to the caller to
    100     // call ->Clone() first.
    101     static void StripPrivacySensitiveFields(scoped_refptr<Action> action);
    102 
    103     // Strip arguments from most API actions, preserving actions only for a
    104     // whitelisted set.  Modifies the Action object in-place.
    105     static void StripArguments(const ApiSet& api_whitelist,
    106                                scoped_refptr<Action> action);
    107 
    108     // Given a base day (timestamp at local midnight), computes the timestamp
    109     // at midnight the given number of days before or after.
    110     static base::Time AddDays(const base::Time& base_date, int days);
    111 
    112     // Compute the time bounds that should be used for a database query to
    113     // cover a time range days_ago days in the past, relative to the specified
    114     // time.
    115     static void ComputeDatabaseTimeBounds(const base::Time& now,
    116                                           int days_ago,
    117                                           int64* early_bound,
    118                                           int64* late_bound);
    119 
    120     // Deletes obsolete database tables from an activity log database.  This
    121     // can be used in InitDatabase() methods of ActivityLogDatabasePolicy
    122     // subclasses to clean up data from old versions of the activity logging
    123     // code.  Returns true on success, false on database error.
    124     static bool DropObsoleteTables(sql::Connection* db);
    125 
    126    private:
    127     DISALLOW_IMPLICIT_CONSTRUCTORS(Util);
    128   };
    129 
    130  protected:
    131   // An ActivityLogPolicy is not directly destroyed.  Instead, call Close()
    132   // which will cause the object to be deleted when it is safe.
    133   virtual ~ActivityLogPolicy();
    134 
    135   // Returns Time::Now() unless a mock clock has been installed with
    136   // SetClockForTesting, in which case the time according to that clock is used
    137   // instead.
    138   base::Time Now() const;
    139 
    140  private:
    141   // Support for a mock clock for testing purposes.  This is used by ReadData
    142   // to determine the date for "today" when when interpreting date ranges to
    143   // fetch.  This has no effect on batching of writes to the database.
    144   scoped_ptr<base::Clock> testing_clock_;
    145 
    146   DISALLOW_COPY_AND_ASSIGN(ActivityLogPolicy);
    147 };
    148 
    149 // A subclass of ActivityLogPolicy which is designed for policies that use
    150 // database storage; it contains several useful helper methods.
    151 class ActivityLogDatabasePolicy : public ActivityLogPolicy,
    152                                   public ActivityDatabase::Delegate {
    153  public:
    154   ActivityLogDatabasePolicy(Profile* profile,
    155                             const base::FilePath& database_name);
    156 
    157   // Initializes an activity log policy database. This needs to be called after
    158   // constructing ActivityLogDatabasePolicy.
    159   void Init();
    160 
    161   // Requests that in-memory state be written to the database.  This method can
    162   // be called from any thread, but the database writes happen asynchronously
    163   // on the database thread.
    164   virtual void Flush();
    165 
    166   // Gets all actions that match the specified fields. URLs are treated like
    167   // prefixes; other fields are exact matches. Empty strings are not matched to
    168   // anything. For the date: 0 = today, 1 = yesterday, etc.; if the data is
    169   // negative, it will be treated as missing.
    170   virtual void ReadFilteredData(
    171       const std::string& extension_id,
    172       const Action::ActionType type,
    173       const std::string& api_name,
    174       const std::string& page_url,
    175       const std::string& arg_url,
    176       const int days_ago,
    177       const base::Callback
    178          <void(scoped_ptr<Action::ActionVector>)>& callback) = 0;
    179 
    180   // Remove actions (rows) which IDs are in the action_ids array.
    181   virtual void RemoveActions(const std::vector<int64>& action_ids) = 0;
    182 
    183   // Clean the relevant URL data. The cleaning may need to be different for
    184   // different policies. If restrict_urls is empty then all URLs are removed.
    185   virtual void RemoveURLs(const std::vector<GURL>& restrict_urls) = 0;
    186 
    187   // Remove all rows relating to a given extension.
    188   virtual void RemoveExtensionData(const std::string& extension_id) = 0;
    189 
    190   // Deletes everything in the database.
    191   virtual void DeleteDatabase() = 0;
    192 
    193  protected:
    194   // The Schedule methods dispatch the calls to the database on a
    195   // separate thread.
    196   template<typename DatabaseType, typename DatabaseFunc>
    197   void ScheduleAndForget(DatabaseType db, DatabaseFunc func) {
    198     content::BrowserThread::PostTask(
    199         content::BrowserThread::DB,
    200         FROM_HERE,
    201         base::Bind(func, base::Unretained(db)));
    202   }
    203 
    204   template<typename DatabaseType, typename DatabaseFunc, typename ArgA>
    205   void ScheduleAndForget(DatabaseType db, DatabaseFunc func, ArgA a) {
    206     content::BrowserThread::PostTask(
    207         content::BrowserThread::DB,
    208         FROM_HERE,
    209         base::Bind(func, base::Unretained(db), a));
    210   }
    211 
    212   template<typename DatabaseType, typename DatabaseFunc,
    213       typename ArgA, typename ArgB>
    214   void ScheduleAndForget(DatabaseType db, DatabaseFunc func, ArgA a, ArgB b) {
    215     content::BrowserThread::PostTask(
    216         content::BrowserThread::DB,
    217         FROM_HERE,
    218         base::Bind(func, base::Unretained(db), a, b));
    219   }
    220 
    221   // Access to the underlying ActivityDatabase.
    222   ActivityDatabase* activity_database() const { return db_; }
    223 
    224   // Access to the SQL connection in the ActivityDatabase.  This should only be
    225   // called from the database thread.  May return NULL if the database is not
    226   // valid.
    227   sql::Connection* GetDatabaseConnection() const;
    228 
    229  private:
    230   // See the comments for the ActivityDatabase class for a discussion of how
    231   // database cleanup runs.
    232   ActivityDatabase* db_;
    233   base::FilePath database_path_;
    234 };
    235 
    236 }  // namespace extensions
    237 
    238 #endif  // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_POLICY_H_
    239