OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/dom_automation_controller.h" | 5 #include "content/renderer/dom_automation_controller.h" |
6 | 6 |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/json/json_string_value_serializer.h" | 7 #include "base/json/json_string_value_serializer.h" |
10 #include "base/metrics/histogram.h" | |
11 #include "base/metrics/statistics_recorder.h" | |
12 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
13 #include "content/common/child_process_messages.h" | 9 #include "content/common/child_process_messages.h" |
14 #include "content/common/view_messages.h" | 10 #include "content/common/view_messages.h" |
15 | 11 #include "content/renderer/render_view_impl.h" |
16 using webkit_glue::CppArgumentList; | 12 #include "content/renderer/v8_value_converter_impl.h" |
17 using webkit_glue::CppVariant; | 13 #include "gin/handle.h" |
| 14 #include "gin/object_template_builder.h" |
| 15 #include "third_party/WebKit/public/web/WebFrame.h" |
| 16 #include "third_party/WebKit/public/web/WebKit.h" |
18 | 17 |
19 namespace content { | 18 namespace content { |
20 | 19 |
21 DomAutomationController::DomAutomationController() | 20 gin::WrapperInfo DomAutomationController::kWrapperInfo = { |
22 : sender_(NULL), | 21 gin::kEmbedderNativeGin}; |
23 routing_id_(MSG_ROUTING_NONE), | 22 |
24 automation_id_(MSG_ROUTING_NONE) { | 23 // static |
25 BindCallback("send", base::Bind(&DomAutomationController::Send, | 24 void DomAutomationController::Install(blink::WebFrame* frame) { |
26 base::Unretained(this))); | 25 v8::Isolate* isolate = blink::mainThreadIsolate(); |
27 BindCallback("setAutomationId", | 26 v8::HandleScope handle_scope(isolate); |
28 base::Bind(&DomAutomationController::SetAutomationId, | 27 v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); |
29 base::Unretained(this))); | 28 if (context.IsEmpty()) |
30 BindCallback("sendJSON", base::Bind(&DomAutomationController::SendJSON, | 29 return; |
31 base::Unretained(this))); | 30 |
32 BindCallback("sendWithId", base::Bind(&DomAutomationController::SendWithId, | 31 v8::Context::Scope context_scope(context); |
33 base::Unretained(this))); | 32 |
| 33 gin::Handle<DomAutomationController> controller = |
| 34 gin::CreateHandle(isolate, new DomAutomationController(frame)); |
| 35 v8::Handle<v8::Object> global = context->Global(); |
| 36 global->Set(gin::StringToV8(isolate, "domAutomationController"), |
| 37 controller.ToV8()); |
34 } | 38 } |
35 | 39 |
36 void DomAutomationController::Send(const CppArgumentList& args, | 40 DomAutomationController::DomAutomationController(blink::WebFrame* frame) |
37 CppVariant* result) { | 41 : frame_(frame), automation_id_(MSG_ROUTING_NONE) {} |
38 if (args.size() != 1) { | |
39 result->SetNull(); | |
40 return; | |
41 } | |
42 | 42 |
43 if (automation_id_ == MSG_ROUTING_NONE) { | 43 DomAutomationController::~DomAutomationController() {} |
44 result->SetNull(); | |
45 return; | |
46 } | |
47 | 44 |
48 if (!sender_) { | 45 gin::ObjectTemplateBuilder DomAutomationController::GetObjectTemplateBuilder( |
49 NOTREACHED(); | 46 v8::Isolate* isolate) { |
50 result->SetNull(); | 47 return gin::Wrappable<DomAutomationController>::GetObjectTemplateBuilder( |
51 return; | 48 isolate) |
52 } | 49 .SetMethod("send", &DomAutomationController::Send) |
| 50 .SetMethod("setAutomationId", &DomAutomationController::SetAutomationId) |
| 51 .SetMethod("sendJSON", &DomAutomationController::SendJSON) |
| 52 .SetMethod("sendWithId", &DomAutomationController::SendWithId); |
| 53 } |
| 54 |
| 55 bool DomAutomationController::Send(const gin::Arguments& args) { |
| 56 if (automation_id_ == MSG_ROUTING_NONE) |
| 57 return false; |
53 | 58 |
54 std::string json; | 59 std::string json; |
55 JSONStringValueSerializer serializer(&json); | 60 JSONStringValueSerializer serializer(&json); |
56 scoped_ptr<base::Value> value; | 61 scoped_ptr<base::Value> value; |
57 | 62 |
58 // Warning: note that JSON officially requires the root-level object to be | 63 // Warning: note that JSON officially requires the root-level object to be |
59 // an object (e.g. {foo:3}) or an array, while here we're serializing | 64 // an object (e.g. {foo:3}) or an array, while here we're serializing |
60 // strings, bools, etc. to "JSON". This only works because (a) the JSON | 65 // strings, bools, etc. to "JSON". This only works because (a) the JSON |
61 // writer is lenient, and (b) on the receiving side we wrap the JSON string | 66 // writer is lenient, and (b) on the receiving side we wrap the JSON string |
62 // in square brackets, converting it to an array, then parsing it and | 67 // in square brackets, converting it to an array, then parsing it and |
63 // grabbing the 0th element to get the value out. | 68 // grabbing the 0th element to get the value out. |
64 switch (args[0].type) { | 69 if (args.PeekNext()->IsString() || args.PeekNext()->IsBoolean() || |
65 case NPVariantType_String: { | 70 args.PeekNext()->IsNumber()) { |
66 value.reset(new base::StringValue(args[0].ToString())); | 71 V8ValueConverterImpl conv; |
67 break; | 72 value.reset( |
68 } | 73 conv.FromV8Value(args.PeekNext(), args.isolate()->GetCurrentContext())); |
69 case NPVariantType_Bool: { | 74 } else { |
70 value.reset(new base::FundamentalValue(args[0].ToBoolean())); | 75 return false; |
71 break; | |
72 } | |
73 case NPVariantType_Int32: { | |
74 value.reset(new base::FundamentalValue(args[0].ToInt32())); | |
75 break; | |
76 } | |
77 case NPVariantType_Double: { | |
78 // The value that is sent back is an integer while it is treated | |
79 // as a double in this binding. The reason being that KJS treats | |
80 // any number value as a double. Refer for more details, | |
81 // chrome/third_party/webkit/src/JavaScriptCore/bindings/c/c_utility.cpp | |
82 value.reset(new base::FundamentalValue(args[0].ToInt32())); | |
83 break; | |
84 } | |
85 default: { | |
86 result->SetNull(); | |
87 return; | |
88 } | |
89 } | 76 } |
90 | 77 |
91 if (!serializer.Serialize(*value)) { | 78 if (!serializer.Serialize(*value)) |
92 result->SetNull(); | 79 return false; |
93 return; | |
94 } | |
95 | 80 |
96 bool succeeded = sender_->Send( | 81 RenderViewImpl* render_view = RenderViewImpl::FromWebView(frame_->view()); |
97 new ViewHostMsg_DomOperationResponse(routing_id_, json, automation_id_)); | 82 bool succeeded = render_view->Send(new ViewHostMsg_DomOperationResponse( |
98 result->Set(succeeded); | 83 render_view->GetRoutingID(), json, automation_id_)); |
99 | 84 |
100 automation_id_ = MSG_ROUTING_NONE; | 85 automation_id_ = MSG_ROUTING_NONE; |
| 86 return succeeded; |
101 } | 87 } |
102 | 88 |
103 void DomAutomationController::SendJSON(const CppArgumentList& args, | 89 bool DomAutomationController::SendJSON(const std::string& json) { |
104 CppVariant* result) { | 90 if (automation_id_ == MSG_ROUTING_NONE) |
105 if (args.size() != 1) { | 91 return false; |
106 result->SetNull(); | 92 RenderViewImpl* render_view = RenderViewImpl::FromWebView(frame_->view()); |
107 return; | 93 bool result = render_view->Send(new ViewHostMsg_DomOperationResponse( |
108 } | 94 render_view->GetRoutingID(), json, automation_id_)); |
109 | |
110 if (automation_id_ == MSG_ROUTING_NONE) { | |
111 result->SetNull(); | |
112 return; | |
113 } | |
114 | |
115 if (!sender_) { | |
116 NOTREACHED(); | |
117 result->SetNull(); | |
118 return; | |
119 } | |
120 | |
121 if (args[0].type != NPVariantType_String) { | |
122 result->SetNull(); | |
123 return; | |
124 } | |
125 | |
126 std::string json = args[0].ToString(); | |
127 result->Set(sender_->Send( | |
128 new ViewHostMsg_DomOperationResponse(routing_id_, json, automation_id_))); | |
129 | 95 |
130 automation_id_ = MSG_ROUTING_NONE; | 96 automation_id_ = MSG_ROUTING_NONE; |
| 97 return result; |
131 } | 98 } |
132 | 99 |
133 void DomAutomationController::SendWithId(const CppArgumentList& args, | 100 bool DomAutomationController::SendWithId(int automation_id, |
134 CppVariant* result) { | 101 const std::string& str) { |
135 if (args.size() != 2) { | 102 RenderViewImpl* render_view = RenderViewImpl::FromWebView(frame_->view()); |
136 result->SetNull(); | 103 return render_view->Send(new ViewHostMsg_DomOperationResponse( |
137 return; | 104 render_view->GetRoutingID(), str, automation_id)); |
138 } | |
139 | |
140 if (!sender_) { | |
141 NOTREACHED(); | |
142 result->SetNull(); | |
143 return; | |
144 } | |
145 | |
146 if (!args[0].isNumber() || args[1].type != NPVariantType_String) { | |
147 result->SetNull(); | |
148 return; | |
149 } | |
150 | |
151 result->Set(sender_->Send( | |
152 new ViewHostMsg_DomOperationResponse(routing_id_, args[1].ToString(), | |
153 args[0].ToInt32()))); | |
154 } | 105 } |
155 | 106 |
156 void DomAutomationController::SetAutomationId( | 107 bool DomAutomationController::SetAutomationId(int automation_id) { |
157 const CppArgumentList& args, CppVariant* result) { | 108 automation_id_ = automation_id; |
158 if (args.size() != 1) { | 109 return true; |
159 result->SetNull(); | |
160 return; | |
161 } | |
162 | |
163 // The check here is for NumberType and not Int32 as | |
164 // KJS::JSType only defines a NumberType (no Int32) | |
165 if (!args[0].isNumber()) { | |
166 result->SetNull(); | |
167 return; | |
168 } | |
169 | |
170 automation_id_ = args[0].ToInt32(); | |
171 result->Set(true); | |
172 } | 110 } |
173 | 111 |
174 } // namespace content | 112 } // namespace content |
OLD | NEW |