1// Copyright 2014 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#include "extensions/renderer/dom_activity_logger.h"
6
7#include "content/public/renderer/render_thread.h"
8#include "content/public/renderer/v8_value_converter.h"
9#include "extensions/common/ad_injection_constants.h"
10#include "extensions/common/dom_action_types.h"
11#include "extensions/common/extension_messages.h"
12#include "extensions/renderer/activity_log_converter_strategy.h"
13#include "third_party/WebKit/public/platform/WebString.h"
14#include "third_party/WebKit/public/platform/WebURL.h"
15
16using content::V8ValueConverter;
17using blink::WebString;
18using blink::WebURL;
19
20namespace extensions {
21
22namespace {
23
24// Converts the given |v8_value| and appends it to the given |list|, if the
25// conversion succeeds.
26void AppendV8Value(const std::string& api_name,
27                   const v8::Handle<v8::Value>& v8_value,
28                   base::ListValue* list) {
29  DCHECK(list);
30  scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
31  ActivityLogConverterStrategy strategy;
32  strategy.set_enable_detailed_parsing(
33      ad_injection_constants::ApiCanInjectAds(api_name));
34  converter->SetFunctionAllowed(true);
35  converter->SetStrategy(&strategy);
36  scoped_ptr<base::Value> value(converter->FromV8Value(
37      v8_value, v8::Isolate::GetCurrent()->GetCurrentContext()));
38
39  if (value.get())
40    list->Append(value.release());
41}
42
43}  // namespace
44
45DOMActivityLogger::DOMActivityLogger(const std::string& extension_id)
46    : extension_id_(extension_id) {
47}
48
49DOMActivityLogger::~DOMActivityLogger() {}
50
51void DOMActivityLogger::AttachToWorld(int world_id,
52                                      const std::string& extension_id) {
53#if defined(ENABLE_EXTENSIONS)
54  // If there is no logger registered for world_id, construct a new logger
55  // and register it with world_id.
56  if (!blink::hasDOMActivityLogger(world_id,
57                                   WebString::fromUTF8(extension_id))) {
58    DOMActivityLogger* logger = new DOMActivityLogger(extension_id);
59    blink::setDOMActivityLogger(world_id,
60                                WebString::fromUTF8(extension_id),
61                                logger);
62  }
63#endif
64}
65
66void DOMActivityLogger::logGetter(const WebString& api_name,
67                                  const WebURL& url,
68                                  const WebString& title) {
69  SendDomActionMessage(api_name.utf8(),
70                       url,
71                       title,
72                       DomActionType::GETTER,
73                       scoped_ptr<base::ListValue>(new base::ListValue()));
74}
75
76void DOMActivityLogger::logSetter(const WebString& api_name,
77                                  const v8::Handle<v8::Value>& new_value,
78                                  const WebURL& url,
79                                  const WebString& title) {
80  logSetter(api_name, new_value, v8::Handle<v8::Value>(), url, title);
81}
82
83void DOMActivityLogger::logSetter(const WebString& api_name,
84                                  const v8::Handle<v8::Value>& new_value,
85                                  const v8::Handle<v8::Value>& old_value,
86                                  const WebURL& url,
87                                  const WebString& title) {
88  scoped_ptr<base::ListValue> args(new base::ListValue);
89  std::string api_name_utf8 = api_name.utf8();
90  AppendV8Value(api_name_utf8, new_value, args.get());
91  if (!old_value.IsEmpty())
92    AppendV8Value(api_name_utf8, old_value, args.get());
93  SendDomActionMessage(
94      api_name_utf8, url, title, DomActionType::SETTER, args.Pass());
95}
96
97void DOMActivityLogger::logMethod(const WebString& api_name,
98                                  int argc,
99                                  const v8::Handle<v8::Value>* argv,
100                                  const WebURL& url,
101                                  const WebString& title) {
102  scoped_ptr<base::ListValue> args(new base::ListValue);
103  std::string api_name_utf8 = api_name.utf8();
104  for (int i = 0; i < argc; ++i)
105    AppendV8Value(api_name_utf8, argv[i], args.get());
106  SendDomActionMessage(
107      api_name_utf8, url, title, DomActionType::METHOD, args.Pass());
108}
109
110void DOMActivityLogger::SendDomActionMessage(const std::string& api_call,
111                                             const GURL& url,
112                                             const base::string16& url_title,
113                                             DomActionType::Type call_type,
114                                             scoped_ptr<base::ListValue> args) {
115  ExtensionHostMsg_DOMAction_Params params;
116  params.api_call = api_call;
117  params.url = url;
118  params.url_title = url_title;
119  params.call_type = call_type;
120  params.arguments.Swap(args.get());
121  content::RenderThread::Get()->Send(
122      new ExtensionHostMsg_AddDOMActionToActivityLog(extension_id_, params));
123}
124
125}  // namespace extensions
126