1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * Copyright (C) 2013 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "core/testing/Internals.h" 29 30 #include "bindings/v8/ExceptionMessages.h" 31 #include "bindings/v8/ExceptionState.h" 32 #include "bindings/v8/ScriptFunction.h" 33 #include "bindings/v8/ScriptPromise.h" 34 #include "bindings/v8/ScriptPromiseResolver.h" 35 #include "bindings/v8/SerializedScriptValue.h" 36 #include "bindings/v8/V8ThrowException.h" 37 #include "core/InternalRuntimeFlags.h" 38 #include "core/animation/AnimationTimeline.h" 39 #include "core/css/StyleSheetContents.h" 40 #include "core/css/resolver/StyleResolver.h" 41 #include "core/css/resolver/StyleResolverStats.h" 42 #include "core/css/resolver/ViewportStyleResolver.h" 43 #include "core/dom/ClientRect.h" 44 #include "core/dom/ClientRectList.h" 45 #include "core/dom/DOMStringList.h" 46 #include "core/dom/Document.h" 47 #include "core/dom/DocumentMarker.h" 48 #include "core/dom/DocumentMarkerController.h" 49 #include "core/dom/Element.h" 50 #include "core/dom/ExceptionCode.h" 51 #include "core/dom/FullscreenElementStack.h" 52 #include "core/dom/NodeRenderStyle.h" 53 #include "core/dom/PseudoElement.h" 54 #include "core/dom/Range.h" 55 #include "core/dom/StaticNodeList.h" 56 #include "core/dom/TreeScope.h" 57 #include "core/dom/ViewportDescription.h" 58 #include "core/dom/shadow/ComposedTreeWalker.h" 59 #include "core/dom/shadow/ElementShadow.h" 60 #include "core/dom/shadow/SelectRuleFeatureSet.h" 61 #include "core/dom/shadow/ShadowRoot.h" 62 #include "core/editing/Editor.h" 63 #include "core/editing/PlainTextRange.h" 64 #include "core/editing/SpellCheckRequester.h" 65 #include "core/editing/SpellChecker.h" 66 #include "core/editing/SurroundingText.h" 67 #include "core/editing/TextIterator.h" 68 #include "core/fetch/MemoryCache.h" 69 #include "core/fetch/ResourceFetcher.h" 70 #include "core/frame/DOMPoint.h" 71 #include "core/frame/LocalDOMWindow.h" 72 #include "core/frame/EventHandlerRegistry.h" 73 #include "core/frame/FrameView.h" 74 #include "core/frame/LocalFrame.h" 75 #include "core/frame/Settings.h" 76 #include "core/html/HTMLContentElement.h" 77 #include "core/html/HTMLIFrameElement.h" 78 #include "core/html/HTMLInputElement.h" 79 #include "core/html/HTMLMediaElement.h" 80 #include "core/html/HTMLSelectElement.h" 81 #include "core/html/HTMLTextAreaElement.h" 82 #include "core/html/forms/FormController.h" 83 #include "core/html/shadow/ShadowElementNames.h" 84 #include "core/html/shadow/TextControlInnerElements.h" 85 #include "core/inspector/InspectorClient.h" 86 #include "core/inspector/InspectorConsoleAgent.h" 87 #include "core/inspector/InspectorController.h" 88 #include "core/inspector/InspectorCounters.h" 89 #include "core/inspector/InspectorFrontendChannel.h" 90 #include "core/inspector/InspectorInstrumentation.h" 91 #include "core/inspector/InspectorOverlay.h" 92 #include "core/inspector/InstrumentingAgents.h" 93 #include "core/loader/FrameLoader.h" 94 #include "core/loader/HistoryItem.h" 95 #include "core/page/Chrome.h" 96 #include "core/page/ChromeClient.h" 97 #include "core/page/EventHandler.h" 98 #include "core/page/FocusController.h" 99 #include "core/page/NetworkStateNotifier.h" 100 #include "core/page/Page.h" 101 #include "core/page/PagePopupController.h" 102 #include "core/page/PrintContext.h" 103 #include "core/rendering/RenderLayer.h" 104 #include "core/rendering/RenderMenuList.h" 105 #include "core/rendering/RenderObject.h" 106 #include "core/rendering/RenderTreeAsText.h" 107 #include "core/rendering/RenderView.h" 108 #include "core/rendering/compositing/CompositedLayerMapping.h" 109 #include "core/rendering/compositing/RenderLayerCompositor.h" 110 #include "core/testing/GCObservation.h" 111 #include "core/testing/InternalProfilers.h" 112 #include "core/testing/InternalSettings.h" 113 #include "core/testing/LayerRect.h" 114 #include "core/testing/LayerRectList.h" 115 #include "core/testing/MallocStatistics.h" 116 #include "core/testing/MockPagePopupDriver.h" 117 #include "core/testing/TypeConversions.h" 118 #include "core/workers/WorkerThread.h" 119 #include "platform/Cursor.h" 120 #include "platform/Language.h" 121 #include "platform/RuntimeEnabledFeatures.h" 122 #include "platform/TraceEvent.h" 123 #include "platform/geometry/IntRect.h" 124 #include "platform/geometry/LayoutRect.h" 125 #include "platform/graphics/GraphicsLayer.h" 126 #include "platform/graphics/filters/FilterOperation.h" 127 #include "platform/graphics/filters/FilterOperations.h" 128 #include "platform/weborigin/SchemeRegistry.h" 129 #include "public/platform/Platform.h" 130 #include "public/platform/WebConnectionType.h" 131 #include "public/platform/WebGraphicsContext3D.h" 132 #include "public/platform/WebGraphicsContext3DProvider.h" 133 #include "public/platform/WebLayer.h" 134 #include "wtf/InstanceCounter.h" 135 #include "wtf/PassOwnPtr.h" 136 #include "wtf/dtoa.h" 137 #include "wtf/text/StringBuffer.h" 138 #include <v8.h> 139 140 namespace WebCore { 141 142 // FIXME: oilpan: These will be removed soon. 143 static MockPagePopupDriver* s_pagePopupDriver = 0; 144 145 using namespace HTMLNames; 146 147 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result) 148 { 149 if (markerType.isEmpty() || equalIgnoringCase(markerType, "all")) 150 result = DocumentMarker::AllMarkers(); 151 else if (equalIgnoringCase(markerType, "Spelling")) 152 result = DocumentMarker::Spelling; 153 else if (equalIgnoringCase(markerType, "Grammar")) 154 result = DocumentMarker::Grammar; 155 else if (equalIgnoringCase(markerType, "TextMatch")) 156 result = DocumentMarker::TextMatch; 157 else 158 return false; 159 160 return true; 161 } 162 163 static SpellCheckRequester* spellCheckRequester(Document* document) 164 { 165 if (!document || !document->frame()) 166 return 0; 167 return &document->frame()->spellChecker().spellCheckRequester(); 168 } 169 170 const char* Internals::internalsId = "internals"; 171 172 PassRefPtrWillBeRawPtr<Internals> Internals::create(Document* document) 173 { 174 return adoptRefWillBeNoop(new Internals(document)); 175 } 176 177 Internals::~Internals() 178 { 179 } 180 181 void Internals::resetToConsistentState(Page* page) 182 { 183 ASSERT(page); 184 185 page->setDeviceScaleFactor(1); 186 page->setIsCursorVisible(true); 187 page->setPageScaleFactor(1, IntPoint(0, 0)); 188 TextRun::setAllowsRoundingHacks(false); 189 WebCore::overrideUserPreferredLanguages(Vector<AtomicString>()); 190 delete s_pagePopupDriver; 191 s_pagePopupDriver = 0; 192 page->chrome().client().resetPagePopupDriver(); 193 if (!page->deprecatedLocalMainFrame()->spellChecker().isContinuousSpellCheckingEnabled()) 194 page->deprecatedLocalMainFrame()->spellChecker().toggleContinuousSpellChecking(); 195 if (page->deprecatedLocalMainFrame()->editor().isOverwriteModeEnabled()) 196 page->deprecatedLocalMainFrame()->editor().toggleOverwriteModeEnabled(); 197 198 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 199 scrollingCoordinator->reset(); 200 201 page->deprecatedLocalMainFrame()->view()->clear(); 202 } 203 204 Internals::Internals(Document* document) 205 : ContextLifecycleObserver(document) 206 , m_runtimeFlags(InternalRuntimeFlags::create()) 207 { 208 } 209 210 Document* Internals::contextDocument() const 211 { 212 return toDocument(executionContext()); 213 } 214 215 LocalFrame* Internals::frame() const 216 { 217 if (!contextDocument()) 218 return 0; 219 return contextDocument()->frame(); 220 } 221 222 InternalSettings* Internals::settings() const 223 { 224 Document* document = contextDocument(); 225 if (!document) 226 return 0; 227 Page* page = document->page(); 228 if (!page) 229 return 0; 230 return InternalSettings::from(*page); 231 } 232 233 InternalRuntimeFlags* Internals::runtimeFlags() const 234 { 235 return m_runtimeFlags.get(); 236 } 237 238 InternalProfilers* Internals::profilers() 239 { 240 if (!m_profilers) 241 m_profilers = InternalProfilers::create(); 242 return m_profilers.get(); 243 } 244 245 unsigned Internals::workerThreadCount() const 246 { 247 return WorkerThread::workerThreadCount(); 248 } 249 250 String Internals::address(Node* node) 251 { 252 char buf[32]; 253 sprintf(buf, "%p", node); 254 255 return String(buf); 256 } 257 258 PassRefPtrWillBeRawPtr<GCObservation> Internals::observeGC(ScriptValue scriptValue) 259 { 260 v8::Handle<v8::Value> observedValue = scriptValue.v8Value(); 261 ASSERT(!observedValue.IsEmpty()); 262 if (observedValue->IsNull() || observedValue->IsUndefined()) { 263 V8ThrowException::throwTypeError("value to observe is null or undefined", v8::Isolate::GetCurrent()); 264 return nullptr; 265 } 266 267 return GCObservation::create(observedValue); 268 } 269 270 unsigned Internals::updateStyleAndReturnAffectedElementCount(ExceptionState& exceptionState) const 271 { 272 Document* document = contextDocument(); 273 if (!document) { 274 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 275 return 0; 276 } 277 278 unsigned beforeCount = document->styleEngine()->resolverAccessCount(); 279 document->updateRenderTreeIfNeeded(); 280 return document->styleEngine()->resolverAccessCount() - beforeCount; 281 } 282 283 unsigned Internals::needsLayoutCount(ExceptionState& exceptionState) const 284 { 285 LocalFrame* contextFrame = frame(); 286 if (!contextFrame) { 287 exceptionState.throwDOMException(InvalidAccessError, "No context frame is available."); 288 return 0; 289 } 290 291 bool isPartial; 292 unsigned needsLayoutObjects; 293 unsigned totalObjects; 294 contextFrame->countObjectsNeedingLayout(needsLayoutObjects, totalObjects, isPartial); 295 return needsLayoutObjects; 296 } 297 298 bool Internals::isPreloaded(const String& url) 299 { 300 Document* document = contextDocument(); 301 return document->fetcher()->isPreloaded(url); 302 } 303 304 bool Internals::isLoadingFromMemoryCache(const String& url) 305 { 306 if (!contextDocument()) 307 return false; 308 Resource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url)); 309 return resource && resource->status() == Resource::Cached; 310 } 311 312 void Internals::crash() 313 { 314 CRASH(); 315 } 316 317 void Internals::setStyleResolverStatsEnabled(bool enabled) 318 { 319 Document* document = contextDocument(); 320 if (enabled) 321 document->ensureStyleResolver().enableStats(StyleResolver::ReportSlowStats); 322 else 323 document->ensureStyleResolver().disableStats(); 324 } 325 326 String Internals::styleResolverStatsReport(ExceptionState& exceptionState) const 327 { 328 Document* document = contextDocument(); 329 if (!document->ensureStyleResolver().stats()) { 330 exceptionState.throwDOMException(InvalidStateError, "Style resolver stats not enabled"); 331 return String(); 332 } 333 return document->ensureStyleResolver().stats()->report(); 334 } 335 336 String Internals::styleResolverStatsTotalsReport(ExceptionState& exceptionState) const 337 { 338 Document* document = contextDocument(); 339 if (!document->ensureStyleResolver().statsTotals()) { 340 exceptionState.throwDOMException(InvalidStateError, "Style resolver stats not enabled"); 341 return String(); 342 } 343 return document->ensureStyleResolver().statsTotals()->report(); 344 } 345 346 bool Internals::isSharingStyle(Element* element1, Element* element2, ExceptionState& exceptionState) const 347 { 348 if (!element1 || !element2) { 349 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(element1 ? 2 : 1, "Element")); 350 return false; 351 } 352 return element1->renderStyle() == element2->renderStyle(); 353 } 354 355 bool Internals::isValidContentSelect(Element* insertionPoint, ExceptionState& exceptionState) 356 { 357 if (!insertionPoint || !insertionPoint->isInsertionPoint()) { 358 exceptionState.throwDOMException(InvalidAccessError, "The insertion point provided is invalid."); 359 return false; 360 } 361 362 return isHTMLContentElement(*insertionPoint) && toHTMLContentElement(*insertionPoint).isSelectValid(); 363 } 364 365 Node* Internals::treeScopeRootNode(Node* node, ExceptionState& exceptionState) 366 { 367 if (!node) { 368 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 369 return 0; 370 } 371 372 return &node->treeScope().rootNode(); 373 } 374 375 Node* Internals::parentTreeScope(Node* node, ExceptionState& exceptionState) 376 { 377 if (!node) { 378 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 379 return 0; 380 } 381 const TreeScope* parentTreeScope = node->treeScope().parentTreeScope(); 382 return parentTreeScope ? &parentTreeScope->rootNode() : 0; 383 } 384 385 bool Internals::hasSelectorForIdInShadow(Element* host, const AtomicString& idValue, ExceptionState& exceptionState) 386 { 387 if (!host || !host->shadow()) { 388 exceptionState.throwDOMException(InvalidAccessError, "The host element provided is invalid, or does not have a shadow."); 389 return 0; 390 } 391 392 return host->shadow()->ensureSelectFeatureSet().hasSelectorForId(idValue); 393 } 394 395 bool Internals::hasSelectorForClassInShadow(Element* host, const AtomicString& className, ExceptionState& exceptionState) 396 { 397 if (!host || !host->shadow()) { 398 exceptionState.throwDOMException(InvalidAccessError, "The host element provided is invalid, or does not have a shadow."); 399 return 0; 400 } 401 402 return host->shadow()->ensureSelectFeatureSet().hasSelectorForClass(className); 403 } 404 405 bool Internals::hasSelectorForAttributeInShadow(Element* host, const AtomicString& attributeName, ExceptionState& exceptionState) 406 { 407 if (!host || !host->shadow()) { 408 exceptionState.throwDOMException(InvalidAccessError, "The host element provided is invalid, or does not have a shadow."); 409 return 0; 410 } 411 412 return host->shadow()->ensureSelectFeatureSet().hasSelectorForAttribute(attributeName); 413 } 414 415 bool Internals::hasSelectorForPseudoClassInShadow(Element* host, const String& pseudoClass, ExceptionState& exceptionState) 416 { 417 if (!host || !host->shadow()) { 418 exceptionState.throwDOMException(InvalidAccessError, "The host element provided is invalid, or does not have a shadow."); 419 return 0; 420 } 421 422 const SelectRuleFeatureSet& featureSet = host->shadow()->ensureSelectFeatureSet(); 423 if (pseudoClass == "checked") 424 return featureSet.hasSelectorForChecked(); 425 if (pseudoClass == "enabled") 426 return featureSet.hasSelectorForEnabled(); 427 if (pseudoClass == "disabled") 428 return featureSet.hasSelectorForDisabled(); 429 if (pseudoClass == "indeterminate") 430 return featureSet.hasSelectorForIndeterminate(); 431 if (pseudoClass == "link") 432 return featureSet.hasSelectorForLink(); 433 if (pseudoClass == "target") 434 return featureSet.hasSelectorForTarget(); 435 if (pseudoClass == "visited") 436 return featureSet.hasSelectorForVisited(); 437 438 ASSERT_NOT_REACHED(); 439 return false; 440 } 441 442 unsigned short Internals::compareTreeScopePosition(const Node* node1, const Node* node2, ExceptionState& exceptionState) const 443 { 444 if (!node1 || !node2) { 445 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(node1 ? 2 : 1, "Node")); 446 return 0; 447 } 448 const TreeScope* treeScope1 = node1->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node1)) : 449 node1->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node1)) : 0; 450 const TreeScope* treeScope2 = node2->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node2)) : 451 node2->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node2)) : 0; 452 if (!treeScope1 || !treeScope2) { 453 exceptionState.throwDOMException(InvalidAccessError, String::format("The %s node is neither a document node, nor a shadow root.", treeScope1 ? "second" : "first")); 454 return 0; 455 } 456 return treeScope1->comparePosition(*treeScope2); 457 } 458 459 unsigned Internals::numberOfActiveAnimations() const 460 { 461 LocalFrame* contextFrame = frame(); 462 Document* document = contextFrame->document(); 463 return document->timeline().numberOfActiveAnimationsForTesting(); 464 } 465 466 void Internals::pauseAnimations(double pauseTime, ExceptionState& exceptionState) 467 { 468 if (pauseTime < 0) { 469 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("pauseTime", pauseTime, 0.0)); 470 return; 471 } 472 473 frame()->view()->updateLayoutAndStyleForPainting(); 474 frame()->document()->timeline().pauseAnimationsForTesting(pauseTime); 475 } 476 477 bool Internals::hasShadowInsertionPoint(const Node* root, ExceptionState& exceptionState) const 478 { 479 if (root && root->isShadowRoot()) 480 return toShadowRoot(root)->containsShadowElements(); 481 482 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 483 return 0; 484 } 485 486 bool Internals::hasContentElement(const Node* root, ExceptionState& exceptionState) const 487 { 488 if (root && root->isShadowRoot()) 489 return toShadowRoot(root)->containsContentElements(); 490 491 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 492 return 0; 493 } 494 495 size_t Internals::countElementShadow(const Node* root, ExceptionState& exceptionState) const 496 { 497 if (!root || !root->isShadowRoot()) { 498 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 499 return 0; 500 } 501 return toShadowRoot(root)->childShadowRootCount(); 502 } 503 504 Node* Internals::nextSiblingByWalker(Node* node, ExceptionState& exceptionState) 505 { 506 if (!node) { 507 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 508 return 0; 509 } 510 ComposedTreeWalker walker(node); 511 walker.nextSibling(); 512 return walker.get(); 513 } 514 515 Node* Internals::firstChildByWalker(Node* node, ExceptionState& exceptionState) 516 { 517 if (!node) { 518 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 519 return 0; 520 } 521 ComposedTreeWalker walker(node); 522 walker.firstChild(); 523 return walker.get(); 524 } 525 526 Node* Internals::lastChildByWalker(Node* node, ExceptionState& exceptionState) 527 { 528 if (!node) { 529 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 530 return 0; 531 } 532 ComposedTreeWalker walker(node); 533 walker.lastChild(); 534 return walker.get(); 535 } 536 537 Node* Internals::nextNodeByWalker(Node* node, ExceptionState& exceptionState) 538 { 539 if (!node) { 540 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 541 return 0; 542 } 543 ComposedTreeWalker walker(node); 544 walker.next(); 545 return walker.get(); 546 } 547 548 Node* Internals::previousNodeByWalker(Node* node, ExceptionState& exceptionState) 549 { 550 if (!node) { 551 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 552 return 0; 553 } 554 ComposedTreeWalker walker(node); 555 walker.previous(); 556 return walker.get(); 557 } 558 559 String Internals::elementRenderTreeAsText(Element* element, ExceptionState& exceptionState) 560 { 561 if (!element) { 562 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 563 return String(); 564 } 565 566 String representation = externalRepresentation(element); 567 if (representation.isEmpty()) { 568 exceptionState.throwDOMException(InvalidAccessError, "The element provided has no external representation."); 569 return String(); 570 } 571 572 return representation; 573 } 574 575 PassRefPtrWillBeRawPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node, ExceptionState& exceptionState) const 576 { 577 if (!node) { 578 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 579 return nullptr; 580 } 581 582 bool allowVisitedStyle = true; 583 return CSSComputedStyleDeclaration::create(node, allowVisitedStyle); 584 } 585 586 ShadowRoot* Internals::shadowRoot(Element* host, ExceptionState& exceptionState) 587 { 588 // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot(). 589 // https://bugs.webkit.org/show_bug.cgi?id=78465 590 return youngestShadowRoot(host, exceptionState); 591 } 592 593 ShadowRoot* Internals::youngestShadowRoot(Element* host, ExceptionState& exceptionState) 594 { 595 if (!host) { 596 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 597 return 0; 598 } 599 600 if (ElementShadow* shadow = host->shadow()) 601 return shadow->youngestShadowRoot(); 602 return 0; 603 } 604 605 ShadowRoot* Internals::oldestShadowRoot(Element* host, ExceptionState& exceptionState) 606 { 607 if (!host) { 608 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 609 return 0; 610 } 611 612 if (ElementShadow* shadow = host->shadow()) 613 return shadow->oldestShadowRoot(); 614 return 0; 615 } 616 617 ShadowRoot* Internals::youngerShadowRoot(Node* shadow, ExceptionState& exceptionState) 618 { 619 if (!shadow || !shadow->isShadowRoot()) { 620 exceptionState.throwDOMException(InvalidAccessError, "The node provided is not a valid shadow root."); 621 return 0; 622 } 623 624 return toShadowRoot(shadow)->youngerShadowRoot(); 625 } 626 627 String Internals::shadowRootType(const Node* root, ExceptionState& exceptionState) const 628 { 629 if (!root || !root->isShadowRoot()) { 630 exceptionState.throwDOMException(InvalidAccessError, "The node provided is not a valid shadow root."); 631 return String(); 632 } 633 634 switch (toShadowRoot(root)->type()) { 635 case ShadowRoot::UserAgentShadowRoot: 636 return String("UserAgentShadowRoot"); 637 case ShadowRoot::AuthorShadowRoot: 638 return String("AuthorShadowRoot"); 639 default: 640 ASSERT_NOT_REACHED(); 641 return String("Unknown"); 642 } 643 } 644 645 const AtomicString& Internals::shadowPseudoId(Element* element, ExceptionState& exceptionState) 646 { 647 if (!element) { 648 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 649 return nullAtom; 650 } 651 652 return element->shadowPseudoId(); 653 } 654 655 void Internals::setShadowPseudoId(Element* element, const AtomicString& id, ExceptionState& exceptionState) 656 { 657 if (!element) { 658 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 659 return; 660 } 661 662 return element->setShadowPseudoId(id); 663 } 664 665 String Internals::visiblePlaceholder(Element* element) 666 { 667 if (element && isHTMLTextFormControlElement(*element)) { 668 if (toHTMLTextFormControlElement(element)->placeholderShouldBeVisible()) 669 return toHTMLTextFormControlElement(element)->placeholderElement()->textContent(); 670 } 671 672 return String(); 673 } 674 675 void Internals::selectColorInColorChooser(Element* element, const String& colorValue) 676 { 677 ASSERT(element); 678 if (!isHTMLInputElement(*element)) 679 return; 680 Color color; 681 if (!color.setFromString(colorValue)) 682 return; 683 toHTMLInputElement(*element).selectColorInColorChooser(color); 684 } 685 686 bool Internals::hasAutofocusRequest(Document* document) 687 { 688 if (!document) 689 document = contextDocument(); 690 return document->autofocusElement(); 691 } 692 693 bool Internals::hasAutofocusRequest() 694 { 695 return hasAutofocusRequest(0); 696 } 697 698 Vector<String> Internals::formControlStateOfHistoryItem(ExceptionState& exceptionState) 699 { 700 HistoryItem* mainItem = frame()->loader().currentItem(); 701 if (!mainItem) { 702 exceptionState.throwDOMException(InvalidAccessError, "No history item is available."); 703 return Vector<String>(); 704 } 705 return mainItem->documentState(); 706 } 707 708 void Internals::setFormControlStateOfHistoryItem(const Vector<String>& state, ExceptionState& exceptionState) 709 { 710 HistoryItem* mainItem = frame()->loader().currentItem(); 711 if (!mainItem) { 712 exceptionState.throwDOMException(InvalidAccessError, "No history item is available."); 713 return; 714 } 715 mainItem->clearDocumentState(); 716 mainItem->setDocumentState(state); 717 } 718 719 void Internals::setEnableMockPagePopup(bool enabled, ExceptionState& exceptionState) 720 { 721 Document* document = contextDocument(); 722 if (!document || !document->page()) 723 return; 724 Page* page = document->page(); 725 if (!enabled) { 726 page->chrome().client().resetPagePopupDriver(); 727 return; 728 } 729 if (!s_pagePopupDriver) 730 s_pagePopupDriver = MockPagePopupDriver::create(page->deprecatedLocalMainFrame()).leakPtr(); 731 page->chrome().client().setPagePopupDriver(s_pagePopupDriver); 732 } 733 734 PassRefPtrWillBeRawPtr<PagePopupController> Internals::pagePopupController() 735 { 736 return s_pagePopupDriver ? s_pagePopupDriver->pagePopupController() : 0; 737 } 738 739 PassRefPtrWillBeRawPtr<ClientRect> Internals::unscaledViewportRect(ExceptionState& exceptionState) 740 { 741 Document* document = contextDocument(); 742 if (!document || !document->view()) { 743 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's viewport cannot be retrieved." : "No context document can be obtained."); 744 return ClientRect::create(); 745 } 746 747 return ClientRect::create(document->view()->visibleContentRect()); 748 } 749 750 PassRefPtrWillBeRawPtr<ClientRect> Internals::absoluteCaretBounds(ExceptionState& exceptionState) 751 { 752 Document* document = contextDocument(); 753 if (!document || !document->frame()) { 754 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "No context document can be obtained."); 755 return ClientRect::create(); 756 } 757 758 return ClientRect::create(document->frame()->selection().absoluteCaretBounds()); 759 } 760 761 PassRefPtrWillBeRawPtr<ClientRect> Internals::boundingBox(Element* element, ExceptionState& exceptionState) 762 { 763 if (!element) { 764 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 765 return ClientRect::create(); 766 } 767 768 element->document().updateLayoutIgnorePendingStylesheets(); 769 RenderObject* renderer = element->renderer(); 770 if (!renderer) 771 return ClientRect::create(); 772 return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms()); 773 } 774 775 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionState& exceptionState) 776 { 777 if (!node) { 778 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 779 return 0; 780 } 781 782 DocumentMarker::MarkerTypes markerTypes = 0; 783 if (!markerTypesFrom(markerType, markerTypes)) { 784 exceptionState.throwDOMException(SyntaxError, "The marker type provided ('" + markerType + "') is invalid."); 785 return 0; 786 } 787 788 return node->document().markers().markersFor(node, markerTypes).size(); 789 } 790 791 unsigned Internals::activeMarkerCountForNode(Node* node, ExceptionState& exceptionState) 792 { 793 if (!node) { 794 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 795 return 0; 796 } 797 798 // Only TextMatch markers can be active. 799 DocumentMarker::MarkerType markerType = DocumentMarker::TextMatch; 800 WillBeHeapVector<DocumentMarker*> markers = node->document().markers().markersFor(node, markerType); 801 802 unsigned activeMarkerCount = 0; 803 for (WillBeHeapVector<DocumentMarker*>::iterator iter = markers.begin(); iter != markers.end(); ++iter) { 804 if ((*iter)->activeMatch()) 805 activeMarkerCount++; 806 } 807 808 return activeMarkerCount; 809 } 810 811 DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState) 812 { 813 if (!node) { 814 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 815 return 0; 816 } 817 818 DocumentMarker::MarkerTypes markerTypes = 0; 819 if (!markerTypesFrom(markerType, markerTypes)) { 820 exceptionState.throwDOMException(SyntaxError, "The marker type provided ('" + markerType + "') is invalid."); 821 return 0; 822 } 823 824 WillBeHeapVector<DocumentMarker*> markers = node->document().markers().markersFor(node, markerTypes); 825 if (markers.size() <= index) 826 return 0; 827 return markers[index]; 828 } 829 830 PassRefPtrWillBeRawPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState) 831 { 832 DocumentMarker* marker = markerAt(node, markerType, index, exceptionState); 833 if (!marker) 834 return nullptr; 835 return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset()); 836 } 837 838 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState) 839 { 840 DocumentMarker* marker = markerAt(node, markerType, index, exceptionState); 841 if (!marker) 842 return String(); 843 return marker->description(); 844 } 845 846 void Internals::addTextMatchMarker(const Range* range, bool isActive) 847 { 848 range->ownerDocument().updateLayoutIgnorePendingStylesheets(); 849 range->ownerDocument().markers().addTextMatchMarker(range, isActive); 850 } 851 852 void Internals::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active, ExceptionState& exceptionState) 853 { 854 if (!node) { 855 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 856 return; 857 } 858 859 node->document().markers().setMarkersActive(node, startOffset, endOffset, active); 860 } 861 862 void Internals::setMarkedTextMatchesAreHighlighted(Document* document, bool highlight, ExceptionState&) 863 { 864 if (!document || !document->frame()) 865 return; 866 867 document->frame()->editor().setMarkedTextMatchesAreHighlighted(highlight); 868 } 869 870 void Internals::setScrollViewPosition(Document* document, long x, long y, ExceptionState& exceptionState) 871 { 872 if (!document || !document->view()) { 873 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's view cannot be retrieved." : "The document provided is invalid."); 874 return; 875 } 876 877 FrameView* frameView = document->view(); 878 bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge(); 879 bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed(); 880 881 frameView->setConstrainsScrollingToContentEdge(false); 882 frameView->setScrollbarsSuppressed(false); 883 frameView->setScrollOffsetFromInternals(IntPoint(x, y)); 884 frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue); 885 frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue); 886 } 887 888 String Internals::viewportAsText(Document* document, float, int availableWidth, int availableHeight, ExceptionState& exceptionState) 889 { 890 if (!document || !document->page()) { 891 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "The document provided is invalid."); 892 return String(); 893 } 894 895 document->updateLayoutIgnorePendingStylesheets(); 896 897 Page* page = document->page(); 898 899 // Update initial viewport size. 900 IntSize initialViewportSize(availableWidth, availableHeight); 901 document->page()->deprecatedLocalMainFrame()->view()->setFrameRect(IntRect(IntPoint::zero(), initialViewportSize)); 902 903 ViewportDescription description = page->viewportDescription(); 904 PageScaleConstraints constraints = description.resolve(initialViewportSize, Length()); 905 906 constraints.fitToContentsWidth(constraints.layoutSize.width(), availableWidth); 907 908 StringBuilder builder; 909 910 builder.appendLiteral("viewport size "); 911 builder.append(String::number(constraints.layoutSize.width())); 912 builder.append('x'); 913 builder.append(String::number(constraints.layoutSize.height())); 914 915 builder.appendLiteral(" scale "); 916 builder.append(String::number(constraints.initialScale)); 917 builder.appendLiteral(" with limits ["); 918 builder.append(String::number(constraints.minimumScale)); 919 builder.appendLiteral(", "); 920 builder.append(String::number(constraints.maximumScale)); 921 922 builder.appendLiteral("] and userScalable "); 923 builder.append(description.userZoom ? "true" : "false"); 924 925 return builder.toString(); 926 } 927 928 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionState& exceptionState) 929 { 930 if (!textField) { 931 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 932 return false; 933 } 934 935 if (isHTMLInputElement(*textField)) 936 return toHTMLInputElement(*textField).lastChangeWasUserEdit(); 937 938 if (isHTMLTextAreaElement(*textField)) 939 return toHTMLTextAreaElement(*textField).lastChangeWasUserEdit(); 940 941 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a TEXTAREA."); 942 return false; 943 } 944 945 bool Internals::elementShouldAutoComplete(Element* element, ExceptionState& exceptionState) 946 { 947 if (!element) { 948 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 949 return false; 950 } 951 952 if (isHTMLInputElement(*element)) 953 return toHTMLInputElement(*element).shouldAutocomplete(); 954 955 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT."); 956 return false; 957 } 958 959 String Internals::suggestedValue(Element* element, ExceptionState& exceptionState) 960 { 961 if (!element) { 962 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 963 return String(); 964 } 965 966 if (!element->isFormControlElement()) { 967 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element."); 968 return String(); 969 } 970 971 String suggestedValue; 972 if (isHTMLInputElement(*element)) 973 suggestedValue = toHTMLInputElement(*element).suggestedValue(); 974 975 if (isHTMLTextAreaElement(*element)) 976 suggestedValue = toHTMLTextAreaElement(*element).suggestedValue(); 977 978 if (isHTMLSelectElement(*element)) 979 suggestedValue = toHTMLSelectElement(*element).suggestedValue(); 980 981 return suggestedValue; 982 } 983 984 void Internals::setSuggestedValue(Element* element, const String& value, ExceptionState& exceptionState) 985 { 986 if (!element) { 987 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 988 return; 989 } 990 991 if (!element->isFormControlElement()) { 992 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element."); 993 return; 994 } 995 996 if (isHTMLInputElement(*element)) 997 toHTMLInputElement(*element).setSuggestedValue(value); 998 999 if (isHTMLTextAreaElement(*element)) 1000 toHTMLTextAreaElement(*element).setSuggestedValue(value); 1001 1002 if (isHTMLSelectElement(*element)) 1003 toHTMLSelectElement(*element).setSuggestedValue(value); 1004 } 1005 1006 void Internals::setEditingValue(Element* element, const String& value, ExceptionState& exceptionState) 1007 { 1008 if (!element) { 1009 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 1010 return; 1011 } 1012 1013 if (!isHTMLInputElement(*element)) { 1014 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT."); 1015 return; 1016 } 1017 1018 toHTMLInputElement(*element).setEditingValue(value); 1019 } 1020 1021 void Internals::setAutofilled(Element* element, bool enabled, ExceptionState& exceptionState) 1022 { 1023 if (!element->isFormControlElement()) { 1024 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element."); 1025 return; 1026 } 1027 toHTMLFormControlElement(element)->setAutofilled(enabled); 1028 } 1029 1030 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionState& exceptionState) 1031 { 1032 if (!element || !element->document().view()) { 1033 exceptionState.throwDOMException(InvalidNodeTypeError, element ? "No view can be obtained from the provided element's document." : ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 1034 return; 1035 } 1036 FrameView* frameView = element->document().view(); 1037 frameView->scrollElementToRect(element, IntRect(x, y, w, h)); 1038 } 1039 1040 PassRefPtrWillBeRawPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionState& exceptionState) 1041 { 1042 if (!scope) { 1043 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 1044 return nullptr; 1045 } 1046 1047 // TextIterator depends on Layout information, make sure layout it up to date. 1048 scope->document().updateLayoutIgnorePendingStylesheets(); 1049 1050 return PlainTextRange(rangeLocation, rangeLocation + rangeLength).createRange(*scope); 1051 } 1052 1053 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionState& exceptionState) 1054 { 1055 if (!scope || !range) { 1056 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(scope ? 2 : 1, scope ? "Range" : "Element")); 1057 return 0; 1058 } 1059 1060 // PlainTextRange depends on Layout information, make sure layout it up to date. 1061 scope->document().updateLayoutIgnorePendingStylesheets(); 1062 1063 return PlainTextRange::create(*scope, *range).start(); 1064 } 1065 1066 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionState& exceptionState) 1067 { 1068 if (!scope || !range) { 1069 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(scope ? 2 : 1, scope ? "Range" : "Element")); 1070 return 0; 1071 } 1072 1073 // PlainTextRange depends on Layout information, make sure layout it up to date. 1074 scope->document().updateLayoutIgnorePendingStylesheets(); 1075 1076 return PlainTextRange::create(*scope, *range).length(); 1077 } 1078 1079 String Internals::rangeAsText(const Range* range, ExceptionState& exceptionState) 1080 { 1081 if (!range) { 1082 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Range")); 1083 return String(); 1084 } 1085 1086 return range->text(); 1087 } 1088 1089 PassRefPtrWillBeRawPtr<DOMPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState) 1090 { 1091 if (!document || !document->frame()) { 1092 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1093 return nullptr; 1094 } 1095 1096 document->updateLayout(); 1097 1098 IntSize radius(width / 2, height / 2); 1099 IntPoint point(x + radius.width(), y + radius.height()); 1100 1101 Node* targetNode; 1102 IntPoint adjustedPoint; 1103 1104 bool foundNode = document->frame()->eventHandler().bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode); 1105 if (foundNode) 1106 return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y()); 1107 1108 return nullptr; 1109 } 1110 1111 Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState) 1112 { 1113 if (!document || !document->frame()) { 1114 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1115 return 0; 1116 } 1117 1118 document->updateLayout(); 1119 1120 IntSize radius(width / 2, height / 2); 1121 IntPoint point(x + radius.width(), y + radius.height()); 1122 1123 Node* targetNode; 1124 IntPoint adjustedPoint; 1125 document->frame()->eventHandler().bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode); 1126 return targetNode; 1127 } 1128 1129 PassRefPtrWillBeRawPtr<DOMPoint> Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState) 1130 { 1131 if (!document || !document->frame()) { 1132 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1133 return nullptr; 1134 } 1135 1136 document->updateLayout(); 1137 1138 IntSize radius(width / 2, height / 2); 1139 IntPoint point(x + radius.width(), y + radius.height()); 1140 1141 Node* targetNode = 0; 1142 IntPoint adjustedPoint; 1143 1144 bool foundNode = document->frame()->eventHandler().bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode); 1145 if (foundNode) 1146 return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y()); 1147 1148 return DOMPoint::create(x, y); 1149 } 1150 1151 Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState) 1152 { 1153 if (!document || !document->frame()) { 1154 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1155 return 0; 1156 } 1157 1158 document->updateLayout(); 1159 1160 IntSize radius(width / 2, height / 2); 1161 IntPoint point(x + radius.width(), y + radius.height()); 1162 1163 Node* targetNode = 0; 1164 IntPoint adjustedPoint; 1165 document->frame()->eventHandler().bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode); 1166 return targetNode; 1167 } 1168 1169 PassRefPtrWillBeRawPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState) 1170 { 1171 if (!document || !document->frame()) { 1172 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1173 return nullptr; 1174 } 1175 1176 document->updateLayout(); 1177 1178 IntSize radius(width / 2, height / 2); 1179 IntPoint point(x + radius.width(), y + radius.height()); 1180 1181 Node* targetNode; 1182 IntRect zoomableArea; 1183 bool foundNode = document->frame()->eventHandler().bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode); 1184 if (foundNode) 1185 return ClientRect::create(zoomableArea); 1186 1187 return nullptr; 1188 } 1189 1190 1191 int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionState& exceptionState) 1192 { 1193 SpellCheckRequester* requester = spellCheckRequester(document); 1194 1195 if (!requester) { 1196 exceptionState.throwDOMException(InvalidAccessError, "No spell check requestor can be obtained for the provided document."); 1197 return -1; 1198 } 1199 1200 return requester->lastRequestSequence(); 1201 } 1202 1203 int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionState& exceptionState) 1204 { 1205 SpellCheckRequester* requester = spellCheckRequester(document); 1206 1207 if (!requester) { 1208 exceptionState.throwDOMException(InvalidAccessError, "No spell check requestor can be obtained for the provided document."); 1209 return -1; 1210 } 1211 1212 return requester->lastProcessedSequence(); 1213 } 1214 1215 Vector<AtomicString> Internals::userPreferredLanguages() const 1216 { 1217 return WebCore::userPreferredLanguages(); 1218 } 1219 1220 // Optimally, the bindings generator would pass a Vector<AtomicString> here but 1221 // this is not supported yet. 1222 void Internals::setUserPreferredLanguages(const Vector<String>& languages) 1223 { 1224 Vector<AtomicString> atomicLanguages; 1225 for (size_t i = 0; i < languages.size(); ++i) 1226 atomicLanguages.append(AtomicString(languages[i])); 1227 WebCore::overrideUserPreferredLanguages(atomicLanguages); 1228 } 1229 1230 unsigned Internals::activeDOMObjectCount(Document* document, ExceptionState& exceptionState) 1231 { 1232 if (!document) { 1233 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 1234 return 0; 1235 } 1236 1237 return document->activeDOMObjectCount(); 1238 } 1239 1240 static unsigned eventHandlerCount(Document& document, EventHandlerRegistry::EventHandlerClass handlerClass) 1241 { 1242 if (!document.frameHost()) 1243 return 0; 1244 EventHandlerRegistry* registry = &document.frameHost()->eventHandlerRegistry(); 1245 unsigned count = 0; 1246 const EventTargetSet* targets = registry->eventHandlerTargets(handlerClass); 1247 if (targets) { 1248 for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) 1249 count += iter->value; 1250 } 1251 return count; 1252 } 1253 1254 unsigned Internals::wheelEventHandlerCount(Document* document, ExceptionState& exceptionState) 1255 { 1256 if (!document) { 1257 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 1258 return 0; 1259 } 1260 1261 return eventHandlerCount(*document, EventHandlerRegistry::WheelEvent); 1262 } 1263 1264 unsigned Internals::scrollEventHandlerCount(Document* document, ExceptionState& exceptionState) 1265 { 1266 if (!document) { 1267 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 1268 return 0; 1269 } 1270 1271 return eventHandlerCount(*document, EventHandlerRegistry::ScrollEvent); 1272 } 1273 1274 unsigned Internals::touchEventHandlerCount(Document* document, ExceptionState& exceptionState) 1275 { 1276 if (!document) { 1277 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 1278 return 0; 1279 } 1280 1281 const TouchEventTargetSet* touchHandlers = document->touchEventTargets(); 1282 if (!touchHandlers) 1283 return 0; 1284 1285 unsigned count = 0; 1286 for (TouchEventTargetSet::const_iterator iter = touchHandlers->begin(); iter != touchHandlers->end(); ++iter) 1287 count += iter->value; 1288 return count; 1289 } 1290 1291 static RenderLayer* findRenderLayerForGraphicsLayer(RenderLayer* searchRoot, GraphicsLayer* graphicsLayer, IntSize* layerOffset, String* layerType) 1292 { 1293 *layerOffset = IntSize(); 1294 if (searchRoot->hasCompositedLayerMapping() && graphicsLayer == searchRoot->compositedLayerMapping()->mainGraphicsLayer()) { 1295 CompositedLayerMappingPtr compositedLayerMapping = searchRoot->compositedLayerMapping(); 1296 LayoutSize offset = compositedLayerMapping->contentOffsetInCompositingLayer(); 1297 *layerOffset = IntSize(offset.width(), offset.height()); 1298 return searchRoot; 1299 } 1300 1301 GraphicsLayer* layerForScrolling = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForScrolling() : 0; 1302 if (graphicsLayer == layerForScrolling) { 1303 *layerType = "scrolling"; 1304 return searchRoot; 1305 } 1306 1307 if (searchRoot->compositingState() == PaintsIntoGroupedBacking) { 1308 GraphicsLayer* squashingLayer = searchRoot->groupedMapping()->squashingLayer(); 1309 if (graphicsLayer == squashingLayer) { 1310 *layerType ="squashing"; 1311 *layerOffset = -searchRoot->offsetFromSquashingLayerOrigin(); 1312 return searchRoot; 1313 } 1314 } 1315 1316 GraphicsLayer* layerForHorizontalScrollbar = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForHorizontalScrollbar() : 0; 1317 if (graphicsLayer == layerForHorizontalScrollbar) { 1318 *layerType = "horizontalScrollbar"; 1319 return searchRoot; 1320 } 1321 1322 GraphicsLayer* layerForVerticalScrollbar = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForVerticalScrollbar() : 0; 1323 if (graphicsLayer == layerForVerticalScrollbar) { 1324 *layerType = "verticalScrollbar"; 1325 return searchRoot; 1326 } 1327 1328 GraphicsLayer* layerForScrollCorner = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForScrollCorner() : 0; 1329 if (graphicsLayer == layerForScrollCorner) { 1330 *layerType = "scrollCorner"; 1331 return searchRoot; 1332 } 1333 1334 // Search right to left to increase the chances that we'll choose the top-most layers in a 1335 // grouped mapping for squashing. 1336 for (RenderLayer* child = searchRoot->lastChild(); child; child = child->previousSibling()) { 1337 RenderLayer* foundLayer = findRenderLayerForGraphicsLayer(child, graphicsLayer, layerOffset, layerType); 1338 if (foundLayer) 1339 return foundLayer; 1340 } 1341 1342 return 0; 1343 } 1344 1345 // Given a vector of rects, merge those that are adjacent, leaving empty rects 1346 // in the place of no longer used slots. This is intended to simplify the list 1347 // of rects returned by an SkRegion (which have been split apart for sorting 1348 // purposes). No attempt is made to do this efficiently (eg. by relying on the 1349 // sort criteria of SkRegion). 1350 static void mergeRects(blink::WebVector<blink::WebRect>& rects) 1351 { 1352 for (size_t i = 0; i < rects.size(); ++i) { 1353 if (rects[i].isEmpty()) 1354 continue; 1355 bool updated; 1356 do { 1357 updated = false; 1358 for (size_t j = i+1; j < rects.size(); ++j) { 1359 if (rects[j].isEmpty()) 1360 continue; 1361 // Try to merge rects[j] into rects[i] along the 4 possible edges. 1362 if (rects[i].y == rects[j].y && rects[i].height == rects[j].height) { 1363 if (rects[i].x + rects[i].width == rects[j].x) { 1364 rects[i].width += rects[j].width; 1365 rects[j] = blink::WebRect(); 1366 updated = true; 1367 } else if (rects[i].x == rects[j].x + rects[j].width) { 1368 rects[i].x = rects[j].x; 1369 rects[i].width += rects[j].width; 1370 rects[j] = blink::WebRect(); 1371 updated = true; 1372 } 1373 } else if (rects[i].x == rects[j].x && rects[i].width == rects[j].width) { 1374 if (rects[i].y + rects[i].height == rects[j].y) { 1375 rects[i].height += rects[j].height; 1376 rects[j] = blink::WebRect(); 1377 updated = true; 1378 } else if (rects[i].y == rects[j].y + rects[j].height) { 1379 rects[i].y = rects[j].y; 1380 rects[i].height += rects[j].height; 1381 rects[j] = blink::WebRect(); 1382 updated = true; 1383 } 1384 } 1385 } 1386 } while (updated); 1387 } 1388 } 1389 1390 static void accumulateLayerRectList(RenderLayerCompositor* compositor, GraphicsLayer* graphicsLayer, LayerRectList* rects) 1391 { 1392 blink::WebVector<blink::WebRect> layerRects = graphicsLayer->platformLayer()->touchEventHandlerRegion(); 1393 if (!layerRects.isEmpty()) { 1394 mergeRects(layerRects); 1395 String layerType; 1396 IntSize layerOffset; 1397 RenderLayer* renderLayer = findRenderLayerForGraphicsLayer(compositor->rootRenderLayer(), graphicsLayer, &layerOffset, &layerType); 1398 Node* node = renderLayer ? renderLayer->renderer()->node() : 0; 1399 for (size_t i = 0; i < layerRects.size(); ++i) { 1400 if (!layerRects[i].isEmpty()) { 1401 rects->append(node, layerType, layerOffset.width(), layerOffset.height(), ClientRect::create(layerRects[i])); 1402 } 1403 } 1404 } 1405 1406 size_t numChildren = graphicsLayer->children().size(); 1407 for (size_t i = 0; i < numChildren; ++i) 1408 accumulateLayerRectList(compositor, graphicsLayer->children()[i], rects); 1409 } 1410 1411 PassRefPtrWillBeRawPtr<LayerRectList> Internals::touchEventTargetLayerRects(Document* document, ExceptionState& exceptionState) 1412 { 1413 if (!document || !document->view() || !document->page() || document != contextDocument()) { 1414 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid."); 1415 return nullptr; 1416 } 1417 1418 // Do any pending layout and compositing update (which may call touchEventTargetRectsChange) to ensure this 1419 // really takes any previous changes into account. 1420 forceCompositingUpdate(document, exceptionState); 1421 if (exceptionState.hadException()) 1422 return nullptr; 1423 1424 if (RenderView* view = document->renderView()) { 1425 if (RenderLayerCompositor* compositor = view->compositor()) { 1426 if (GraphicsLayer* rootLayer = compositor->rootGraphicsLayer()) { 1427 RefPtrWillBeRawPtr<LayerRectList> rects = LayerRectList::create(); 1428 accumulateLayerRectList(compositor, rootLayer, rects.get()); 1429 return rects; 1430 } 1431 } 1432 } 1433 1434 return nullptr; 1435 } 1436 1437 PassRefPtrWillBeRawPtr<StaticNodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding, 1438 unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionState& exceptionState) const 1439 { 1440 if (!document || !document->frame() || !document->frame()->view()) { 1441 exceptionState.throwDOMException(InvalidAccessError, "No view can be obtained from the provided document."); 1442 return nullptr; 1443 } 1444 1445 LocalFrame* frame = document->frame(); 1446 FrameView* frameView = document->view(); 1447 RenderView* renderView = document->renderView(); 1448 1449 if (!renderView) 1450 return nullptr; 1451 1452 float zoomFactor = frame->pageZoomFactor(); 1453 LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY())); 1454 1455 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active; 1456 if (ignoreClipping) 1457 hitType |= HitTestRequest::IgnoreClipping; 1458 if (!allowShadowContent) 1459 hitType |= HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent; 1460 if (allowChildFrameContent) 1461 hitType |= HitTestRequest::AllowChildFrameContent; 1462 1463 HitTestRequest request(hitType); 1464 1465 // When ignoreClipping is false, this method returns null for coordinates outside of the viewport. 1466 if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding))) 1467 return nullptr; 1468 1469 WillBeHeapVector<RefPtrWillBeMember<Node> > matches; 1470 1471 // Need padding to trigger a rect based hit test, but we want to return a NodeList 1472 // so we special case this. 1473 if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) { 1474 HitTestResult result(point); 1475 renderView->hitTest(request, result); 1476 if (result.innerNode()) 1477 matches.append(result.innerNode()->deprecatedShadowAncestorNode()); 1478 } else { 1479 HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding); 1480 renderView->hitTest(request, result); 1481 copyToVector(result.rectBasedTestResult(), matches); 1482 } 1483 1484 return StaticNodeList::adopt(matches); 1485 } 1486 1487 void Internals::emitInspectorDidBeginFrame(int frameId) 1488 { 1489 contextDocument()->page()->inspectorController().didBeginFrame(frameId); 1490 } 1491 1492 void Internals::emitInspectorDidCancelFrame() 1493 { 1494 contextDocument()->page()->inspectorController().didCancelFrame(); 1495 } 1496 1497 bool Internals::hasSpellingMarker(Document* document, int from, int length, ExceptionState&) 1498 { 1499 if (!document || !document->frame()) 1500 return 0; 1501 1502 return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length); 1503 } 1504 1505 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionState&) 1506 { 1507 if (!contextDocument() || !contextDocument()->frame()) 1508 return; 1509 1510 if (enabled != contextDocument()->frame()->spellChecker().isContinuousSpellCheckingEnabled()) 1511 contextDocument()->frame()->spellChecker().toggleContinuousSpellChecking(); 1512 } 1513 1514 bool Internals::isOverwriteModeEnabled(Document* document, ExceptionState&) 1515 { 1516 if (!document || !document->frame()) 1517 return 0; 1518 1519 return document->frame()->editor().isOverwriteModeEnabled(); 1520 } 1521 1522 void Internals::toggleOverwriteModeEnabled(Document* document, ExceptionState&) 1523 { 1524 if (!document || !document->frame()) 1525 return; 1526 1527 document->frame()->editor().toggleOverwriteModeEnabled(); 1528 } 1529 1530 unsigned Internals::numberOfLiveNodes() const 1531 { 1532 return InspectorCounters::counterValue(InspectorCounters::NodeCounter); 1533 } 1534 1535 unsigned Internals::numberOfLiveDocuments() const 1536 { 1537 return InspectorCounters::counterValue(InspectorCounters::DocumentCounter); 1538 } 1539 1540 String Internals::dumpRefCountedInstanceCounts() const 1541 { 1542 return WTF::dumpRefCountedInstanceCounts(); 1543 } 1544 1545 Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const 1546 { 1547 InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page()); 1548 if (!instrumentingAgents) 1549 return Vector<String>(); 1550 InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent(); 1551 if (!consoleAgent) 1552 return Vector<String>(); 1553 Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts(); 1554 Vector<String> result(counts.size()); 1555 for (size_t i = 0; i < counts.size(); i++) 1556 result[i] = String::number(counts[i]); 1557 return result; 1558 } 1559 1560 Vector<unsigned long> Internals::setMemoryCacheCapacities(unsigned long minDeadBytes, unsigned long maxDeadBytes, unsigned long totalBytes) 1561 { 1562 Vector<unsigned long> result; 1563 result.append(memoryCache()->minDeadCapacity()); 1564 result.append(memoryCache()->maxDeadCapacity()); 1565 result.append(memoryCache()->capacity()); 1566 memoryCache()->setCapacities(minDeadBytes, maxDeadBytes, totalBytes); 1567 return result; 1568 } 1569 1570 void Internals::setInspectorResourcesDataSizeLimits(int maximumResourcesContentSize, int maximumSingleResourceContentSize, ExceptionState& exceptionState) 1571 { 1572 Page* page = contextDocument()->frame()->page(); 1573 if (!page) { 1574 exceptionState.throwDOMException(InvalidAccessError, "No page can be obtained from the current context document."); 1575 return; 1576 } 1577 page->inspectorController().setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize); 1578 } 1579 1580 bool Internals::hasGrammarMarker(Document* document, int from, int length, ExceptionState&) 1581 { 1582 if (!document || !document->frame()) 1583 return 0; 1584 1585 return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length); 1586 } 1587 1588 unsigned Internals::numberOfScrollableAreas(Document* document, ExceptionState&) 1589 { 1590 unsigned count = 0; 1591 LocalFrame* frame = document->frame(); 1592 if (frame->view()->scrollableAreas()) 1593 count += frame->view()->scrollableAreas()->size(); 1594 1595 for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) { 1596 if (child->isLocalFrame() && toLocalFrame(child)->view() && toLocalFrame(child)->view()->scrollableAreas()) 1597 count += toLocalFrame(child)->view()->scrollableAreas()->size(); 1598 } 1599 1600 return count; 1601 } 1602 1603 bool Internals::isPageBoxVisible(Document* document, int pageNumber, ExceptionState& exceptionState) 1604 { 1605 if (!document) { 1606 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 1607 return false; 1608 } 1609 1610 return document->isPageBoxVisible(pageNumber); 1611 } 1612 1613 String Internals::layerTreeAsText(Document* document, ExceptionState& exceptionState) const 1614 { 1615 return layerTreeAsText(document, 0, exceptionState); 1616 } 1617 1618 String Internals::elementLayerTreeAsText(Element* element, ExceptionState& exceptionState) const 1619 { 1620 if (!element) { 1621 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 1622 return String(); 1623 } 1624 1625 FrameView* frameView = element->document().view(); 1626 frameView->updateLayoutAndStyleForPainting(); 1627 1628 return elementLayerTreeAsText(element, 0, exceptionState); 1629 } 1630 1631 bool Internals::scrollsWithRespectTo(Element* element1, Element* element2, ExceptionState& exceptionState) 1632 { 1633 if (!element1 || !element2) { 1634 exceptionState.throwDOMException(InvalidAccessError, String::format("The %s element provided is invalid.", element1 ? "second" : "first")); 1635 return 0; 1636 } 1637 1638 element1->document().updateLayout(); 1639 1640 RenderObject* renderer1 = element1->renderer(); 1641 RenderObject* renderer2 = element2->renderer(); 1642 if (!renderer1 || !renderer1->isBox()) { 1643 exceptionState.throwDOMException(InvalidAccessError, renderer1 ? "The first provided element's renderer is not a box." : "The first provided element has no renderer."); 1644 return 0; 1645 } 1646 if (!renderer2 || !renderer2->isBox()) { 1647 exceptionState.throwDOMException(InvalidAccessError, renderer2 ? "The second provided element's renderer is not a box." : "The second provided element has no renderer."); 1648 return 0; 1649 } 1650 1651 RenderLayer* layer1 = toRenderBox(renderer1)->layer(); 1652 RenderLayer* layer2 = toRenderBox(renderer2)->layer(); 1653 if (!layer1 || !layer2) { 1654 exceptionState.throwDOMException(InvalidAccessError, String::format("No render layer can be obtained from the %s provided element.", layer1 ? "second" : "first")); 1655 return 0; 1656 } 1657 1658 return layer1->scrollsWithRespectTo(layer2); 1659 } 1660 1661 bool Internals::isUnclippedDescendant(Element* element, ExceptionState& exceptionState) 1662 { 1663 if (!element) { 1664 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 1665 return 0; 1666 } 1667 1668 element->document().view()->updateLayoutAndStyleForPainting(); 1669 1670 RenderObject* renderer = element->renderer(); 1671 if (!renderer || !renderer->isBox()) { 1672 exceptionState.throwDOMException(InvalidAccessError, renderer ? "The provided element's renderer is not a box." : "The provided element has no renderer."); 1673 return 0; 1674 } 1675 1676 RenderLayer* layer = toRenderBox(renderer)->layer(); 1677 if (!layer) { 1678 exceptionState.throwDOMException(InvalidAccessError, "No render layer can be obtained from the provided element."); 1679 return 0; 1680 } 1681 1682 // We used to compute isUnclippedDescendant only when acceleratedCompositingForOverflowScrollEnabled, 1683 // but now we compute it all the time. 1684 // FIXME: Remove this if statement and rebaseline the tests that make this assumption. 1685 if (!layer->compositor()->acceleratedCompositingForOverflowScrollEnabled()) 1686 return false; 1687 1688 return layer->compositingInputs().isUnclippedDescendant; 1689 } 1690 1691 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionState& exceptionState) const 1692 { 1693 if (!document || !document->frame()) { 1694 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1695 return String(); 1696 } 1697 1698 document->view()->updateLayoutAndStyleForPainting(); 1699 1700 return document->frame()->layerTreeAsText(flags); 1701 } 1702 1703 String Internals::elementLayerTreeAsText(Element* element, unsigned flags, ExceptionState& exceptionState) const 1704 { 1705 if (!element) { 1706 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 1707 return String(); 1708 } 1709 1710 element->document().updateLayout(); 1711 1712 RenderObject* renderer = element->renderer(); 1713 if (!renderer || !renderer->isBox()) { 1714 exceptionState.throwDOMException(InvalidAccessError, renderer ? "The provided element's renderer is not a box." : "The provided element has no renderer."); 1715 return String(); 1716 } 1717 1718 RenderLayer* layer = toRenderBox(renderer)->layer(); 1719 if (!layer 1720 || !layer->hasCompositedLayerMapping() 1721 || !layer->compositedLayerMapping()->mainGraphicsLayer()) { 1722 // Don't raise exception in these cases which may be normally used in tests. 1723 return String(); 1724 } 1725 1726 return layer->compositedLayerMapping()->mainGraphicsLayer()->layerTreeAsText(flags); 1727 } 1728 1729 static RenderLayer* getRenderLayerForElement(Element* element, ExceptionState& exceptionState) 1730 { 1731 if (!element) { 1732 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 1733 return 0; 1734 } 1735 1736 RenderObject* renderer = element->renderer(); 1737 if (!renderer || !renderer->isBox()) { 1738 exceptionState.throwDOMException(InvalidAccessError, renderer ? "The provided element's renderer is not a box." : "The provided element has no renderer."); 1739 return 0; 1740 } 1741 1742 RenderLayer* layer = toRenderBox(renderer)->layer(); 1743 if (!layer) { 1744 exceptionState.throwDOMException(InvalidAccessError, "No render layer can be obtained from the provided element."); 1745 return 0; 1746 } 1747 1748 return layer; 1749 } 1750 1751 String Internals::repaintRectsAsText(Document* document, ExceptionState& exceptionState) const 1752 { 1753 if (!document || !document->frame()) { 1754 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1755 return String(); 1756 } 1757 1758 return document->frame()->trackedRepaintRectsAsText(); 1759 } 1760 1761 PassRefPtrWillBeRawPtr<ClientRectList> Internals::repaintRects(Element* element, ExceptionState& exceptionState) const 1762 { 1763 if (!element) { 1764 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 1765 return nullptr; 1766 } 1767 1768 element->document().frame()->view()->updateLayoutAndStyleForPainting(); 1769 1770 if (RenderLayer* layer = getRenderLayerForElement(element, exceptionState)) { 1771 if (layer->compositingState() == PaintsIntoOwnBacking) { 1772 OwnPtr<Vector<FloatRect> > rects = layer->collectTrackedRepaintRects(); 1773 ASSERT(rects.get()); 1774 Vector<FloatQuad> quads(rects->size()); 1775 for (size_t i = 0; i < rects->size(); ++i) 1776 quads[i] = FloatRect(rects->at(i)); 1777 return ClientRectList::create(quads); 1778 } 1779 } 1780 1781 exceptionState.throwDOMException(InvalidAccessError, "The provided element is not composited."); 1782 return nullptr; 1783 } 1784 1785 String Internals::scrollingStateTreeAsText(Document* document, ExceptionState& exceptionState) const 1786 { 1787 return String(); 1788 } 1789 1790 String Internals::mainThreadScrollingReasons(Document* document, ExceptionState& exceptionState) const 1791 { 1792 if (!document || !document->frame()) { 1793 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1794 return String(); 1795 } 1796 1797 document->frame()->view()->updateLayoutAndStyleForPainting(); 1798 1799 Page* page = document->page(); 1800 if (!page) 1801 return String(); 1802 1803 return page->mainThreadScrollingReasonsAsText(); 1804 } 1805 1806 PassRefPtrWillBeRawPtr<ClientRectList> Internals::nonFastScrollableRects(Document* document, ExceptionState& exceptionState) const 1807 { 1808 if (!document || !document->frame()) { 1809 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 1810 return nullptr; 1811 } 1812 1813 Page* page = document->page(); 1814 if (!page) 1815 return nullptr; 1816 1817 return page->nonFastScrollableRects(document->frame()); 1818 } 1819 1820 void Internals::garbageCollectDocumentResources(Document* document, ExceptionState& exceptionState) const 1821 { 1822 if (!document) { 1823 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 1824 return; 1825 } 1826 ResourceFetcher* fetcher = document->fetcher(); 1827 if (!fetcher) 1828 return; 1829 fetcher->garbageCollectDocumentResources(); 1830 } 1831 1832 void Internals::evictAllResources() const 1833 { 1834 memoryCache()->evictResources(); 1835 } 1836 1837 void Internals::allowRoundingHacks() const 1838 { 1839 TextRun::setAllowsRoundingHacks(true); 1840 } 1841 1842 String Internals::counterValue(Element* element) 1843 { 1844 if (!element) 1845 return String(); 1846 1847 return counterValueForElement(element); 1848 } 1849 1850 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight) 1851 { 1852 if (!element) 1853 return 0; 1854 1855 return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight)); 1856 } 1857 1858 Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const 1859 { 1860 Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask); 1861 Vector<String> array; 1862 1863 Vector<IconURL>::const_iterator iter(iconURLs.begin()); 1864 for (; iter != iconURLs.end(); ++iter) 1865 array.append(iter->m_iconURL.string()); 1866 1867 return array; 1868 } 1869 1870 Vector<String> Internals::shortcutIconURLs(Document* document) const 1871 { 1872 return iconURLs(document, Favicon); 1873 } 1874 1875 Vector<String> Internals::allIconURLs(Document* document) const 1876 { 1877 return iconURLs(document, Favicon | TouchIcon | TouchPrecomposedIcon); 1878 } 1879 1880 int Internals::numberOfPages(float pageWidth, float pageHeight) 1881 { 1882 if (!frame()) 1883 return -1; 1884 1885 return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight)); 1886 } 1887 1888 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionState& exceptionState) const 1889 { 1890 if (!frame()) { 1891 exceptionState.throwDOMException(InvalidAccessError, "No frame is available."); 1892 return String(); 1893 } 1894 1895 return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber); 1896 } 1897 1898 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionState& exceptionState) const 1899 { 1900 if (!frame()) { 1901 exceptionState.throwDOMException(InvalidAccessError, "No frame is available."); 1902 return String(); 1903 } 1904 1905 return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft); 1906 } 1907 1908 void Internals::setDeviceScaleFactor(float scaleFactor, ExceptionState& exceptionState) 1909 { 1910 Document* document = contextDocument(); 1911 if (!document || !document->page()) { 1912 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "No context document can be obtained."); 1913 return; 1914 } 1915 Page* page = document->page(); 1916 page->setDeviceScaleFactor(scaleFactor); 1917 } 1918 1919 void Internals::setIsCursorVisible(Document* document, bool isVisible, ExceptionState& exceptionState) 1920 { 1921 if (!document || !document->page()) { 1922 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "No context document can be obtained."); 1923 return; 1924 } 1925 document->page()->setIsCursorVisible(isVisible); 1926 } 1927 1928 void Internals::webkitWillEnterFullScreenForElement(Document* document, Element* element) 1929 { 1930 if (!document) 1931 return; 1932 FullscreenElementStack::from(*document).webkitWillEnterFullScreenForElement(element); 1933 } 1934 1935 void Internals::webkitDidEnterFullScreenForElement(Document* document, Element* element) 1936 { 1937 if (!document) 1938 return; 1939 FullscreenElementStack::from(*document).webkitDidEnterFullScreenForElement(element); 1940 } 1941 1942 void Internals::webkitWillExitFullScreenForElement(Document* document, Element* element) 1943 { 1944 if (!document) 1945 return; 1946 FullscreenElementStack::from(*document).webkitWillExitFullScreenForElement(element); 1947 } 1948 1949 void Internals::webkitDidExitFullScreenForElement(Document* document, Element* element) 1950 { 1951 if (!document) 1952 return; 1953 FullscreenElementStack::from(*document).webkitDidExitFullScreenForElement(element); 1954 } 1955 1956 void Internals::mediaPlayerRequestFullscreen(HTMLMediaElement* mediaElement) 1957 { 1958 mediaElement->mediaPlayerRequestFullscreen(); 1959 } 1960 1961 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) 1962 { 1963 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme); 1964 } 1965 1966 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme) 1967 { 1968 SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme); 1969 } 1970 1971 PassRefPtrWillBeRawPtr<MallocStatistics> Internals::mallocStatistics() const 1972 { 1973 return MallocStatistics::create(); 1974 } 1975 1976 PassRefPtrWillBeRawPtr<TypeConversions> Internals::typeConversions() const 1977 { 1978 return TypeConversions::create(); 1979 } 1980 1981 Vector<String> Internals::getReferencedFilePaths() const 1982 { 1983 return frame()->loader().currentItem()->getReferencedFilePaths(); 1984 } 1985 1986 void Internals::startTrackingRepaints(Document* document, ExceptionState& exceptionState) 1987 { 1988 if (!document || !document->view()) { 1989 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's view cannot be retrieved." : "The document provided is invalid."); 1990 return; 1991 } 1992 1993 FrameView* frameView = document->view(); 1994 frameView->updateLayoutAndStyleForPainting(); 1995 frameView->setTracksPaintInvalidations(true); 1996 } 1997 1998 void Internals::stopTrackingRepaints(Document* document, ExceptionState& exceptionState) 1999 { 2000 if (!document || !document->view()) { 2001 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's view cannot be retrieved." : "The document provided is invalid."); 2002 return; 2003 } 2004 2005 FrameView* frameView = document->view(); 2006 frameView->updateLayoutAndStyleForPainting(); 2007 frameView->setTracksPaintInvalidations(false); 2008 } 2009 2010 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionState& exceptionState) 2011 { 2012 updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(0, exceptionState); 2013 } 2014 2015 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionState& exceptionState) 2016 { 2017 Document* document; 2018 if (!node) { 2019 document = contextDocument(); 2020 } else if (node->isDocumentNode()) { 2021 document = toDocument(node); 2022 } else if (isHTMLIFrameElement(*node)) { 2023 document = toHTMLIFrameElement(*node).contentDocument(); 2024 } else { 2025 exceptionState.throwTypeError("The node provided is neither a document nor an IFrame."); 2026 return; 2027 } 2028 document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously); 2029 } 2030 2031 void Internals::forceFullRepaint(Document* document, ExceptionState& exceptionState) 2032 { 2033 if (!document || !document->view()) { 2034 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's view cannot be retrieved." : "The document provided is invalid."); 2035 return; 2036 } 2037 2038 if (RenderView *renderView = document->renderView()) 2039 renderView->repaintViewAndCompositedLayers(); 2040 } 2041 2042 PassRefPtrWillBeRawPtr<ClientRectList> Internals::draggableRegions(Document* document, ExceptionState& exceptionState) 2043 { 2044 return annotatedRegions(document, true, exceptionState); 2045 } 2046 2047 PassRefPtrWillBeRawPtr<ClientRectList> Internals::nonDraggableRegions(Document* document, ExceptionState& exceptionState) 2048 { 2049 return annotatedRegions(document, false, exceptionState); 2050 } 2051 2052 PassRefPtrWillBeRawPtr<ClientRectList> Internals::annotatedRegions(Document* document, bool draggable, ExceptionState& exceptionState) 2053 { 2054 if (!document || !document->view()) { 2055 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's view cannot be retrieved." : "The document provided is invalid."); 2056 return ClientRectList::create(); 2057 } 2058 2059 document->updateLayout(); 2060 document->view()->updateAnnotatedRegions(); 2061 Vector<AnnotatedRegionValue> regions = document->annotatedRegions(); 2062 2063 Vector<FloatQuad> quads; 2064 for (size_t i = 0; i < regions.size(); ++i) { 2065 if (regions[i].draggable == draggable) 2066 quads.append(FloatQuad(regions[i].bounds)); 2067 } 2068 return ClientRectList::create(quads); 2069 } 2070 2071 static const char* cursorTypeToString(Cursor::Type cursorType) 2072 { 2073 switch (cursorType) { 2074 case Cursor::Pointer: return "Pointer"; 2075 case Cursor::Cross: return "Cross"; 2076 case Cursor::Hand: return "Hand"; 2077 case Cursor::IBeam: return "IBeam"; 2078 case Cursor::Wait: return "Wait"; 2079 case Cursor::Help: return "Help"; 2080 case Cursor::EastResize: return "EastResize"; 2081 case Cursor::NorthResize: return "NorthResize"; 2082 case Cursor::NorthEastResize: return "NorthEastResize"; 2083 case Cursor::NorthWestResize: return "NorthWestResize"; 2084 case Cursor::SouthResize: return "SouthResize"; 2085 case Cursor::SouthEastResize: return "SouthEastResize"; 2086 case Cursor::SouthWestResize: return "SouthWestResize"; 2087 case Cursor::WestResize: return "WestResize"; 2088 case Cursor::NorthSouthResize: return "NorthSouthResize"; 2089 case Cursor::EastWestResize: return "EastWestResize"; 2090 case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize"; 2091 case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize"; 2092 case Cursor::ColumnResize: return "ColumnResize"; 2093 case Cursor::RowResize: return "RowResize"; 2094 case Cursor::MiddlePanning: return "MiddlePanning"; 2095 case Cursor::EastPanning: return "EastPanning"; 2096 case Cursor::NorthPanning: return "NorthPanning"; 2097 case Cursor::NorthEastPanning: return "NorthEastPanning"; 2098 case Cursor::NorthWestPanning: return "NorthWestPanning"; 2099 case Cursor::SouthPanning: return "SouthPanning"; 2100 case Cursor::SouthEastPanning: return "SouthEastPanning"; 2101 case Cursor::SouthWestPanning: return "SouthWestPanning"; 2102 case Cursor::WestPanning: return "WestPanning"; 2103 case Cursor::Move: return "Move"; 2104 case Cursor::VerticalText: return "VerticalText"; 2105 case Cursor::Cell: return "Cell"; 2106 case Cursor::ContextMenu: return "ContextMenu"; 2107 case Cursor::Alias: return "Alias"; 2108 case Cursor::Progress: return "Progress"; 2109 case Cursor::NoDrop: return "NoDrop"; 2110 case Cursor::Copy: return "Copy"; 2111 case Cursor::None: return "None"; 2112 case Cursor::NotAllowed: return "NotAllowed"; 2113 case Cursor::ZoomIn: return "ZoomIn"; 2114 case Cursor::ZoomOut: return "ZoomOut"; 2115 case Cursor::Grab: return "Grab"; 2116 case Cursor::Grabbing: return "Grabbing"; 2117 case Cursor::Custom: return "Custom"; 2118 } 2119 2120 ASSERT_NOT_REACHED(); 2121 return "UNKNOWN"; 2122 } 2123 2124 String Internals::getCurrentCursorInfo(Document* document, ExceptionState& exceptionState) 2125 { 2126 if (!document || !document->frame()) { 2127 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "The document provided is invalid."); 2128 return String(); 2129 } 2130 2131 Cursor cursor = document->frame()->eventHandler().currentMouseCursor(); 2132 2133 StringBuilder result; 2134 result.append("type="); 2135 result.append(cursorTypeToString(cursor.type())); 2136 result.append(" hotSpot="); 2137 result.appendNumber(cursor.hotSpot().x()); 2138 result.append(","); 2139 result.appendNumber(cursor.hotSpot().y()); 2140 if (cursor.image()) { 2141 IntSize size = cursor.image()->size(); 2142 result.append(" image="); 2143 result.appendNumber(size.width()); 2144 result.append("x"); 2145 result.appendNumber(size.height()); 2146 } 2147 if (cursor.imageScaleFactor() != 1) { 2148 result.append(" scale="); 2149 NumberToStringBuffer buffer; 2150 result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true)); 2151 } 2152 2153 return result.toString(); 2154 } 2155 2156 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const 2157 { 2158 String stringValue = value->toWireString(); 2159 RefPtr<ArrayBuffer> buffer = ArrayBuffer::createUninitialized(stringValue.length(), sizeof(UChar)); 2160 stringValue.copyTo(static_cast<UChar*>(buffer->data()), 0, stringValue.length()); 2161 return buffer.release(); 2162 } 2163 2164 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const 2165 { 2166 String value(static_cast<const UChar*>(buffer->data()), buffer->byteLength() / sizeof(UChar)); 2167 return SerializedScriptValue::createFromWire(value); 2168 } 2169 2170 void Internals::forceReload(bool endToEnd) 2171 { 2172 frame()->loader().reload(endToEnd ? EndToEndReload : NormalReload); 2173 } 2174 2175 PassRefPtrWillBeRawPtr<ClientRect> Internals::selectionBounds(ExceptionState& exceptionState) 2176 { 2177 Document* document = contextDocument(); 2178 if (!document || !document->frame()) { 2179 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "No context document can be obtained."); 2180 return nullptr; 2181 } 2182 2183 return ClientRect::create(document->frame()->selection().bounds()); 2184 } 2185 2186 String Internals::markerTextForListItem(Element* element, ExceptionState& exceptionState) 2187 { 2188 if (!element) { 2189 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 2190 return String(); 2191 } 2192 return WebCore::markerTextForListItem(element); 2193 } 2194 2195 String Internals::getImageSourceURL(Element* element, ExceptionState& exceptionState) 2196 { 2197 if (!element) { 2198 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 2199 return String(); 2200 } 2201 return element->imageSourceURL(); 2202 } 2203 2204 String Internals::baseURL(Document* document, ExceptionState& exceptionState) 2205 { 2206 if (!document) { 2207 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 2208 return String(); 2209 } 2210 2211 return document->baseURL().string(); 2212 } 2213 2214 bool Internals::isSelectPopupVisible(Node* node) 2215 { 2216 ASSERT(node); 2217 if (!isHTMLSelectElement(*node)) 2218 return false; 2219 2220 HTMLSelectElement& select = toHTMLSelectElement(*node); 2221 2222 RenderObject* renderer = select.renderer(); 2223 if (!renderer || !renderer->isMenuList()) 2224 return false; 2225 2226 RenderMenuList* menuList = toRenderMenuList(renderer); 2227 return menuList->popupIsVisible(); 2228 } 2229 2230 bool Internals::loseSharedGraphicsContext3D() 2231 { 2232 OwnPtr<blink::WebGraphicsContext3DProvider> sharedProvider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); 2233 if (!sharedProvider) 2234 return false; 2235 blink::WebGraphicsContext3D* sharedContext = sharedProvider->context3d(); 2236 sharedContext->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_EXT, GL_INNOCENT_CONTEXT_RESET_EXT); 2237 // To prevent tests that call loseSharedGraphicsContext3D from being 2238 // flaky, we call finish so that the context is guaranteed to be lost 2239 // synchronously (i.e. before returning). 2240 sharedContext->finish(); 2241 return true; 2242 } 2243 2244 void Internals::forceCompositingUpdate(Document* document, ExceptionState& exceptionState) 2245 { 2246 // Hit when running content_shell with --expose-internals-for-testing. 2247 DisableCompositingQueryAsserts disabler; 2248 2249 if (!document || !document->renderView()) { 2250 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's render view cannot be retrieved." : "The document provided is invalid."); 2251 return; 2252 } 2253 2254 document->frame()->view()->updateLayoutAndStyleForPainting(); 2255 } 2256 2257 void Internals::setZoomFactor(float factor) 2258 { 2259 frame()->setPageZoomFactor(factor); 2260 } 2261 2262 void Internals::setShouldRevealPassword(Element* element, bool reveal, ExceptionState& exceptionState) 2263 { 2264 if (!isHTMLInputElement(element)) { 2265 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::argumentNullOrIncorrectType(1, "Element")); 2266 return; 2267 } 2268 2269 return toHTMLInputElement(*element).setShouldRevealPassword(reveal); 2270 } 2271 2272 namespace { 2273 2274 class AddOneFunction : public ScriptFunction { 2275 public: 2276 static PassOwnPtr<ScriptFunction> create(ExecutionContext* context) 2277 { 2278 return adoptPtr(new AddOneFunction(toIsolate(context))); 2279 } 2280 2281 private: 2282 AddOneFunction(v8::Isolate* isolate) 2283 : ScriptFunction(isolate) 2284 { 2285 } 2286 2287 virtual ScriptValue call(ScriptValue value) OVERRIDE 2288 { 2289 v8::Local<v8::Value> v8Value = value.v8Value(); 2290 ASSERT(v8Value->IsNumber()); 2291 int intValue = v8Value.As<v8::Integer>()->Value(); 2292 ScriptValue result = ScriptValue(ScriptState::current(isolate()), v8::Integer::New(isolate(), intValue + 1)); 2293 return result; 2294 } 2295 }; 2296 2297 } // namespace 2298 2299 ScriptPromise Internals::createPromise(ScriptState* scriptState) 2300 { 2301 return ScriptPromiseResolver::create(scriptState)->promise(); 2302 } 2303 2304 ScriptPromise Internals::createResolvedPromise(ScriptState* scriptState, ScriptValue value) 2305 { 2306 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); 2307 ScriptPromise promise = resolver->promise(); 2308 resolver->resolve(value); 2309 return promise; 2310 } 2311 2312 ScriptPromise Internals::createRejectedPromise(ScriptState* scriptState, ScriptValue value) 2313 { 2314 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); 2315 ScriptPromise promise = resolver->promise(); 2316 resolver->reject(value); 2317 return promise; 2318 } 2319 2320 ScriptPromise Internals::addOneToPromise(ExecutionContext* context, ScriptPromise promise) 2321 { 2322 return promise.then(AddOneFunction::create(context)); 2323 } 2324 2325 void Internals::trace(Visitor* visitor) 2326 { 2327 visitor->trace(m_runtimeFlags); 2328 visitor->trace(m_profilers); 2329 } 2330 2331 void Internals::setValueForUser(Element* element, const String& value) 2332 { 2333 toHTMLInputElement(element)->setValueForUser(value); 2334 } 2335 2336 String Internals::textSurroundingNode(Node* node, int x, int y, unsigned long maxLength) 2337 { 2338 if (!node) 2339 return String(); 2340 blink::WebPoint point(x, y); 2341 SurroundingText surroundingText(VisiblePosition(node->renderer()->positionForPoint(static_cast<IntPoint>(point))).deepEquivalent().parentAnchoredEquivalent(), maxLength); 2342 return surroundingText.content(); 2343 } 2344 2345 void Internals::setFocused(bool focused) 2346 { 2347 frame()->page()->focusController().setFocused(focused); 2348 } 2349 2350 bool Internals::ignoreLayoutWithPendingStylesheets(Document* document, ExceptionState& exceptionState) 2351 { 2352 if (!document) { 2353 exceptionState.throwDOMException(InvalidAccessError, "No context document is available."); 2354 return false; 2355 } 2356 2357 return document->ignoreLayoutWithPendingStylesheets(); 2358 } 2359 2360 void Internals::setNetworkStateNotifierTestOnly(bool testOnly) 2361 { 2362 networkStateNotifier().setTestUpdatesOnly(testOnly); 2363 } 2364 2365 void Internals::setNetworkConnectionInfo(const String& type, ExceptionState& exceptionState) 2366 { 2367 blink::WebConnectionType webtype; 2368 if (type == "cellular") { 2369 webtype = blink::ConnectionTypeCellular; 2370 } else if (type == "bluetooth") { 2371 webtype = blink::ConnectionTypeBluetooth; 2372 } else if (type == "ethernet") { 2373 webtype = blink::ConnectionTypeEthernet; 2374 } else if (type == "wifi") { 2375 webtype = blink::ConnectionTypeWifi; 2376 } else if (type == "other") { 2377 webtype = blink::ConnectionTypeOther; 2378 } else if (type == "none") { 2379 webtype = blink::ConnectionTypeNone; 2380 } else { 2381 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::failedToEnumerate("connection type", type)); 2382 return; 2383 } 2384 networkStateNotifier().setWebConnectionTypeForTest(webtype); 2385 } 2386 2387 } // namespace WebCore 2388