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