OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011 Google Inc. All rights reserved. | 2 * Copyright (c) 2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 15 matching lines...) Expand all Loading... |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "core/inspector/MainThreadDebugger.h" | 31 #include "core/inspector/MainThreadDebugger.h" |
32 | 32 |
33 #include "bindings/core/v8/BindingSecurity.h" | 33 #include "bindings/core/v8/BindingSecurity.h" |
34 #include "bindings/core/v8/DOMWrapperWorld.h" | 34 #include "bindings/core/v8/DOMWrapperWorld.h" |
35 #include "bindings/core/v8/ScriptController.h" | 35 #include "bindings/core/v8/ScriptController.h" |
| 36 #include "bindings/core/v8/V8Node.h" |
36 #include "bindings/core/v8/V8Window.h" | 37 #include "bindings/core/v8/V8Window.h" |
| 38 #include "core/dom/ContainerNode.h" |
| 39 #include "core/dom/Document.h" |
| 40 #include "core/dom/Element.h" |
37 #include "core/dom/ExecutionContext.h" | 41 #include "core/dom/ExecutionContext.h" |
| 42 #include "core/dom/StaticNodeList.h" |
38 #include "core/frame/FrameConsole.h" | 43 #include "core/frame/FrameConsole.h" |
39 #include "core/frame/LocalDOMWindow.h" | 44 #include "core/frame/LocalDOMWindow.h" |
40 #include "core/frame/LocalFrame.h" | 45 #include "core/frame/LocalFrame.h" |
41 #include "core/frame/UseCounter.h" | 46 #include "core/frame/UseCounter.h" |
42 #include "core/inspector/IdentifiersFactory.h" | 47 #include "core/inspector/IdentifiersFactory.h" |
43 #include "core/inspector/InspectedFrames.h" | 48 #include "core/inspector/InspectedFrames.h" |
44 #include "core/inspector/InspectorTaskRunner.h" | 49 #include "core/inspector/InspectorTaskRunner.h" |
45 #include "core/timing/MemoryInfo.h" | 50 #include "core/timing/MemoryInfo.h" |
46 #include "core/workers/MainThreadWorkletGlobalScope.h" | 51 #include "core/workers/MainThreadWorkletGlobalScope.h" |
| 52 #include "core/xml/XPathEvaluator.h" |
| 53 #include "core/xml/XPathResult.h" |
47 #include "platform/UserGestureIndicator.h" | 54 #include "platform/UserGestureIndicator.h" |
48 #include "platform/v8_inspector/public/V8Debugger.h" | 55 #include "platform/v8_inspector/public/V8Debugger.h" |
49 #include "public/platform/Platform.h" | 56 #include "public/platform/Platform.h" |
50 #include "wtf/OwnPtr.h" | 57 #include "wtf/OwnPtr.h" |
51 #include "wtf/PassOwnPtr.h" | 58 #include "wtf/PassOwnPtr.h" |
52 #include "wtf/ThreadingPrimitives.h" | 59 #include "wtf/ThreadingPrimitives.h" |
53 | 60 |
54 namespace blink { | 61 namespace blink { |
55 | 62 |
56 namespace { | 63 namespace { |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 } | 234 } |
228 | 235 |
229 v8::MaybeLocal<v8::Value> MainThreadDebugger::memoryInfo(v8::Isolate* isolate, v
8::Local<v8::Context> context, v8::Local<v8::Object> creationContext) | 236 v8::MaybeLocal<v8::Value> MainThreadDebugger::memoryInfo(v8::Isolate* isolate, v
8::Local<v8::Context> context, v8::Local<v8::Object> creationContext) |
230 { | 237 { |
231 ExecutionContext* executionContext = toExecutionContext(context); | 238 ExecutionContext* executionContext = toExecutionContext(context); |
232 ASSERT_UNUSED(executionContext, executionContext); | 239 ASSERT_UNUSED(executionContext, executionContext); |
233 ASSERT(executionContext->isDocument()); | 240 ASSERT(executionContext->isDocument()); |
234 return toV8(MemoryInfo::create(), creationContext, isolate); | 241 return toV8(MemoryInfo::create(), creationContext, isolate); |
235 } | 242 } |
236 | 243 |
| 244 bool MainThreadDebugger::isCommandLineAPIMethod(const String& name) |
| 245 { |
| 246 DEFINE_STATIC_LOCAL(HashSet<String>, methods, ()); |
| 247 if (methods.size() == 0) { |
| 248 const char* members[] = { "$", "$$", "$x" }; |
| 249 for (size_t i = 0; i < WTF_ARRAY_LENGTH(members); ++i) |
| 250 methods.add(members[i]); |
| 251 } |
| 252 return methods.find(name) != methods.end() || V8Debugger::isCommandLineAPIMe
thod(name); |
| 253 } |
| 254 |
| 255 static void returnDataCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| 256 { |
| 257 info.GetReturnValue().Set(info.Data()); |
| 258 } |
| 259 |
| 260 static void createFunctionProperty(v8::Local<v8::Context> context, v8::Local<v8:
:Object> object, const char* name, v8::FunctionCallback callback, const char* de
scription) |
| 261 { |
| 262 v8::Local<v8::String> funcName = v8String(context->GetIsolate(), name); |
| 263 v8::Local<v8::Function> func; |
| 264 if (!v8::Function::New(context, callback).ToLocal(&func)) |
| 265 return; |
| 266 func->SetName(funcName); |
| 267 v8::Local<v8::String> returnValue = v8String(context->GetIsolate(), descript
ion); |
| 268 v8::Local<v8::Function> toStringFunction; |
| 269 if (v8::Function::New(context, returnDataCallback, returnValue).ToLocal(&toS
tringFunction)) |
| 270 func->Set(v8String(context->GetIsolate(), "toString"), toStringFunction)
; |
| 271 if (!object->Set(context, funcName, func).FromMaybe(false)) |
| 272 return; |
| 273 } |
| 274 |
| 275 void MainThreadDebugger::installAdditionalCommandLineAPI(v8::Local<v8::Context>
context, v8::Local<v8::Object> object) |
| 276 { |
| 277 createFunctionProperty(context, object, "$", MainThreadDebugger::querySelect
orCallback, "function $(selector, [startNode]) { [Command Line API] }"); |
| 278 createFunctionProperty(context, object, "$$", MainThreadDebugger::querySelec
torAllCallback, "function $$(selector, [startNode]) { [Command Line API] }"); |
| 279 createFunctionProperty(context, object, "$x", MainThreadDebugger::xpathSelec
torCallback, "function $x(xpath, [startNode]) { [Command Line API] }"); |
| 280 } |
| 281 |
| 282 static Node* secondArgumentAsNode(const v8::FunctionCallbackInfo<v8::Value>& inf
o) |
| 283 { |
| 284 if (info.Length() > 1) { |
| 285 if (Node* node = V8Node::toImplWithTypeCheck(info.GetIsolate(), info[1])
) |
| 286 return node; |
| 287 } |
| 288 ExecutionContext* executionContext = toExecutionContext(info.GetIsolate()->G
etCurrentContext()); |
| 289 if (executionContext->isDocument()) |
| 290 return toDocument(executionContext); |
| 291 return nullptr; |
| 292 } |
| 293 |
| 294 void MainThreadDebugger::querySelectorCallback(const v8::FunctionCallbackInfo<v8
::Value>& info) |
| 295 { |
| 296 if (info.Length() < 1) |
| 297 return; |
| 298 String selector = toCoreStringWithUndefinedOrNullCheck(info[0]); |
| 299 if (selector.isEmpty()) |
| 300 return; |
| 301 Node* node = secondArgumentAsNode(info); |
| 302 if (!node || !node->isContainerNode()) |
| 303 return; |
| 304 ExceptionState exceptionState(ExceptionState::ExecutionContext, "$", "Comman
dLineAPI", info.Holder(), info.GetIsolate()); |
| 305 Element* element = toContainerNode(node)->querySelector(AtomicString(selecto
r), exceptionState); |
| 306 if (exceptionState.throwIfNeeded()) |
| 307 return; |
| 308 if (element) |
| 309 info.GetReturnValue().Set(toV8(element, info.Holder(), info.GetIsolate()
)); |
| 310 else |
| 311 info.GetReturnValue().Set(v8::Null(info.GetIsolate())); |
| 312 } |
| 313 |
| 314 void MainThreadDebugger::querySelectorAllCallback(const v8::FunctionCallbackInfo
<v8::Value>& info) |
| 315 { |
| 316 if (info.Length() < 1) |
| 317 return; |
| 318 String selector = toCoreStringWithUndefinedOrNullCheck(info[0]); |
| 319 if (selector.isEmpty()) |
| 320 return; |
| 321 Node* node = secondArgumentAsNode(info); |
| 322 if (!node || !node->isContainerNode()) |
| 323 return; |
| 324 ExceptionState exceptionState(ExceptionState::ExecutionContext, "$$", "Comma
ndLineAPI", info.Holder(), info.GetIsolate()); |
| 325 // toV8(elementList) doesn't work here, since we need a proper Array instanc
e, not NodeList. |
| 326 StaticElementList* elementList = toContainerNode(node)->querySelectorAll(Ato
micString(selector), exceptionState); |
| 327 if (exceptionState.throwIfNeeded() || !elementList) |
| 328 return; |
| 329 v8::Isolate* isolate = info.GetIsolate(); |
| 330 v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| 331 v8::Local<v8::Array> nodes = v8::Array::New(isolate, elementList->length()); |
| 332 for (size_t i = 0; i < elementList->length(); ++i) { |
| 333 Element* element = elementList->item(i); |
| 334 if (!nodes->Set(context, i, toV8(element, info.Holder(), info.GetIsolate
())).FromMaybe(false)) |
| 335 return; |
| 336 } |
| 337 info.GetReturnValue().Set(nodes); |
| 338 } |
| 339 |
| 340 void MainThreadDebugger::xpathSelectorCallback(const v8::FunctionCallbackInfo<v8
::Value>& info) |
| 341 { |
| 342 if (info.Length() < 1) |
| 343 return; |
| 344 String selector = toCoreStringWithUndefinedOrNullCheck(info[0]); |
| 345 if (selector.isEmpty()) |
| 346 return; |
| 347 Node* node = secondArgumentAsNode(info); |
| 348 if (!node || !node->isContainerNode()) |
| 349 return; |
| 350 |
| 351 ExceptionState exceptionState(ExceptionState::ExecutionContext, "$x", "Comma
ndLineAPI", info.Holder(), info.GetIsolate()); |
| 352 XPathResult* result = XPathEvaluator::create()->evaluate(selector, node, nul
lptr, XPathResult::ANY_TYPE, ScriptValue(), exceptionState); |
| 353 if (exceptionState.throwIfNeeded() || !result) |
| 354 return; |
| 355 if (result->resultType() == XPathResult::NUMBER_TYPE) { |
| 356 info.GetReturnValue().Set(toV8(result->numberValue(exceptionState), info
.Holder(), info.GetIsolate())); |
| 357 } else if (result->resultType() == XPathResult::STRING_TYPE) { |
| 358 info.GetReturnValue().Set(toV8(result->stringValue(exceptionState), info
.Holder(), info.GetIsolate())); |
| 359 } else if (result->resultType() == XPathResult::BOOLEAN_TYPE) { |
| 360 info.GetReturnValue().Set(toV8(result->booleanValue(exceptionState), inf
o.Holder(), info.GetIsolate())); |
| 361 } else { |
| 362 v8::Isolate* isolate = info.GetIsolate(); |
| 363 v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| 364 v8::Local<v8::Array> nodes = v8::Array::New(isolate); |
| 365 size_t index = 0; |
| 366 while (Node* node = result->iterateNext(exceptionState)) { |
| 367 if (exceptionState.throwIfNeeded()) |
| 368 return; |
| 369 if (!nodes->Set(context, index++, toV8(node, info.Holder(), info.Get
Isolate())).FromMaybe(false)) |
| 370 return; |
| 371 } |
| 372 info.GetReturnValue().Set(nodes); |
| 373 } |
| 374 exceptionState.throwIfNeeded(); |
| 375 } |
| 376 |
237 } // namespace blink | 377 } // namespace blink |
OLD | NEW |