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