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
29class Profile;
30using content::BrowserThread;
31
32namespace extensions {
33class Extension;
34class ActivityLogPolicy;
35
36// A utility for tracing interesting activity for each extension.
37// It writes to an ActivityDatabase on a separate thread to record the activity.
38class ActivityLog : public BrowserContextKeyedService,
39                    public TabHelper::ScriptExecutionObserver,
40                    public InstallObserver {
41 public:
42  // Observers can listen for activity events. There is probably only one
43  // observer: the activityLogPrivate API.
44  class Observer {
45   public:
46    virtual void OnExtensionActivity(scoped_refptr<Action> activity) = 0;
47  };
48
49  // ActivityLog is a singleton, so don't instantiate it with the constructor;
50  // use GetInstance instead.
51  static ActivityLog* GetInstance(Profile* profile);
52
53  // Provides up-to-date information about whether the AL is enabled for a
54  // profile. The AL is enabled if the user has installed the whitelisted
55  // AL extension *or* set the --enable-extension-activity-logging flag.
56  bool IsLogEnabled();
57
58  // If you want to know whether the log is enabled but DON'T have a profile
59  // object yet, use this method. However, it's preferable for the caller to
60  // use IsLogEnabled when possible.
61  static bool IsLogEnabledOnAnyProfile();
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  // Retrieves the list of actions for a given extension on a specific day.
74  // Today is 0, yesterday is 1, etc. Returns one day at a time.
75  // Response is sent to the method/function in the callback.
76  // Use base::Bind to create the callback.
77  void GetActions(const std::string& extension_id,
78                  const int day,
79                  const base::Callback
80                      <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>&
81                      callback);
82
83  // Extension::InstallObserver
84  // We keep track of whether the whitelisted extension is installed; if it is,
85  // we want to recompute whether to have logging enabled.
86  virtual void OnExtensionInstalled(
87      const extensions::Extension* extension) OVERRIDE {}
88  virtual void OnExtensionLoaded(
89      const extensions::Extension* extension) OVERRIDE;
90  virtual void OnExtensionUnloaded(
91      const extensions::Extension* extension) OVERRIDE;
92  virtual void OnExtensionUninstalled(
93      const extensions::Extension* extension) OVERRIDE {}
94  // We also have to list the following from InstallObserver.
95  virtual void OnBeginExtensionInstall(const std::string& extension_id,
96                                       const std::string& extension_name,
97                                       const gfx::ImageSkia& installing_icon,
98                                       bool is_app,
99                                       bool is_platform_app) OVERRIDE {}
100  virtual void OnDownloadProgress(const std::string& extension_id,
101                                  int percent_downloaded) OVERRIDE {}
102  virtual void OnInstallFailure(const std::string& extension_id) OVERRIDE {}
103  virtual void OnAppsReordered() OVERRIDE {}
104  virtual void OnAppInstalledToAppList(
105      const std::string& extension_id) OVERRIDE {}
106  virtual void OnShutdown() OVERRIDE {}
107
108  // BrowserContextKeyedService
109  virtual void Shutdown() OVERRIDE;
110
111 private:
112  friend class ActivityLogFactory;
113  friend class ActivityLogTest;
114  friend class RenderViewActivityLogTest;
115
116  explicit ActivityLog(Profile* profile);
117  virtual ~ActivityLog();
118
119  // Some setup needs to wait until after the ExtensionSystem/ExtensionService
120  // are done with their own setup.
121  void Init();
122
123  // TabHelper::ScriptExecutionObserver implementation.
124  // Fires when a ContentScript is executed.
125  virtual void OnScriptsExecuted(
126      const content::WebContents* web_contents,
127      const ExecutingScriptsMap& extension_ids,
128      int32 page_id,
129      const GURL& on_url) OVERRIDE;
130
131  // For unit tests only. Does not call Init again!
132  // Sets whether logging should be enabled for the whole current profile.
133  static void RecomputeLoggingIsEnabled(bool profile_enabled);
134
135  // At the moment, ActivityLog will use only one policy for summarization.
136  // These methods are used to choose and set the most appropriate policy.
137  void ChooseDefaultPolicy();
138  void SetDefaultPolicy(ActivityLogPolicy::PolicyType policy_type);
139
140  typedef ObserverListThreadSafe<Observer> ObserverList;
141  scoped_refptr<ObserverList> observers_;
142
143  // The policy object takes care of data summarization, compression, and
144  // logging.  The policy object is owned by the ActivityLog, but this cannot
145  // be a scoped_ptr since some cleanup work must happen on the database
146  // thread.  Calling policy_->Close() will free the object; see the comments
147  // on the ActivityDatabase class for full details.
148  extensions::ActivityLogPolicy* policy_;
149
150  // TODO(dbabic,felt) change this into a list of policy types later.
151  ActivityLogPolicy::PolicyType policy_type_;
152
153  Profile* profile_;
154  bool enabled_;  // Whether logging is currently enabled.
155  bool initialized_;  // Whether Init() has already been called.
156  bool policy_chosen_;  // Whether we've already set the default policy.
157  // testing_mode_ controls whether to log API call arguments. By default, we
158  // don't log most arguments to avoid saving too much data. In testing mode,
159  // argument collection is enabled. We also whitelist some arguments for
160  // collection regardless of whether this bool is true.
161  // When testing_mode_ is enabled, we also print to the console.
162  bool testing_mode_;
163  // We need the DB, FILE, and IO threads to operate. In some cases (tests),
164  // these threads might not exist, so we avoid dispatching anything to the
165  // ActivityDatabase to prevent things from exploding.
166  bool has_threads_;
167
168  // Used to track whether the whitelisted extension is installed. If it's
169  // added or removed, enabled_ may change.
170  InstallTracker* tracker_;
171
172  DISALLOW_COPY_AND_ASSIGN(ActivityLog);
173};
174
175// Each profile has different extensions, so we keep a different database for
176// each profile.
177class ActivityLogFactory : public BrowserContextKeyedServiceFactory {
178 public:
179  static ActivityLog* GetForProfile(Profile* profile) {
180    return static_cast<ActivityLog*>(
181        GetInstance()->GetServiceForBrowserContext(profile, true));
182  }
183
184  static ActivityLogFactory* GetInstance();
185
186 private:
187  friend struct DefaultSingletonTraits<ActivityLogFactory>;
188  ActivityLogFactory();
189  virtual ~ActivityLogFactory();
190
191  virtual BrowserContextKeyedService* BuildServiceInstanceFor(
192      content::BrowserContext* profile) const OVERRIDE;
193
194  virtual content::BrowserContext* GetBrowserContextToUse(
195      content::BrowserContext* context) const OVERRIDE;
196
197  DISALLOW_COPY_AND_ASSIGN(ActivityLogFactory);
198};
199
200
201}  // namespace extensions
202
203#endif  // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_
204