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
15 using content::V8ValueConverter;
16 using blink::WebString;
17 using blink::WebURL;
18
19 namespace extensions {
20
21 namespace {
22
23 // Converts the given |v8_value| and appends it to the given |list|, if the
24 // conversion succeeds.
AppendV8Value(const std::string & api_name,const v8::Handle<v8::Value> & v8_value,base::ListValue * list)25 void 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
DOMActivityLogger(const std::string & extension_id)42 DOMActivityLogger::DOMActivityLogger(const std::string& extension_id)
43 : extension_id_(extension_id) {
44 }
45
~DOMActivityLogger()46 DOMActivityLogger::~DOMActivityLogger() {}
47
AttachToWorld(int world_id,const std::string & extension_id)48 void 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
logGetter(const WebString & api_name,const WebURL & url,const WebString & title)63 void 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
logSetter(const WebString & api_name,const v8::Handle<v8::Value> & new_value,const WebURL & url,const WebString & title)73 void 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
logSetter(const WebString & api_name,const v8::Handle<v8::Value> & new_value,const v8::Handle<v8::Value> & old_value,const WebURL & url,const WebString & title)80 void 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
logMethod(const WebString & api_name,int argc,const v8::Handle<v8::Value> * argv,const WebURL & url,const WebString & title)94 void 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
logEvent(const WebString & event_name,int argc,const WebString * argv,const WebURL & url,const WebString & title)107 void 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
SendDomActionMessage(const std::string & api_call,const GURL & url,const base::string16 & url_title,DomActionType::Type call_type,scoped_ptr<base::ListValue> args)120 void 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