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 "gin/handle.h" |
17 using webkit_glue::CppVariant; | 13 #include "gin/object_template_builder.h" |
14 #include "third_party/WebKit/public/web/WebFrame.h" | |
15 #include "third_party/WebKit/public/web/WebKit.h" | |
18 | 16 |
19 namespace content { | 17 namespace content { |
20 | 18 |
21 DomAutomationController::DomAutomationController() | 19 gin::WrapperInfo DomAutomationController::kWrapperInfo = { |
22 : sender_(NULL), | 20 gin::kEmbedderNativeGin}; |
23 routing_id_(MSG_ROUTING_NONE), | 21 |
24 automation_id_(MSG_ROUTING_NONE) { | 22 DomAutomationController::DomAutomationController(RenderViewImpl* render_view) |
25 BindCallback("send", base::Bind(&DomAutomationController::Send, | 23 : render_view_(render_view), automation_id_(MSG_ROUTING_NONE) {} |
26 base::Unretained(this))); | 24 |
27 BindCallback("setAutomationId", | 25 void DomAutomationController::Install(blink::WebFrame* frame) { |
28 base::Bind(&DomAutomationController::SetAutomationId, | 26 v8::Isolate* isolate = blink::mainThreadIsolate(); |
29 base::Unretained(this))); | 27 v8::HandleScope handle_scope(isolate); |
30 BindCallback("sendJSON", base::Bind(&DomAutomationController::SendJSON, | 28 v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); |
31 base::Unretained(this))); | 29 if (context.IsEmpty()) |
32 BindCallback("sendWithId", base::Bind(&DomAutomationController::SendWithId, | 30 return; |
33 base::Unretained(this))); | 31 |
32 v8::Context::Scope context_scope(context); | |
33 | |
34 gin::Handle<DomAutomationController> controller = | |
35 gin::CreateHandle(isolate, this); | |
36 v8::Handle<v8::Object> global = context->Global(); | |
37 global->Set(gin::StringToV8(isolate, "domAutomationController"), | |
38 controller.ToV8()); | |
34 } | 39 } |
35 | 40 |
36 void DomAutomationController::Send(const CppArgumentList& args, | 41 DomAutomationController::~DomAutomationController() {} |
37 CppVariant* result) { | |
38 if (args.size() != 1) { | |
39 result->SetNull(); | |
40 return; | |
41 } | |
42 | 42 |
43 if (automation_id_ == MSG_ROUTING_NONE) { | 43 gin::ObjectTemplateBuilder DomAutomationController::GetObjectTemplateBuilder( |
44 result->SetNull(); | 44 v8::Isolate* isolate) { |
45 return; | 45 return gin::Wrappable<DomAutomationController>::GetObjectTemplateBuilder( |
46 } | 46 isolate) |
47 .SetMethod("send", &DomAutomationController::Send) | |
48 .SetMethod("setAutomationId", &DomAutomationController::SetAutomationId) | |
49 .SetMethod("sendJSON", &DomAutomationController::SendJSON) | |
50 .SetMethod("sendWithId", &DomAutomationController::SendWithId); | |
51 } | |
47 | 52 |
48 if (!sender_) { | 53 bool DomAutomationController::Send(gin::Arguments* args) { |
49 NOTREACHED(); | 54 |
50 result->SetNull(); | 55 if (automation_id_ == MSG_ROUTING_NONE) |
51 return; | 56 return false; |
52 } | |
53 | 57 |
54 std::string json; | 58 std::string json; |
55 JSONStringValueSerializer serializer(&json); | 59 JSONStringValueSerializer serializer(&json); |
56 scoped_ptr<base::Value> value; | 60 scoped_ptr<base::Value> value; |
57 | 61 |
58 // Warning: note that JSON officially requires the root-level object to be | 62 // 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 | 63 // 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 | 64 // 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 | 65 // 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 | 66 // in square brackets, converting it to an array, then parsing it and |
63 // grabbing the 0th element to get the value out. | 67 // grabbing the 0th element to get the value out. |
64 switch (args[0].type) { | 68 if (args->PeekNext()->IsString()) { |
Aaron Boodman
2014/01/09 20:11:06
Weird API is weird. Why just these three JSON type
| |
65 case NPVariantType_String: { | 69 std::string str; |
Aaron Boodman
2014/01/09 20:11:06
You could shorten this a bit by using V8ValueConve
jochen (gone - plz use gerrit)
2014/01/09 20:30:38
The problem is that some tests rely on passing a d
Aaron Boodman
2014/01/09 20:41:25
Do you mean they pass a non-integral number, or th
| |
66 value.reset(new base::StringValue(args[0].ToString())); | 70 args->GetNext(&str); |
67 break; | 71 value.reset(new base::StringValue(str)); |
68 } | 72 } else if (args->PeekNext()->IsBoolean()) { |
69 case NPVariantType_Bool: { | 73 bool val; |
70 value.reset(new base::FundamentalValue(args[0].ToBoolean())); | 74 args->GetNext(&val); |
71 break; | 75 value.reset(new base::FundamentalValue(val)); |
72 } | 76 } else if (args->PeekNext()->IsNumber()) { |
73 case NPVariantType_Int32: { | 77 double val; |
74 value.reset(new base::FundamentalValue(args[0].ToInt32())); | 78 args->GetNext(&val); |
75 break; | 79 value.reset(new base::FundamentalValue(static_cast<int>(val))); |
76 } | 80 } else { |
77 case NPVariantType_Double: { | 81 return false; |
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 } | 82 } |
90 | 83 |
91 if (!serializer.Serialize(*value)) { | 84 if (!serializer.Serialize(*value)) |
92 result->SetNull(); | 85 return false; |
93 return; | |
94 } | |
95 | 86 |
96 bool succeeded = sender_->Send( | 87 bool succeeded = render_view_->Send(new ViewHostMsg_DomOperationResponse( |
97 new ViewHostMsg_DomOperationResponse(routing_id_, json, automation_id_)); | 88 render_view_->GetRoutingID(), json, automation_id_)); |
98 result->Set(succeeded); | |
99 | 89 |
100 automation_id_ = MSG_ROUTING_NONE; | 90 automation_id_ = MSG_ROUTING_NONE; |
91 return succeeded; | |
101 } | 92 } |
102 | 93 |
103 void DomAutomationController::SendJSON(const CppArgumentList& args, | 94 bool DomAutomationController::SendJSON(const std::string& json) { |
104 CppVariant* result) { | 95 if (automation_id_ == MSG_ROUTING_NONE) |
105 if (args.size() != 1) { | 96 return false; |
106 result->SetNull(); | 97 bool result = render_view_->Send(new ViewHostMsg_DomOperationResponse( |
107 return; | 98 render_view_->GetRoutingID(), json, automation_id_)); |
108 } | |
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 | 99 |
130 automation_id_ = MSG_ROUTING_NONE; | 100 automation_id_ = MSG_ROUTING_NONE; |
101 return result; | |
131 } | 102 } |
132 | 103 |
133 void DomAutomationController::SendWithId(const CppArgumentList& args, | 104 bool DomAutomationController::SendWithId(int automation_id, |
134 CppVariant* result) { | 105 const std::string& str) { |
135 if (args.size() != 2) { | 106 return render_view_->Send(new ViewHostMsg_DomOperationResponse( |
136 result->SetNull(); | 107 render_view_->GetRoutingID(), str, automation_id)); |
137 return; | |
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 } | 108 } |
155 | 109 |
156 void DomAutomationController::SetAutomationId( | 110 bool DomAutomationController::SetAutomationId(int automation_id) { |
157 const CppArgumentList& args, CppVariant* result) { | 111 automation_id_ = automation_id; |
158 if (args.size() != 1) { | 112 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 } | 113 } |
173 | 114 |
174 } // namespace content | 115 } // namespace content |
OLD | NEW |