Rename desktop_cursor_loader_updater_aurax11.
[chromium-blink-merge.git] / chrome / browser / extensions / activity_log / activity_actions.cc
blob0e7bc523d2a71768ec6937662dceb7c78244ba5c
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.
5 #include "chrome/browser/extensions/activity_log/activity_actions.h"
7 #include <string>
9 #include "base/command_line.h"
10 #include "base/json/json_string_value_serializer.h"
11 #include "base/logging.h"
12 #include "base/memory/singleton.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "chrome/browser/extensions/activity_log/activity_action_constants.h"
17 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/extensions/dom_action_types.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/web_contents.h"
23 #include "sql/statement.h"
25 namespace constants = activity_log_constants;
27 namespace {
29 std::string Serialize(const base::Value* value) {
30 std::string value_as_text;
31 if (!value) {
32 value_as_text = "null";
33 } else {
34 JSONStringValueSerializer serializer(&value_as_text);
35 serializer.SerializeAndOmitBinaryValues(*value);
37 return value_as_text;
40 } // namespace
42 namespace extensions {
44 using api::activity_log_private::ExtensionActivity;
46 Action::Action(const std::string& extension_id,
47 const base::Time& time,
48 const ActionType action_type,
49 const std::string& api_name)
50 : extension_id_(extension_id),
51 time_(time),
52 action_type_(action_type),
53 api_name_(api_name),
54 page_incognito_(false),
55 arg_incognito_(false),
56 count_(0) {}
58 Action::~Action() {}
60 // TODO(mvrable): As an optimization, we might return this directly if the
61 // refcount is one. However, there are likely to be other stray references in
62 // many cases that will prevent this optimization.
63 scoped_refptr<Action> Action::Clone() const {
64 scoped_refptr<Action> clone(
65 new Action(extension_id(), time(), action_type(), api_name()));
66 if (args())
67 clone->set_args(make_scoped_ptr(args()->DeepCopy()));
68 clone->set_page_url(page_url());
69 clone->set_page_title(page_title());
70 clone->set_page_incognito(page_incognito());
71 clone->set_arg_url(arg_url());
72 clone->set_arg_incognito(arg_incognito());
73 if (other())
74 clone->set_other(make_scoped_ptr(other()->DeepCopy()));
75 return clone;
78 void Action::set_args(scoped_ptr<ListValue> args) {
79 args_.reset(args.release());
82 ListValue* Action::mutable_args() {
83 if (!args_.get()) {
84 args_.reset(new ListValue());
86 return args_.get();
89 void Action::set_page_url(const GURL& page_url) {
90 page_url_ = page_url;
93 void Action::set_arg_url(const GURL& arg_url) {
94 arg_url_ = arg_url;
97 void Action::set_other(scoped_ptr<DictionaryValue> other) {
98 other_.reset(other.release());
101 DictionaryValue* Action::mutable_other() {
102 if (!other_.get()) {
103 other_.reset(new DictionaryValue());
105 return other_.get();
108 std::string Action::SerializePageUrl() const {
109 return (page_incognito() ? constants::kIncognitoUrl : "") + page_url().spec();
112 void Action::ParsePageUrl(const std::string& url) {
113 set_page_incognito(StartsWithASCII(url, constants::kIncognitoUrl, true));
114 if (page_incognito())
115 set_page_url(GURL(url.substr(strlen(constants::kIncognitoUrl))));
116 else
117 set_page_url(GURL(url));
120 std::string Action::SerializeArgUrl() const {
121 return (arg_incognito() ? constants::kIncognitoUrl : "") + arg_url().spec();
124 void Action::ParseArgUrl(const std::string& url) {
125 set_arg_incognito(StartsWithASCII(url, constants::kIncognitoUrl, true));
126 if (arg_incognito())
127 set_arg_url(GURL(url.substr(strlen(constants::kIncognitoUrl))));
128 else
129 set_arg_url(GURL(url));
132 scoped_ptr<ExtensionActivity> Action::ConvertToExtensionActivity() {
133 scoped_ptr<ExtensionActivity> result(new ExtensionActivity);
135 // We do this translation instead of using the same enum because the database
136 // values need to be stable; this allows us to change the extension API
137 // without affecting the database.
138 switch (action_type()) {
139 case ACTION_API_CALL:
140 result->activity_type = ExtensionActivity::ACTIVITY_TYPE_API_CALL;
141 break;
142 case ACTION_API_EVENT:
143 result->activity_type = ExtensionActivity::ACTIVITY_TYPE_API_EVENT;
144 break;
145 case ACTION_CONTENT_SCRIPT:
146 result->activity_type = ExtensionActivity::ACTIVITY_TYPE_CONTENT_SCRIPT;
147 break;
148 case ACTION_DOM_ACCESS:
149 result->activity_type = ExtensionActivity::ACTIVITY_TYPE_DOM_ACCESS;
150 break;
151 case ACTION_DOM_EVENT:
152 result->activity_type = ExtensionActivity::ACTIVITY_TYPE_DOM_EVENT;
153 break;
154 case ACTION_WEB_REQUEST:
155 result->activity_type = ExtensionActivity::ACTIVITY_TYPE_WEB_REQUEST;
156 break;
157 case UNUSED_ACTION_API_BLOCKED:
158 case ACTION_ANY:
159 default:
160 // This shouldn't be reached, but some people might have old or otherwise
161 // weird db entries. Treat it like an API call if that happens.
162 result->activity_type = ExtensionActivity::ACTIVITY_TYPE_API_CALL;
163 break;
166 result->extension_id.reset(new std::string(extension_id()));
167 result->time.reset(new double(time().ToJsTime()));
168 result->count.reset(new double(count()));
169 result->api_call.reset(new std::string(api_name()));
170 result->args.reset(new std::string(Serialize(args())));
171 if (page_url().is_valid()) {
172 if (!page_title().empty())
173 result->page_title.reset(new std::string(page_title()));
174 result->page_url.reset(new std::string(SerializePageUrl()));
176 if (arg_url().is_valid())
177 result->arg_url.reset(new std::string(SerializeArgUrl()));
179 if (other()) {
180 scoped_ptr<ExtensionActivity::Other> other_field(
181 new ExtensionActivity::Other);
182 bool prerender;
183 if (other()->GetBooleanWithoutPathExpansion(constants::kActionPrerender,
184 &prerender)) {
185 other_field->prerender.reset(new bool(prerender));
187 const DictionaryValue* web_request;
188 if (other()->GetDictionaryWithoutPathExpansion(constants::kActionWebRequest,
189 &web_request)) {
190 other_field->web_request.reset(new std::string(
191 ActivityLogPolicy::Util::Serialize(web_request)));
193 std::string extra;
194 if (other()->GetStringWithoutPathExpansion(constants::kActionExtra, &extra))
195 other_field->extra.reset(new std::string(extra));
196 int dom_verb;
197 if (other()->GetIntegerWithoutPathExpansion(constants::kActionDomVerb,
198 &dom_verb)) {
199 switch (static_cast<DomActionType::Type>(dom_verb)) {
200 case DomActionType::GETTER:
201 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_GETTER;
202 break;
203 case DomActionType::SETTER:
204 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_SETTER;
205 break;
206 case DomActionType::METHOD:
207 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_METHOD;
208 break;
209 case DomActionType::INSERTED:
210 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_INSERTED;
211 break;
212 case DomActionType::XHR:
213 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_XHR;
214 break;
215 case DomActionType::WEBREQUEST:
216 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_WEBREQUEST;
217 break;
218 case DomActionType::MODIFIED:
219 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_MODIFIED;
220 break;
221 default:
222 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_NONE;
224 } else {
225 other_field->dom_verb = ExtensionActivity::Other::DOM_VERB_NONE;
227 result->other.reset(other_field.release());
230 return result.Pass();
233 std::string Action::PrintForDebug() const {
234 std::string result = "ID=" + extension_id() + " CATEGORY=";
235 switch (action_type_) {
236 case ACTION_API_CALL:
237 result += "api_call";
238 break;
239 case ACTION_API_EVENT:
240 result += "api_event_callback";
241 break;
242 case ACTION_WEB_REQUEST:
243 result += "webrequest";
244 break;
245 case ACTION_CONTENT_SCRIPT:
246 result += "content_script";
247 break;
248 case UNUSED_ACTION_API_BLOCKED:
249 // This is deprecated.
250 result += "api_blocked";
251 break;
252 case ACTION_DOM_EVENT:
253 result += "dom_event";
254 break;
255 case ACTION_DOM_ACCESS:
256 result += "dom_access";
257 break;
258 default:
259 result += base::StringPrintf("type%d", static_cast<int>(action_type_));
262 result += " API=" + api_name_;
263 if (args_.get()) {
264 result += " ARGS=" + Serialize(args_.get());
266 if (page_url_.is_valid()) {
267 if (page_incognito_)
268 result += " PAGE_URL=(incognito)" + page_url_.spec();
269 else
270 result += " PAGE_URL=" + page_url_.spec();
272 if (!page_title_.empty()) {
273 StringValue title(page_title_);
274 result += " PAGE_TITLE=" + Serialize(&title);
276 if (arg_url_.is_valid()) {
277 if (arg_incognito_)
278 result += " ARG_URL=(incognito)" + arg_url_.spec();
279 else
280 result += " ARG_URL=" + arg_url_.spec();
282 if (other_.get()) {
283 result += " OTHER=" + Serialize(other_.get());
286 result += base::StringPrintf(" COUNT=%d", count_);
287 return result;
290 bool ActionComparator::operator()(
291 const scoped_refptr<Action>& lhs,
292 const scoped_refptr<Action>& rhs) const {
293 if (lhs->time() != rhs->time())
294 return lhs->time() < rhs->time();
295 else
296 return ActionComparatorExcludingTime()(lhs, rhs);
299 bool ActionComparatorExcludingTime::operator()(
300 const scoped_refptr<Action>& lhs,
301 const scoped_refptr<Action>& rhs) const {
302 if (lhs->extension_id() != rhs->extension_id())
303 return lhs->extension_id() < rhs->extension_id();
304 if (lhs->action_type() != rhs->action_type())
305 return lhs->action_type() < rhs->action_type();
306 if (lhs->api_name() != rhs->api_name())
307 return lhs->api_name() < rhs->api_name();
309 // args might be null; treat a null value as less than all non-null values,
310 // including the empty string.
311 if (!lhs->args() && rhs->args())
312 return true;
313 if (lhs->args() && !rhs->args())
314 return false;
315 if (lhs->args() && rhs->args()) {
316 std::string lhs_args = ActivityLogPolicy::Util::Serialize(lhs->args());
317 std::string rhs_args = ActivityLogPolicy::Util::Serialize(rhs->args());
318 if (lhs_args != rhs_args)
319 return lhs_args < rhs_args;
322 // Compare URLs as strings, and treat the incognito flag as a separate field.
323 if (lhs->page_url().spec() != rhs->page_url().spec())
324 return lhs->page_url().spec() < rhs->page_url().spec();
325 if (lhs->page_incognito() != rhs->page_incognito())
326 return lhs->page_incognito() < rhs->page_incognito();
328 if (lhs->page_title() != rhs->page_title())
329 return lhs->page_title() < rhs->page_title();
331 if (lhs->arg_url().spec() != rhs->arg_url().spec())
332 return lhs->arg_url().spec() < rhs->arg_url().spec();
333 if (lhs->arg_incognito() != rhs->arg_incognito())
334 return lhs->arg_incognito() < rhs->arg_incognito();
336 // other is treated much like the args field.
337 if (!lhs->other() && rhs->other())
338 return true;
339 if (lhs->other() && !rhs->other())
340 return false;
341 if (lhs->other() && rhs->other()) {
342 std::string lhs_other = ActivityLogPolicy::Util::Serialize(lhs->other());
343 std::string rhs_other = ActivityLogPolicy::Util::Serialize(rhs->other());
344 if (lhs_other != rhs_other)
345 return lhs_other < rhs_other;
348 // All fields compare as equal if this point is reached.
349 return false;
352 } // namespace extensions