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