Home | History | Annotate | Download | only in activity_log
      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_ACTIVITY_LOG_ACTIVITY_LOG_H_
      6 #define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/callback.h"
     13 #include "base/memory/singleton.h"
     14 #include "base/observer_list_threadsafe.h"
     15 #include "base/synchronization/lock.h"
     16 #include "base/threading/thread.h"
     17 #include "chrome/browser/extensions/activity_log/activity_actions.h"
     18 #include "chrome/browser/extensions/activity_log/activity_database.h"
     19 #include "chrome/browser/extensions/activity_log/activity_log_policy.h"
     20 #include "chrome/browser/extensions/install_observer.h"
     21 #include "chrome/browser/extensions/install_tracker.h"
     22 #include "chrome/browser/extensions/tab_helper.h"
     23 #include "chrome/browser/profiles/profile.h"
     24 #include "chrome/common/extensions/dom_action_types.h"
     25 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
     26 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
     27 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
     28 #include "extensions/browser/event_router.h"
     29 
     30 class Profile;
     31 using content::BrowserThread;
     32 
     33 namespace content {
     34 class BrowserContext;
     35 }
     36 
     37 namespace user_prefs {
     38 class PrefRegistrySyncable;
     39 }
     40 
     41 namespace extensions {
     42 class Extension;
     43 class ActivityLogPolicy;
     44 
     45 // A utility for tracing interesting activity for each extension.
     46 // It writes to an ActivityDatabase on a separate thread to record the activity.
     47 class ActivityLog : public BrowserContextKeyedService,
     48                     public EventRouter::EventDispatchObserver,
     49                     public TabHelper::ScriptExecutionObserver,
     50                     public InstallObserver {
     51  public:
     52   // Observers can listen for activity events. There is probably only one
     53   // observer: the activityLogPrivate API.
     54   class Observer {
     55    public:
     56     virtual void OnExtensionActivity(scoped_refptr<Action> activity) = 0;
     57   };
     58 
     59   // ActivityLog is a singleton, so don't instantiate it with the constructor;
     60   // use GetInstance instead.
     61   static ActivityLog* GetInstance(content::BrowserContext* context);
     62 
     63   // Add/remove observer: the activityLogPrivate API only listens when the
     64   // ActivityLog extension is registered for an event.
     65   void AddObserver(Observer* observer);
     66   void RemoveObserver(Observer* observer);
     67 
     68   // Logs an extension action: passes it to any installed policy to be logged
     69   // to the database, to any observers, and logs to the console if in testing
     70   // mode.
     71   void LogAction(scoped_refptr<Action> action);
     72 
     73   // Gets all actions that match the specified fields. URLs are treated like
     74   // prefixes; other fields are exact matches. Empty strings are not matched to
     75   // anything. For daysAgo, today is 0, yesterday is 1, etc.; a negative number
     76   // of days is treated as a missing parameter.
     77   void GetFilteredActions(
     78       const std::string& extension_id,
     79       const Action::ActionType type,
     80       const std::string& api_name,
     81       const std::string& page_url,
     82       const std::string& arg_url,
     83       const int days_ago,
     84       const base::Callback
     85           <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback);
     86 
     87   // Extension::InstallObserver
     88   // We keep track of whether the whitelisted extension is installed; if it is,
     89   // we want to recompute whether to have logging enabled.
     90   virtual void OnExtensionInstalled(const Extension* extension) OVERRIDE {}
     91   virtual void OnExtensionLoaded(const Extension* extension) OVERRIDE;
     92   virtual void OnExtensionUnloaded(const Extension* extension) OVERRIDE;
     93   virtual void OnExtensionUninstalled(const Extension* extension) OVERRIDE;
     94   // We also have to list the following from InstallObserver.
     95   virtual void OnBeginExtensionInstall(
     96       const ExtensionInstallParams& params) OVERRIDE {}
     97   virtual void OnDownloadProgress(const std::string& extension_id,
     98                                   int percent_downloaded) OVERRIDE {}
     99   virtual void OnInstallFailure(const std::string& extension_id) OVERRIDE {}
    100   virtual void OnAppsReordered() OVERRIDE {}
    101   virtual void OnAppInstalledToAppList(
    102       const std::string& extension_id) OVERRIDE {}
    103   virtual void OnShutdown() OVERRIDE {}
    104 
    105   // EventRouter::EventDispatchObserver
    106   virtual void OnWillDispatchEvent(scoped_ptr<EventDispatchInfo> details)
    107       OVERRIDE;
    108 
    109   // BrowserContextKeyedService
    110   virtual void Shutdown() OVERRIDE;
    111 
    112   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
    113 
    114   // Clean up URLs from the activity log database.
    115   // If restrict_urls is empty then all URLs in the activity log database are
    116   // removed, otherwise only those in restrict_urls are removed.
    117   void RemoveURLs(const std::vector<GURL>& restrict_urls);
    118   void RemoveURLs(const std::set<GURL>& restrict_urls);
    119   void RemoveURL(const GURL& url);
    120 
    121   // Deletes the database associated with the policy that's currently in use.
    122   void DeleteDatabase();
    123 
    124  private:
    125   friend class ActivityLogFactory;
    126   friend class ActivityLogTest;
    127   friend class RenderViewActivityLogTest;
    128 
    129   explicit ActivityLog(Profile* profile);
    130   virtual ~ActivityLog();
    131 
    132   // Specifies if the Watchdog app is active (installed & enabled).
    133   // If so, we need to log to the database and stream to the API.
    134   bool IsWatchdogAppActive();
    135   // If we're in a browser test, we need to pretend that the watchdog app is
    136   // active.
    137   void SetWatchdogAppActive(bool active);
    138 
    139   // Specifies if we need to record actions to the db. If so, we need to log to
    140   // the database. This is true if the Watchdog app is active *or* the
    141   // --enable-extension-activity-logging flag is set.
    142   bool IsDatabaseEnabled();
    143 
    144   // Delayed initialization of Install Tracker which waits until after the
    145   // ExtensionSystem/ExtensionService are done with their own setup.
    146   void InitInstallTracker();
    147 
    148   // TabHelper::ScriptExecutionObserver implementation.
    149   // Fires when a ContentScript is executed.
    150   virtual void OnScriptsExecuted(
    151       const content::WebContents* web_contents,
    152       const ExecutingScriptsMap& extension_ids,
    153       int32 page_id,
    154       const GURL& on_url) OVERRIDE;
    155 
    156   // At the moment, ActivityLog will use only one policy for summarization.
    157   // These methods are used to choose and set the most appropriate policy.
    158   // Changing policies at runtime is not recommended, and likely only should be
    159   // done for unit tests.
    160   void ChooseDatabasePolicy();
    161   void SetDatabasePolicy(ActivityLogPolicy::PolicyType policy_type);
    162 
    163   typedef ObserverListThreadSafe<Observer> ObserverList;
    164   scoped_refptr<ObserverList> observers_;
    165 
    166   // Policy objects are owned by the ActivityLog, but cannot be scoped_ptrs
    167   // since they may need to do some cleanup work on the database thread.
    168   // Calling policy->Close() will free the object; see the comments on the
    169   // ActivityDatabase class for full details.
    170 
    171   // The database policy object takes care of recording & looking up data:
    172   // data summarization, compression, and logging. There should only be a
    173   // database_policy_ if the Watchdog app is installed or flag is set.
    174   ActivityLogDatabasePolicy* database_policy_;
    175   ActivityLogPolicy::PolicyType database_policy_type_;
    176 
    177   // The UMA policy is used for recording statistics about extension behavior.
    178   // This policy is always in use, except for Incognito profiles.
    179   ActivityLogPolicy* uma_policy_;
    180 
    181   Profile* profile_;
    182   bool db_enabled_;  // Whether logging to disk is currently enabled.
    183   // testing_mode_ controls which policy is selected.
    184   // * By default, we choose a policy that doesn't log most arguments to avoid
    185   // saving too much data. We also elide some arguments for privacy reasons.
    186   // * In testing mode, we choose a policy that logs all arguments.
    187   // testing_mode_ also causes us to print to the console.
    188   bool testing_mode_;
    189   // We need the DB, FILE, and IO threads to write to the database.
    190   // In some cases (tests), these threads might not exist, so we avoid
    191   // dispatching anything to the policies/database to prevent things from
    192   // exploding.
    193   bool has_threads_;
    194 
    195   // Used to track whether the whitelisted extension is installed. If it's
    196   // added or removed, enabled_ may change.
    197   InstallTracker* tracker_;
    198 
    199   // Set if the watchdog app is installed and enabled. Maintained by
    200   // kWatchdogExtensionActive pref variable. Since there are multiple valid
    201   // extension IDs, this needs to be an int to count how many are installed.
    202   int watchdog_apps_active_;
    203 
    204   FRIEND_TEST_ALL_PREFIXES(ActivityLogApiTest, TriggerEvent);
    205   FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, AppAndCommandLine);
    206   FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, CommandLineSwitch);
    207   FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, NoSwitch);
    208   FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, PrefSwitch);
    209   FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, WatchdogSwitch);
    210   DISALLOW_COPY_AND_ASSIGN(ActivityLog);
    211 };
    212 
    213 // Each profile has different extensions, so we keep a different database for
    214 // each profile.
    215 class ActivityLogFactory : public BrowserContextKeyedServiceFactory {
    216  public:
    217   static ActivityLog* GetForBrowserContext(content::BrowserContext* context) {
    218     return static_cast<ActivityLog*>(
    219         GetInstance()->GetServiceForBrowserContext(context, true));
    220   }
    221 
    222   static ActivityLogFactory* GetInstance();
    223 
    224  private:
    225   friend struct DefaultSingletonTraits<ActivityLogFactory>;
    226   ActivityLogFactory();
    227   virtual ~ActivityLogFactory();
    228 
    229   virtual BrowserContextKeyedService* BuildServiceInstanceFor(
    230       content::BrowserContext* profile) const OVERRIDE;
    231 
    232   virtual content::BrowserContext* GetBrowserContextToUse(
    233       content::BrowserContext* context) const OVERRIDE;
    234 
    235   DISALLOW_COPY_AND_ASSIGN(ActivityLogFactory);
    236 };
    237 
    238 
    239 }  // namespace extensions
    240 
    241 #endif  // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_
    242