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