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