1// Copyright (c) 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_ACTIONS_H_
6#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_ACTIONS_H_
7
8#include <string>
9#include <vector>
10
11#include "base/memory/ref_counted_memory.h"
12#include "base/time/time.h"
13#include "chrome/browser/profiles/profile.h"
14#include "chrome/common/extensions/api/activity_log_private.h"
15#include "sql/connection.h"
16#include "sql/statement.h"
17#include "sql/transaction.h"
18#include "url/gurl.h"
19
20namespace base {
21class ListValue;
22class DictionaryValue;
23}
24
25namespace rappor {
26class RapporService;
27}
28
29namespace extensions {
30
31// This is the interface for extension actions that are to be recorded in
32// the activity log.
33class Action : public base::RefCountedThreadSafe<Action> {
34 public:
35  // Types of log entries that can be stored.  The numeric values are stored in
36  // the database, so keep them stable.  Append values only.
37  enum ActionType {
38    ACTION_API_CALL = 0,
39    ACTION_API_EVENT = 1,
40    UNUSED_ACTION_API_BLOCKED = 2,  // Not in use, but reserved for future.
41    ACTION_CONTENT_SCRIPT = 3,
42    ACTION_DOM_ACCESS = 4,
43    ACTION_DOM_EVENT = 5,
44    ACTION_WEB_REQUEST = 6,
45    ACTION_ANY = 1001,              // Used for lookups of unspecified type.
46  };
47
48  // The type of ad injection an action performed. Do not delete or reorder
49  // these metrics, as they are used in histogramming.
50  enum InjectionType {
51    // No ad injection occurred.
52    NO_AD_INJECTION = 0,
53    // A new ad was injected.
54    INJECTION_NEW_AD,
55    // An ad was removed.
56    INJECTION_REMOVED_AD,
57    // An ad was replaced.
58    INJECTION_REPLACED_AD,
59    // Something occurred which heuristically looks like an ad injection, but we
60    // didn't categorize it as such (likely because we didn't recognize it as
61    // an ad network). If our list is effective, this should be significantly
62    // lower than the non-LIKELY counterparts.
63    INJECTION_LIKELY_NEW_AD,
64    INJECTION_LIKELY_REPLACED_AD,
65
66    // Place any new injection types above this entry.
67    NUM_INJECTION_TYPES
68  };
69
70  // The type of ad which was injected.
71  enum AdType {
72    AD_TYPE_NONE,
73    AD_TYPE_IFRAME,
74    AD_TYPE_EMBED,
75    AD_TYPE_ANCHOR,
76
77    // Place any new injection types above this entry.
78    NUM_AD_TYPES
79  };
80
81  // A useful shorthand for methods that take or return collections of Action
82  // objects.
83  typedef std::vector<scoped_refptr<Action> > ActionVector;
84
85  // Creates a new activity log Action object.  The extension_id and type
86  // fields are immutable.  All other fields can be filled in with the
87  // accessors/mutators below.
88  Action(const std::string& extension_id,
89         const base::Time& time,
90         const ActionType action_type,
91         const std::string& api_name,
92         int64 action_id = -1);
93
94  // Creates and returns a mutable copy of an Action.
95  scoped_refptr<Action> Clone() const;
96
97  // Return the type of ad-injection performed in the |action|, or
98  // NO_AD_INJECTION if none was present.
99  // TODO(rdevlin.cronin): This isn't done.
100  // See crbug.com/357204.
101  InjectionType DidInjectAd(rappor::RapporService* rappor_service) const;
102
103  // The extension which caused this record to be generated.
104  const std::string& extension_id() const { return extension_id_; }
105
106  // The time the record was generated (or some approximation).
107  const base::Time& time() const { return time_; }
108  void set_time(const base::Time& time) { time_ = time; }
109
110  // The ActionType distinguishes different classes of actions that can be
111  // logged, and determines which other fields are expected to be filled in.
112  ActionType action_type() const { return action_type_; }
113
114  // The specific API call used or accessed, for example "chrome.tabs.get".
115  const std::string& api_name() const { return api_name_; }
116  void set_api_name(const std::string api_name) { api_name_ = api_name; }
117
118  // Any applicable arguments.  This might be null to indicate no data
119  // available (a distinct condition from an empty argument list).
120  // mutable_args() returns a pointer to the list stored in the Action which
121  // can be modified in place; if the list was null an empty list is created
122  // first.
123  const base::ListValue* args() const { return args_.get(); }
124  void set_args(scoped_ptr<base::ListValue> args);
125  base::ListValue* mutable_args();
126
127  // The URL of the page which was modified or accessed.
128  const GURL& page_url() const { return page_url_; }
129  void set_page_url(const GURL& page_url);
130
131  // The title of the above page if available.
132  const std::string& page_title() const { return page_title_; }
133  void set_page_title(const std::string& title) { page_title_ = title; }
134
135  // A URL which appears in the arguments of the API call, if present.
136  const GURL& arg_url() const { return arg_url_; }
137  void set_arg_url(const GURL& arg_url);
138
139  // Get or set a flag indicating whether the page or argument values above
140  // refer to incognito pages.
141  bool page_incognito() const { return page_incognito_; }
142  void set_page_incognito(bool incognito) { page_incognito_ = incognito; }
143  bool arg_incognito() const { return arg_incognito_; }
144  void set_arg_incognito(bool incognito) { arg_incognito_ = incognito; }
145
146  // A dictionary where any additional data can be stored.
147  const base::DictionaryValue* other() const { return other_.get(); }
148  void set_other(scoped_ptr<base::DictionaryValue> other);
149  base::DictionaryValue* mutable_other();
150
151  // An ID that identifies an action stored in the Activity Log database. If the
152  // action is not retrieved from the database, e.g., live stream, then the ID
153  // is set to -1.
154  int64 action_id() const { return action_id_; }
155
156  // Helper methods for serializing and deserializing URLs into strings.  If
157  // the URL is marked as incognito, then the string is prefixed with
158  // kIncognitoUrl ("<incognito>").
159  std::string SerializePageUrl() const;
160  void ParsePageUrl(const std::string& url);
161  std::string SerializeArgUrl() const;
162  void ParseArgUrl(const std::string& url);
163
164  // Number of merged records for this action.
165  int count() const { return count_; }
166  void set_count(int count) { count_ = count; }
167
168  // Flatten the activity's type-specific fields into an ExtensionActivity.
169  scoped_ptr<api::activity_log_private::ExtensionActivity>
170      ConvertToExtensionActivity();
171
172  // Print an action as a regular string for debugging purposes.
173  virtual std::string PrintForDebug() const;
174
175 protected:
176  virtual ~Action();
177
178 private:
179  friend class base::RefCountedThreadSafe<Action>;
180
181  // Returns true if a given |url| could be an ad.
182  bool UrlCouldBeAd(const GURL& url) const;
183
184  // Uploads the URL to RAPPOR (preserving privacy) if this might have been an
185  // ad injection.
186  void MaybeUploadUrl(rappor::RapporService* rappor_service) const;
187
188  // Checks an action that modified the src of an element for ad injection.
189  InjectionType CheckSrcModification() const;
190  // Checks an action with the appendChild API for ad injection.
191  // |ad_type_out| is populated with the type of ad which was injected, if there
192  // was an injection.
193  InjectionType CheckAppendChild(AdType* ad_type_out) const;
194  // Checks a DOM object (e.g. an appended child) for ad injection.
195  // |ad_type_out| is populated with the type of ad which was injected, if there
196  // was an injection.
197  InjectionType CheckDomObject(const base::DictionaryValue* object,
198                               AdType* ad_type_out) const;
199
200  std::string extension_id_;
201  base::Time time_;
202  ActionType action_type_;
203  std::string api_name_;
204  scoped_ptr<base::ListValue> args_;
205  GURL page_url_;
206  std::string page_title_;
207  bool page_incognito_;
208  GURL arg_url_;
209  bool arg_incognito_;
210  scoped_ptr<base::DictionaryValue> other_;
211  int count_;
212  int64 action_id_;
213
214  DISALLOW_COPY_AND_ASSIGN(Action);
215};
216
217// A comparator for Action class objects; this performs a lexicographic
218// comparison of the fields of the Action object (in an unspecfied order).
219// This can be used to use Action objects as keys in STL containers.
220struct ActionComparator {
221  // Evaluates the comparison lhs < rhs.
222  bool operator()(const scoped_refptr<Action>& lhs,
223                  const scoped_refptr<Action>& rhs) const;
224};
225
226// Like ActionComparator, but ignores the time field and the action ID field in
227// comparisons.
228struct ActionComparatorExcludingTimeAndActionId {
229  // Evaluates the comparison lhs < rhs.
230  bool operator()(const scoped_refptr<Action>& lhs,
231                  const scoped_refptr<Action>& rhs) const;
232};
233
234}  // namespace extensions
235
236#endif  // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_ACTIONS_H_
237