activity_log.h revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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  // Log a successful API call made by an extension.
69  // This will create an APIAction for storage in the database.
70  // (Note: implemented as a wrapper for LogAPIActionInternal.)
71  void LogAPIAction(const std::string& extension_id,
72                    const std::string& name,    // e.g., tabs.get
73                    ListValue* args,            // the argument values e.g. 46
74                    const std::string& extra);  // any extra logging info
75
76  // Log an event notification delivered to an extension.
77  // This will create an APIAction for storage in the database.
78  // (Note: implemented as a wrapper for LogAPIActionInternal.)
79  void LogEventAction(const std::string& extension_id,
80                      const std::string& name,    // e.g., tabs.onUpdate
81                      ListValue* args,            // arguments to the callback
82                      const std::string& extra);  // any extra logging info
83
84  // Log a blocked API call made by an extension.
85  // This will create a BlockedAction for storage in the database.
86  void LogBlockedAction(const std::string& extension_id,
87                        const std::string& blocked_call,  // e.g., tabs.get
88                        ListValue* args,                  // argument values
89                        BlockedAction::Reason reason,     // why it's blocked
90                        const std::string& extra);        // extra logging info
91
92  // Log an interaction between an extension and a URL.
93  // This will create a DOMAction for storage in the database.
94  void LogDOMAction(const std::string& extension_id,
95                    const GURL& url,                      // target URL
96                    const string16& url_title,            // title of the URL
97                    const std::string& api_call,          // api call
98                    const ListValue* args,                // arguments
99                    DomActionType::Type call_type,        // type of the call
100                    const std::string& extra);            // extra logging info
101
102  // Log a use of the WebRequest API to redirect, cancel, or modify page
103  // headers.
104  void LogWebRequestAction(const std::string& extension_id,
105                           const GURL& url,
106                           const std::string& api_call,
107                           scoped_ptr<base::DictionaryValue> details,
108                           const std::string& extra);
109
110  // Retrieves the list of actions for a given extension on a specific day.
111  // Today is 0, yesterday is 1, etc. Returns one day at a time.
112  // Response is sent to the method/function in the callback.
113  // Use base::Bind to create the callback.
114  void GetActions(const std::string& extension_id,
115                  const int day,
116                  const base::Callback
117                      <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>&
118                      callback);
119
120  // Extension::InstallObserver
121  // We keep track of whether the whitelisted extension is installed; if it is,
122  // we want to recompute whether to have logging enabled.
123  virtual void OnExtensionInstalled(
124      const extensions::Extension* extension) OVERRIDE;
125  virtual void OnExtensionUninstalled(
126      const extensions::Extension* extension) OVERRIDE;
127  virtual void OnExtensionDisabled(
128      const extensions::Extension* extension) OVERRIDE;
129  // We also have to list the following from InstallObserver.
130  virtual void OnBeginExtensionInstall(const std::string& extension_id,
131                                       const std::string& extension_name,
132                                       const gfx::ImageSkia& installing_icon,
133                                       bool is_app,
134                                       bool is_platform_app) OVERRIDE {}
135  virtual void OnDownloadProgress(const std::string& extension_id,
136                                  int percent_downloaded) OVERRIDE {}
137  virtual void OnInstallFailure(const std::string& extension_id) OVERRIDE {}
138  virtual void OnAppsReordered() OVERRIDE {}
139  virtual void OnAppInstalledToAppList(
140      const std::string& extension_id) OVERRIDE {}
141  virtual void OnShutdown() OVERRIDE {}
142
143  // For unit tests only.
144  // TODO(felt) In the future, when we'll have multiple policies, it might
145  // be needed to rename the argument.
146  void SetArgumentLoggingForTesting(bool log_arguments);
147  static void RecomputeLoggingIsEnabled(bool profile_enabled);
148
149  // BrowserContextKeyedService
150  virtual void Shutdown() OVERRIDE;
151
152  // At the moment, ActivityLog will use only one policy for summarization
153  // (POLICY_NOARGS by default).  This static member function can be used
154  // to change the default type, but has to be called before the first
155  // GetInstance call.
156  // TODO(dbabic,felt) ActivityLog should support multiple policies at the
157  // same time, so this will need to be changed later.
158  void SetDefaultPolicy(ActivityLogPolicy::PolicyType policy_type);
159
160 private:
161  friend class ActivityLogFactory;
162
163  explicit ActivityLog(Profile* profile);
164  virtual ~ActivityLog();
165
166  // We log callbacks and API calls very similarly, so we handle them the same
167  // way internally.
168  void LogAPIActionInternal(
169      const std::string& extension_id,
170      const std::string& api_call,
171      ListValue* args,
172      const std::string& extra,
173      const APIAction::Type type);
174
175  // TabHelper::ScriptExecutionObserver implementation.
176  // Fires when a ContentScript is executed.
177  virtual void OnScriptsExecuted(
178      const content::WebContents* web_contents,
179      const ExecutingScriptsMap& extension_ids,
180      int32 page_id,
181      const GURL& on_url) OVERRIDE;
182
183  typedef ObserverListThreadSafe<Observer> ObserverList;
184  scoped_refptr<ObserverList> observers_;
185
186  // The policy object takes care of data summarization, compression, and
187  // logging
188  extensions::ActivityLogPolicy* policy_;
189
190  // TODO(dbabic,felt) change this into a list of policy types later.
191  ActivityLogPolicy::PolicyType policy_type_;
192
193  Profile* profile_;
194  // TODO(felt) These two flags could use a comment.
195  bool enabled_;
196  bool first_time_checking_;
197  // testing_mode_ controls whether to log API call arguments. By default, we
198  // don't log most arguments to avoid saving too much data. In testing mode,
199  // argument collection is enabled. We also whitelist some arguments for
200  // collection regardless of whether this bool is true.
201  // When testing_mode_ is enabled, we also print to the console.
202  bool testing_mode_;
203  // We need the DB, FILE, and IO threads to operate. In some cases (tests),
204  // these threads might not exist, so we avoid dispatching anything to the
205  // ActivityDatabase to prevent things from exploding.
206  bool has_threads_;
207
208  InstallTracker* tracker_;
209
210  DISALLOW_COPY_AND_ASSIGN(ActivityLog);
211};
212
213// Each profile has different extensions, so we keep a different database for
214// each profile.
215class ActivityLogFactory : public BrowserContextKeyedServiceFactory {
216 public:
217  static ActivityLog* GetForProfile(Profile* profile) {
218    return static_cast<ActivityLog*>(
219        GetInstance()->GetServiceForBrowserContext(profile, 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