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 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 "AXObjectCache.h" 31#include "AnimationController.h" 32#include "ApplicationCacheStorage.h" 33#include "BackForwardController.h" 34#include "CachedResourceLoader.h" 35#include "Chrome.h" 36#include "ChromeClient.h" 37#include "ClientRect.h" 38#include "ClientRectList.h" 39#include "ContentDistributor.h" 40#include "Cursor.h" 41#include "DOMStringList.h" 42#include "DOMWindow.h" 43#include "Document.h" 44#include "DocumentMarker.h" 45#include "DocumentMarkerController.h" 46#include "Editor.h" 47#include "Element.h" 48#include "EventHandler.h" 49#include "ExceptionCode.h" 50#include "FormController.h" 51#include "FrameLoader.h" 52#include "FrameView.h" 53#include "HTMLIFrameElement.h" 54#include "HTMLInputElement.h" 55#include "HTMLNames.h" 56#include "HTMLPlugInElement.h" 57#include "HTMLSelectElement.h" 58#include "HTMLTextAreaElement.h" 59#include "HistoryController.h" 60#include "HistoryItem.h" 61#include "InspectorClient.h" 62#include "InspectorController.h" 63#include "InspectorForwarding.h" 64#include "InspectorFrontendClientLocal.h" 65#include "InspectorInstrumentation.h" 66#include "InspectorOverlay.h" 67#include "InstrumentingAgents.h" 68#include "IntRect.h" 69#include "InternalSettings.h" 70#include "Language.h" 71#include "MainFrame.h" 72#include "MallocStatistics.h" 73#include "MediaPlayer.h" 74#include "MediaSessionManager.h" 75#include "MemoryCache.h" 76#include "MemoryInfo.h" 77#include "Page.h" 78#include "PrintContext.h" 79#include "PseudoElement.h" 80#include "Range.h" 81#include "RenderEmbeddedObject.h" 82#include "RenderMenuList.h" 83#include "RenderTreeAsText.h" 84#include "RenderView.h" 85#include "RuntimeEnabledFeatures.h" 86#include "SchemeRegistry.h" 87#include "ScrollingCoordinator.h" 88#include "SerializedScriptValue.h" 89#include "Settings.h" 90#include "ShadowRoot.h" 91#include "SourceBuffer.h" 92#include "SpellChecker.h" 93#include "StaticNodeList.h" 94#include "StyleSheetContents.h" 95#include "TextIterator.h" 96#include "TreeScope.h" 97#include "TypeConversions.h" 98#include "ViewportArguments.h" 99#include "WebConsoleAgent.h" 100#include "WorkerThread.h" 101#include <bytecode/CodeBlock.h> 102#include <inspector/InspectorAgentBase.h> 103#include <inspector/InspectorValues.h> 104#include <runtime/JSCInlines.h> 105#include <runtime/JSCJSValue.h> 106#include <wtf/text/CString.h> 107#include <wtf/text/StringBuffer.h> 108 109#if ENABLE(INPUT_TYPE_COLOR) 110#include "ColorChooser.h" 111#endif 112 113#if ENABLE(BATTERY_STATUS) 114#include "BatteryController.h" 115#endif 116 117#if ENABLE(PROXIMITY_EVENTS) 118#include "DeviceProximityController.h" 119#endif 120 121#if ENABLE(MOUSE_CURSOR_SCALE) 122#include <wtf/dtoa.h> 123#endif 124 125#if ENABLE(ENCRYPTED_MEDIA_V2) 126#include "CDM.h" 127#include "MockCDM.h" 128#endif 129 130#if ENABLE(VIDEO_TRACK) 131#include "CaptionUserPreferences.h" 132#include "PageGroup.h" 133#endif 134 135#if ENABLE(VIDEO) 136#include "HTMLMediaElement.h" 137#include "TimeRanges.h" 138#endif 139 140#if ENABLE(SPEECH_SYNTHESIS) 141#include "DOMWindowSpeechSynthesis.h" 142#include "PlatformSpeechSynthesizerMock.h" 143#include "SpeechSynthesis.h" 144#endif 145 146#if ENABLE(VIBRATION) 147#include "Vibration.h" 148#endif 149 150#if ENABLE(MEDIA_STREAM) 151#include "MockMediaStreamCenter.h" 152#include "RTCPeerConnection.h" 153#include "RTCPeerConnectionHandlerMock.h" 154#include "UserMediaClientMock.h" 155#endif 156 157#if ENABLE(MEDIA_SOURCE) 158#include "MockMediaPlayerMediaSource.h" 159#endif 160 161using JSC::CodeBlock; 162using JSC::FunctionExecutable; 163using JSC::JSFunction; 164using JSC::JSValue; 165using JSC::ScriptExecutable; 166using JSC::StackVisitor; 167 168using namespace Inspector; 169 170namespace WebCore { 171 172using namespace HTMLNames; 173 174#if ENABLE(INSPECTOR) 175class InspectorFrontendClientDummy : public InspectorFrontendClientLocal { 176public: 177 InspectorFrontendClientDummy(InspectorController*, Page*); 178 virtual ~InspectorFrontendClientDummy() { } 179 virtual void attachWindow(DockSide) override { } 180 virtual void detachWindow() override { } 181 182 virtual String localizedStringsURL() override { return String(); } 183 184 virtual void bringToFront() override { } 185 virtual void closeWindow() override { } 186 187 virtual void inspectedURLChanged(const String&) override { } 188 189protected: 190 virtual void setAttachedWindowHeight(unsigned) override { } 191 virtual void setAttachedWindowWidth(unsigned) override { } 192 virtual void setToolbarHeight(unsigned) override { } 193}; 194 195InspectorFrontendClientDummy::InspectorFrontendClientDummy(InspectorController* controller, Page* page) 196 : InspectorFrontendClientLocal(controller, page, std::make_unique<InspectorFrontendClientLocal::Settings>()) 197{ 198} 199 200class InspectorFrontendChannelDummy : public InspectorFrontendChannel { 201public: 202 explicit InspectorFrontendChannelDummy(Page*); 203 virtual ~InspectorFrontendChannelDummy() { } 204 virtual bool sendMessageToFrontend(const String& message) override; 205 206private: 207 Page* m_frontendPage; 208}; 209 210InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page) 211 : m_frontendPage(page) 212{ 213} 214 215bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message) 216{ 217 return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message); 218} 219#endif // ENABLE(INSPECTOR) 220 221static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result) 222{ 223 if (markerType.isEmpty() || equalIgnoringCase(markerType, "all")) 224 result = DocumentMarker::AllMarkers(); 225 else if (equalIgnoringCase(markerType, "Spelling")) 226 result = DocumentMarker::Spelling; 227 else if (equalIgnoringCase(markerType, "Grammar")) 228 result = DocumentMarker::Grammar; 229 else if (equalIgnoringCase(markerType, "TextMatch")) 230 result = DocumentMarker::TextMatch; 231 else if (equalIgnoringCase(markerType, "Replacement")) 232 result = DocumentMarker::Replacement; 233 else if (equalIgnoringCase(markerType, "CorrectionIndicator")) 234 result = DocumentMarker::CorrectionIndicator; 235 else if (equalIgnoringCase(markerType, "RejectedCorrection")) 236 result = DocumentMarker::RejectedCorrection; 237 else if (equalIgnoringCase(markerType, "Autocorrected")) 238 result = DocumentMarker::Autocorrected; 239 else if (equalIgnoringCase(markerType, "SpellCheckingExemption")) 240 result = DocumentMarker::SpellCheckingExemption; 241 else if (equalIgnoringCase(markerType, "DeletedAutocorrection")) 242 result = DocumentMarker::DeletedAutocorrection; 243 else if (equalIgnoringCase(markerType, "DictationAlternatives")) 244 result = DocumentMarker::DictationAlternatives; 245#if ENABLE(TELEPHONE_NUMBER_DETECTION) 246 else if (equalIgnoringCase(markerType, "TelephoneNumber")) 247 result = DocumentMarker::TelephoneNumber; 248#endif 249 else 250 return false; 251 252 return true; 253} 254 255const char* Internals::internalsId = "internals"; 256 257PassRefPtr<Internals> Internals::create(Document* document) 258{ 259 return adoptRef(new Internals(document)); 260} 261 262Internals::~Internals() 263{ 264} 265 266void Internals::resetToConsistentState(Page* page) 267{ 268 ASSERT(page); 269 270 page->setPageScaleFactor(1, IntPoint(0, 0)); 271 page->setPagination(Pagination()); 272 273 FrameView* mainFrameView = page->mainFrame().view(); 274 if (mainFrameView) { 275 mainFrameView->setHeaderHeight(0); 276 mainFrameView->setFooterHeight(0); 277 page->setTopContentInset(0); 278 } 279 280 TextRun::setAllowsRoundingHacks(false); 281 WebCore::overrideUserPreferredLanguages(Vector<String>()); 282 WebCore::Settings::setUsesOverlayScrollbars(false); 283#if ENABLE(INSPECTOR) 284 page->inspectorController().setProfilerEnabled(false); 285#endif 286#if ENABLE(VIDEO_TRACK) 287 page->group().captionPreferences()->setCaptionsStyleSheetOverride(emptyString()); 288 page->group().captionPreferences()->setTestingMode(false); 289#endif 290 if (!page->mainFrame().editor().isContinuousSpellCheckingEnabled()) 291 page->mainFrame().editor().toggleContinuousSpellChecking(); 292 if (page->mainFrame().editor().isOverwriteModeEnabled()) 293 page->mainFrame().editor().toggleOverwriteModeEnabled(); 294 cacheStorage().setDefaultOriginQuota(ApplicationCacheStorage::noQuota()); 295#if ENABLE(VIDEO) 296 MediaSessionManager::sharedManager().resetRestrictions(); 297#endif 298#if HAVE(ACCESSIBILITY) 299 AXObjectCache::setEnhancedUserInterfaceAccessibility(false); 300 AXObjectCache::disableAccessibility(); 301#endif 302} 303 304Internals::Internals(Document* document) 305 : ContextDestructionObserver(document) 306{ 307#if ENABLE(VIDEO_TRACK) 308 if (document && document->page()) 309 document->page()->group().captionPreferences()->setTestingMode(true); 310#endif 311 312#if ENABLE(MEDIA_STREAM) 313 MockMediaStreamCenter::registerMockMediaStreamCenter(); 314 enableMockRTCPeerConnectionHandler(); 315 WebCore::provideUserMediaTo(document->page(), new UserMediaClientMock()); 316#endif 317} 318 319Document* Internals::contextDocument() const 320{ 321 return toDocument(scriptExecutionContext()); 322} 323 324Frame* Internals::frame() const 325{ 326 if (!contextDocument()) 327 return 0; 328 return contextDocument()->frame(); 329} 330 331InternalSettings* Internals::settings() const 332{ 333 Document* document = contextDocument(); 334 if (!document) 335 return 0; 336 Page* page = document->page(); 337 if (!page) 338 return 0; 339 return InternalSettings::from(page); 340} 341 342unsigned Internals::workerThreadCount() const 343{ 344 return WorkerThread::workerThreadCount(); 345} 346 347String Internals::address(Node* node) 348{ 349 char buf[32]; 350 sprintf(buf, "%p", node); 351 352 return String(buf); 353} 354 355bool Internals::isPreloaded(const String& url) 356{ 357 Document* document = contextDocument(); 358 return document->cachedResourceLoader()->isPreloaded(url); 359} 360 361bool Internals::isLoadingFromMemoryCache(const String& url) 362{ 363 if (!contextDocument() || !contextDocument()->page()) 364 return false; 365 CachedResource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url), contextDocument()->page()->sessionID()); 366 return resource && resource->status() == CachedResource::Cached; 367} 368 369 370Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec) 371{ 372 if (!node) { 373 ec = INVALID_ACCESS_ERR; 374 return nullptr; 375 } 376 377 return &node->treeScope().rootNode(); 378} 379 380Node* Internals::parentTreeScope(Node* node, ExceptionCode& ec) 381{ 382 if (!node) { 383 ec = INVALID_ACCESS_ERR; 384 return nullptr; 385 } 386 const TreeScope* parentTreeScope = node->treeScope().parentTreeScope(); 387 return parentTreeScope ? &parentTreeScope->rootNode() : nullptr; 388} 389 390unsigned Internals::lastSpatialNavigationCandidateCount(ExceptionCode& ec) const 391{ 392 if (!contextDocument() || !contextDocument()->page()) { 393 ec = INVALID_ACCESS_ERR; 394 return 0; 395 } 396 397 return contextDocument()->page()->lastSpatialNavigationCandidateCount(); 398} 399 400unsigned Internals::numberOfActiveAnimations() const 401{ 402 return frame()->animation().numberOfActiveAnimations(frame()->document()); 403} 404 405bool Internals::animationsAreSuspended(ExceptionCode& ec) const 406{ 407 Document* document = contextDocument(); 408 if (!document || !document->frame()) { 409 ec = INVALID_ACCESS_ERR; 410 return false; 411 } 412 413 return document->frame()->animation().isSuspended(); 414} 415 416void Internals::suspendAnimations(ExceptionCode& ec) const 417{ 418 Document* document = contextDocument(); 419 if (!document || !document->frame()) { 420 ec = INVALID_ACCESS_ERR; 421 return; 422 } 423 424 document->frame()->animation().suspendAnimations(); 425} 426 427void Internals::resumeAnimations(ExceptionCode& ec) const 428{ 429 Document* document = contextDocument(); 430 if (!document || !document->frame()) { 431 ec = INVALID_ACCESS_ERR; 432 return; 433 } 434 435 document->frame()->animation().resumeAnimations(); 436} 437 438bool Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element* element, ExceptionCode& ec) 439{ 440 if (!element || pauseTime < 0) { 441 ec = INVALID_ACCESS_ERR; 442 return false; 443 } 444 return frame()->animation().pauseAnimationAtTime(element->renderer(), AtomicString(animationName), pauseTime); 445} 446 447bool Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec) 448{ 449 if (!element || pauseTime < 0) { 450 ec = INVALID_ACCESS_ERR; 451 return false; 452 } 453 454 if (pseudoId != "before" && pseudoId != "after") { 455 ec = INVALID_ACCESS_ERR; 456 return false; 457 } 458 459 PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement(); 460 if (!pseudoElement) { 461 ec = INVALID_ACCESS_ERR; 462 return false; 463 } 464 465 return frame()->animation().pauseAnimationAtTime(pseudoElement->renderer(), AtomicString(animationName), pauseTime); 466} 467 468bool Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element* element, ExceptionCode& ec) 469{ 470 if (!element || pauseTime < 0) { 471 ec = INVALID_ACCESS_ERR; 472 return false; 473 } 474 return frame()->animation().pauseTransitionAtTime(element->renderer(), propertyName, pauseTime); 475} 476 477bool Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec) 478{ 479 if (!element || pauseTime < 0) { 480 ec = INVALID_ACCESS_ERR; 481 return false; 482 } 483 484 if (pseudoId != "before" && pseudoId != "after") { 485 ec = INVALID_ACCESS_ERR; 486 return false; 487 } 488 489 PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement(); 490 if (!pseudoElement) { 491 ec = INVALID_ACCESS_ERR; 492 return false; 493 } 494 495 return frame()->animation().pauseTransitionAtTime(pseudoElement->renderer(), property, pauseTime); 496} 497 498// FIXME: Remove. 499bool Internals::attached(Node* node, ExceptionCode& ec) 500{ 501 if (!node) { 502 ec = INVALID_ACCESS_ERR; 503 return false; 504 } 505 506 return true; 507} 508 509String Internals::elementRenderTreeAsText(Element* element, ExceptionCode& ec) 510{ 511 if (!element) { 512 ec = INVALID_ACCESS_ERR; 513 return String(); 514 } 515 516 element->document().updateStyleIfNeeded(); 517 518 String representation = externalRepresentation(element); 519 if (representation.isEmpty()) { 520 ec = INVALID_ACCESS_ERR; 521 return String(); 522 } 523 524 return representation; 525} 526 527PassRefPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node, ExceptionCode& ec) const 528{ 529 if (!node) { 530 ec = INVALID_ACCESS_ERR; 531 return 0; 532 } 533 534 bool allowVisitedStyle = true; 535 return CSSComputedStyleDeclaration::create(node, allowVisitedStyle); 536} 537 538Node* Internals::ensureShadowRoot(Element* host, ExceptionCode& ec) 539{ 540 if (!host) { 541 ec = INVALID_ACCESS_ERR; 542 return 0; 543 } 544 545 if (ShadowRoot* shadowRoot = host->shadowRoot()) 546 return shadowRoot; 547 548 return host->createShadowRoot(ec).get(); 549} 550 551Node* Internals::createShadowRoot(Element* host, ExceptionCode& ec) 552{ 553 if (!host) { 554 ec = INVALID_ACCESS_ERR; 555 return 0; 556 } 557 return host->createShadowRoot(ec).get(); 558} 559 560Node* Internals::shadowRoot(Element* host, ExceptionCode& ec) 561{ 562 if (!host) { 563 ec = INVALID_ACCESS_ERR; 564 return 0; 565 } 566 return host->shadowRoot(); 567} 568 569String Internals::shadowRootType(const Node* root, ExceptionCode& ec) const 570{ 571 if (!root || !root->isShadowRoot()) { 572 ec = INVALID_ACCESS_ERR; 573 return String(); 574 } 575 576 switch (toShadowRoot(root)->type()) { 577 case ShadowRoot::UserAgentShadowRoot: 578 return String("UserAgentShadowRoot"); 579 default: 580 ASSERT_NOT_REACHED(); 581 return String("Unknown"); 582 } 583} 584 585Element* Internals::includerFor(Node*, ExceptionCode& ec) 586{ 587 ec = INVALID_ACCESS_ERR; 588 return 0; 589} 590 591String Internals::shadowPseudoId(Element* element, ExceptionCode& ec) 592{ 593 if (!element) { 594 ec = INVALID_ACCESS_ERR; 595 return String(); 596 } 597 598 return element->shadowPseudoId().string(); 599} 600 601void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionCode& ec) 602{ 603 if (!element) { 604 ec = INVALID_ACCESS_ERR; 605 return; 606 } 607 608 return element->setPseudo(id); 609} 610 611String Internals::visiblePlaceholder(Element* element) 612{ 613 if (element && isHTMLTextFormControlElement(*element)) { 614 if (toHTMLTextFormControlElement(*element).placeholderShouldBeVisible()) 615 return toHTMLTextFormControlElement(*element).placeholderElement()->textContent(); 616 } 617 618 return String(); 619} 620 621#if ENABLE(INPUT_TYPE_COLOR) 622void Internals::selectColorInColorChooser(Element* element, const String& colorValue) 623{ 624 if (!isHTMLInputElement(element)) 625 return; 626 HTMLInputElement* inputElement = element->toInputElement(); 627 if (!inputElement) 628 return; 629 inputElement->selectColorInColorChooser(Color(colorValue)); 630} 631#endif 632 633Vector<String> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec) 634{ 635 HistoryItem* mainItem = frame()->loader().history().previousItem(); 636 if (!mainItem) { 637 ec = INVALID_ACCESS_ERR; 638 return Vector<String>(); 639 } 640 String uniqueName = frame()->tree().uniqueName(); 641 if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) { 642 ec = INVALID_ACCESS_ERR; 643 return Vector<String>(); 644 } 645 return mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState(); 646} 647 648void Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state, ExceptionCode& ec) 649{ 650 HistoryItem* mainItem = frame()->loader().history().previousItem(); 651 if (!mainItem) { 652 ec = INVALID_ACCESS_ERR; 653 return; 654 } 655 String uniqueName = frame()->tree().uniqueName(); 656 if (mainItem->target() == uniqueName) 657 mainItem->setDocumentState(state); 658 else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName)) 659 subItem->setDocumentState(state); 660 else 661 ec = INVALID_ACCESS_ERR; 662} 663 664#if ENABLE(SPEECH_SYNTHESIS) 665void Internals::enableMockSpeechSynthesizer() 666{ 667 Document* document = contextDocument(); 668 if (!document || !document->domWindow()) 669 return; 670 SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(document->domWindow()); 671 if (!synthesis) 672 return; 673 674 synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis)); 675} 676#endif 677 678#if ENABLE(MEDIA_STREAM) 679void Internals::enableMockRTCPeerConnectionHandler() 680{ 681 RTCPeerConnectionHandler::create = RTCPeerConnectionHandlerMock::create; 682} 683#endif 684 685PassRefPtr<ClientRect> Internals::absoluteCaretBounds(ExceptionCode& ec) 686{ 687 Document* document = contextDocument(); 688 if (!document || !document->frame()) { 689 ec = INVALID_ACCESS_ERR; 690 return ClientRect::create(); 691 } 692 693 return ClientRect::create(document->frame()->selection().absoluteCaretBounds()); 694} 695 696PassRefPtr<ClientRect> Internals::boundingBox(Element* element, ExceptionCode& ec) 697{ 698 if (!element) { 699 ec = INVALID_ACCESS_ERR; 700 return ClientRect::create(); 701 } 702 703 element->document().updateLayoutIgnorePendingStylesheets(); 704 auto renderer = element->renderer(); 705 if (!renderer) 706 return ClientRect::create(); 707 return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms()); 708} 709 710PassRefPtr<ClientRectList> Internals::inspectorHighlightRects(ExceptionCode& ec) 711{ 712#if ENABLE(INSPECTOR) 713 Document* document = contextDocument(); 714 if (!document || !document->page()) { 715 ec = INVALID_ACCESS_ERR; 716 return ClientRectList::create(); 717 } 718 719 Highlight highlight; 720 document->page()->inspectorController().getHighlight(&highlight, InspectorOverlay::CoordinateSystem::View); 721 return ClientRectList::create(highlight.quads); 722#else 723 UNUSED_PARAM(ec); 724 return ClientRectList::create(); 725#endif 726} 727 728String Internals::inspectorHighlightObject(ExceptionCode& ec) 729{ 730#if ENABLE(INSPECTOR) 731 Document* document = contextDocument(); 732 if (!document || !document->page()) { 733 ec = INVALID_ACCESS_ERR; 734 return String(); 735 } 736 RefPtr<InspectorObject> object = document->page()->inspectorController().buildObjectForHighlightedNode(); 737 return object ? object->toJSONString() : String(); 738#else 739 UNUSED_PARAM(ec); 740 return String(); 741#endif 742} 743 744unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec) 745{ 746 if (!node) { 747 ec = INVALID_ACCESS_ERR; 748 return 0; 749 } 750 751 DocumentMarker::MarkerTypes markerTypes = 0; 752 if (!markerTypesFrom(markerType, markerTypes)) { 753 ec = SYNTAX_ERR; 754 return 0; 755 } 756 757 node->document().frame()->editor().updateEditorUINowIfScheduled(); 758 759 return node->document().markers().markersFor(node, markerTypes).size(); 760} 761 762DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionCode& ec) 763{ 764 node->document().updateLayoutIgnorePendingStylesheets(); 765 if (!node) { 766 ec = INVALID_ACCESS_ERR; 767 return 0; 768 } 769 770 DocumentMarker::MarkerTypes markerTypes = 0; 771 if (!markerTypesFrom(markerType, markerTypes)) { 772 ec = SYNTAX_ERR; 773 return 0; 774 } 775 776 node->document().frame()->editor().updateEditorUINowIfScheduled(); 777 778 Vector<DocumentMarker*> markers = node->document().markers().markersFor(node, markerTypes); 779 if (markers.size() <= index) 780 return 0; 781 return markers[index]; 782} 783 784PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec) 785{ 786 DocumentMarker* marker = markerAt(node, markerType, index, ec); 787 if (!marker) 788 return 0; 789 return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset()); 790} 791 792String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec) 793{ 794 DocumentMarker* marker = markerAt(node, markerType, index, ec); 795 if (!marker) 796 return String(); 797 return marker->description(); 798} 799 800void Internals::addTextMatchMarker(const Range* range, bool isActive) 801{ 802 range->ownerDocument().updateLayoutIgnorePendingStylesheets(); 803 range->ownerDocument().markers().addTextMatchMarker(range, isActive); 804} 805 806void Internals::setMarkedTextMatchesAreHighlighted(bool flag, ExceptionCode& ec) 807{ 808 Document* document = contextDocument(); 809 if (!document || !document->frame()) { 810 ec = INVALID_ACCESS_ERR; 811 return; 812 } 813 document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag); 814} 815 816void Internals::setScrollViewPosition(long x, long y, ExceptionCode& ec) 817{ 818 Document* document = contextDocument(); 819 if (!document || !document->view()) { 820 ec = INVALID_ACCESS_ERR; 821 return; 822 } 823 824 FrameView* frameView = document->view(); 825 bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge(); 826 bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed(); 827 828 frameView->setConstrainsScrollingToContentEdge(false); 829 frameView->setScrollbarsSuppressed(false); 830 frameView->setScrollOffsetFromInternals(IntPoint(x, y)); 831 frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue); 832 frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue); 833} 834 835void Internals::setPagination(const String& mode, int gap, int pageLength, ExceptionCode& ec) 836{ 837 Document* document = contextDocument(); 838 if (!document || !document->page()) { 839 ec = INVALID_ACCESS_ERR; 840 return; 841 } 842 Page* page = document->page(); 843 844 Pagination pagination; 845 if (mode == "Unpaginated") 846 pagination.mode = Pagination::Unpaginated; 847 else if (mode == "LeftToRightPaginated") 848 pagination.mode = Pagination::LeftToRightPaginated; 849 else if (mode == "RightToLeftPaginated") 850 pagination.mode = Pagination::RightToLeftPaginated; 851 else if (mode == "TopToBottomPaginated") 852 pagination.mode = Pagination::TopToBottomPaginated; 853 else if (mode == "BottomToTopPaginated") 854 pagination.mode = Pagination::BottomToTopPaginated; 855 else { 856 ec = SYNTAX_ERR; 857 return; 858 } 859 860 pagination.gap = gap; 861 pagination.pageLength = pageLength; 862 page->setPagination(pagination); 863} 864 865String Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionCode& ec) 866{ 867 Document* document = contextDocument(); 868 if (!document || !document->page()) { 869 ec = INVALID_ACCESS_ERR; 870 return String(); 871 } 872 Page* page = document->page(); 873 874 const int defaultLayoutWidthForNonMobilePages = 980; 875 876 ViewportArguments arguments = page->viewportArguments(); 877 ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight)); 878 restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio); 879 restrictScaleFactorToInitialScaleIfNotUserScalable(attributes); 880 881 return "viewport size " + String::number(attributes.layoutSize.width()) + "x" + String::number(attributes.layoutSize.height()) + " scale " + String::number(attributes.initialScale) + " with limits [" + String::number(attributes.minimumScale) + ", " + String::number(attributes.maximumScale) + "] and userScalable " + (attributes.userScalable ? "true" : "false"); 882} 883 884bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec) 885{ 886 if (!textField) { 887 ec = INVALID_ACCESS_ERR; 888 return false; 889 } 890 891 if (HTMLInputElement* inputElement = textField->toInputElement()) 892 return inputElement->lastChangeWasUserEdit(); 893 894 // FIXME: We should be using hasTagName instead but Windows port doesn't link QualifiedNames properly. 895 if (textField->tagName() == "TEXTAREA") 896 return toHTMLTextAreaElement(textField)->lastChangeWasUserEdit(); 897 898 ec = INVALID_NODE_TYPE_ERR; 899 return false; 900} 901 902bool Internals::elementShouldAutoComplete(Element* element, ExceptionCode& ec) 903{ 904 if (!element) { 905 ec = INVALID_ACCESS_ERR; 906 return false; 907 } 908 909 if (HTMLInputElement* inputElement = element->toInputElement()) 910 return inputElement->shouldAutocomplete(); 911 912 ec = INVALID_NODE_TYPE_ERR; 913 return false; 914} 915 916String Internals::suggestedValue(Element* element, ExceptionCode& ec) 917{ 918 if (!element) { 919 ec = INVALID_ACCESS_ERR; 920 return String(); 921 } 922 923 HTMLInputElement* inputElement = element->toInputElement(); 924 if (!inputElement) { 925 ec = INVALID_NODE_TYPE_ERR; 926 return String(); 927 } 928 929 return inputElement->suggestedValue(); 930} 931 932void Internals::setSuggestedValue(Element* element, const String& value, ExceptionCode& ec) 933{ 934 if (!element) { 935 ec = INVALID_ACCESS_ERR; 936 return; 937 } 938 939 HTMLInputElement* inputElement = element->toInputElement(); 940 if (!inputElement) { 941 ec = INVALID_NODE_TYPE_ERR; 942 return; 943 } 944 945 inputElement->setSuggestedValue(value); 946} 947 948void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec) 949{ 950 if (!element) { 951 ec = INVALID_ACCESS_ERR; 952 return; 953 } 954 955 HTMLInputElement* inputElement = element->toInputElement(); 956 if (!inputElement) { 957 ec = INVALID_NODE_TYPE_ERR; 958 return; 959 } 960 961 inputElement->setEditingValue(value); 962} 963 964void Internals::setAutofilled(Element* element, bool enabled, ExceptionCode& ec) 965{ 966 HTMLInputElement* inputElement = element->toInputElement(); 967 if (!inputElement) { 968 ec = INVALID_ACCESS_ERR; 969 return; 970 } 971 inputElement->setAutofilled(enabled); 972} 973 974void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec) 975{ 976 if (!element || !element->document().view()) { 977 ec = INVALID_ACCESS_ERR; 978 return; 979 } 980 FrameView* frameView = element->document().view(); 981 frameView->scrollElementToRect(element, IntRect(x, y, w, h)); 982} 983 984void Internals::paintControlTints(ExceptionCode& ec) 985{ 986 Document* document = contextDocument(); 987 if (!document || !document->view()) { 988 ec = INVALID_ACCESS_ERR; 989 return; 990 } 991 992 FrameView* frameView = document->view(); 993 frameView->paintControlTints(); 994} 995 996PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec) 997{ 998 if (!scope) { 999 ec = INVALID_ACCESS_ERR; 1000 return 0; 1001 } 1002 1003 return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength); 1004} 1005 1006unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec) 1007{ 1008 if (!scope || !range) { 1009 ec = INVALID_ACCESS_ERR; 1010 return 0; 1011 } 1012 1013 size_t location = 0; 1014 size_t unusedLength = 0; 1015 TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength); 1016 return location; 1017} 1018 1019unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec) 1020{ 1021 if (!scope || !range) { 1022 ec = INVALID_ACCESS_ERR; 1023 return 0; 1024 } 1025 1026 size_t unusedLocation = 0; 1027 size_t length = 0; 1028 TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length); 1029 return length; 1030} 1031 1032String Internals::rangeAsText(const Range* range, ExceptionCode& ec) 1033{ 1034 if (!range) { 1035 ec = INVALID_ACCESS_ERR; 1036 return String(); 1037 } 1038 1039 return range->text(); 1040} 1041 1042void Internals::setDelegatesScrolling(bool enabled, ExceptionCode& ec) 1043{ 1044 Document* document = contextDocument(); 1045 // Delegate scrolling is valid only on mainframe's view. 1046 if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame()) { 1047 ec = INVALID_ACCESS_ERR; 1048 return; 1049 } 1050 1051 document->view()->setDelegatesScrolling(enabled); 1052} 1053 1054int Internals::lastSpellCheckRequestSequence(ExceptionCode& ec) 1055{ 1056 Document* document = contextDocument(); 1057 if (!document || !document->frame()) { 1058 ec = INVALID_ACCESS_ERR; 1059 return -1; 1060 } 1061 1062 return document->frame()->editor().spellChecker().lastRequestSequence(); 1063} 1064 1065int Internals::lastSpellCheckProcessedSequence(ExceptionCode& ec) 1066{ 1067 Document* document = contextDocument(); 1068 if (!document || !document->frame()) { 1069 ec = INVALID_ACCESS_ERR; 1070 return -1; 1071 } 1072 1073 return document->frame()->editor().spellChecker().lastProcessedSequence(); 1074} 1075 1076Vector<String> Internals::userPreferredLanguages() const 1077{ 1078 return WebCore::userPreferredLanguages(); 1079} 1080 1081void Internals::setUserPreferredLanguages(const Vector<String>& languages) 1082{ 1083 WebCore::overrideUserPreferredLanguages(languages); 1084} 1085 1086unsigned Internals::wheelEventHandlerCount(ExceptionCode& ec) 1087{ 1088 Document* document = contextDocument(); 1089 if (!document) { 1090 ec = INVALID_ACCESS_ERR; 1091 return 0; 1092 } 1093 1094 return document->wheelEventHandlerCount(); 1095} 1096 1097unsigned Internals::touchEventHandlerCount(ExceptionCode& ec) 1098{ 1099 Document* document = contextDocument(); 1100 if (!document) { 1101 ec = INVALID_ACCESS_ERR; 1102 return 0; 1103 } 1104 1105 const TouchEventTargetSet* touchHandlers = document->touchEventTargets(); 1106 if (!touchHandlers) 1107 return 0; 1108 1109 unsigned count = 0; 1110 for (TouchEventTargetSet::const_iterator iter = touchHandlers->begin(); iter != touchHandlers->end(); ++iter) 1111 count += iter->value; 1112 return count; 1113} 1114 1115// FIXME: Remove the document argument. It is almost always the same as 1116// contextDocument(), with the exception of a few tests that pass a 1117// different document, and could just make the call through another Internals 1118// instance instead. 1119PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding, 1120 unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionCode& ec) const 1121{ 1122 if (!document || !document->frame() || !document->frame()->view()) { 1123 ec = INVALID_ACCESS_ERR; 1124 return 0; 1125 } 1126 1127 Frame* frame = document->frame(); 1128 FrameView* frameView = document->view(); 1129 RenderView* renderView = document->renderView(); 1130 if (!renderView) 1131 return 0; 1132 1133 document->updateLayoutIgnorePendingStylesheets(); 1134 1135 float zoomFactor = frame->pageZoomFactor(); 1136 LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY())); 1137 1138 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active; 1139 if (ignoreClipping) 1140 hitType |= HitTestRequest::IgnoreClipping; 1141 if (!allowShadowContent) 1142 hitType |= HitTestRequest::DisallowShadowContent; 1143 if (allowChildFrameContent) 1144 hitType |= HitTestRequest::AllowChildFrameContent; 1145 1146 HitTestRequest request(hitType); 1147 1148 // When ignoreClipping is false, this method returns null for coordinates outside of the viewport. 1149 if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding))) 1150 return 0; 1151 1152 Vector<Ref<Node>> matches; 1153 1154 // Need padding to trigger a rect based hit test, but we want to return a NodeList 1155 // so we special case this. 1156 if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) { 1157 HitTestResult result(point); 1158 renderView->hitTest(request, result); 1159 if (result.innerNode()) 1160 matches.append(*result.innerNode()->deprecatedShadowAncestorNode()); 1161 } else { 1162 HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding); 1163 renderView->hitTest(request, result); 1164 1165 const HitTestResult::NodeSet& nodeSet = result.rectBasedTestResult(); 1166 matches.reserveInitialCapacity(nodeSet.size()); 1167 for (auto it = nodeSet.begin(), end = nodeSet.end(); it != end; ++it) 1168 matches.uncheckedAppend(*it->get()); 1169 } 1170 1171 return StaticNodeList::adopt(matches); 1172} 1173 1174class GetCallerCodeBlockFunctor { 1175public: 1176 GetCallerCodeBlockFunctor() 1177 : m_iterations(0) 1178 , m_codeBlock(0) 1179 { 1180 } 1181 1182 StackVisitor::Status operator()(StackVisitor& visitor) 1183 { 1184 ++m_iterations; 1185 if (m_iterations < 2) 1186 return StackVisitor::Continue; 1187 1188 m_codeBlock = visitor->codeBlock(); 1189 return StackVisitor::Done; 1190 } 1191 1192 CodeBlock* codeBlock() const { return m_codeBlock; } 1193 1194private: 1195 int m_iterations; 1196 CodeBlock* m_codeBlock; 1197}; 1198 1199String Internals::parserMetaData(Deprecated::ScriptValue value) 1200{ 1201 JSC::VM& vm = contextDocument()->vm(); 1202 JSC::ExecState* exec = vm.topCallFrame; 1203 JSC::JSValue code = value.jsValue(); 1204 ScriptExecutable* executable; 1205 1206 if (!code || code.isNull() || code.isUndefined()) { 1207 GetCallerCodeBlockFunctor iter; 1208 exec->iterate(iter); 1209 CodeBlock* codeBlock = iter.codeBlock(); 1210 executable = codeBlock->ownerExecutable(); 1211 } else if (code.isFunction()) { 1212 JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec)); 1213 executable = funcObj->jsExecutable(); 1214 } else 1215 return String(); 1216 1217 unsigned startLine = executable->lineNo(); 1218 unsigned startColumn = executable->startColumn(); 1219 unsigned endLine = executable->lastLine(); 1220 unsigned endColumn = executable->endColumn(); 1221 1222 StringBuilder result; 1223 1224 if (executable->isFunctionExecutable()) { 1225 FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable); 1226 String inferredName = funcExecutable->inferredName().string(); 1227 result.append("function \""); 1228 result.append(inferredName); 1229 result.append("\""); 1230 } else if (executable->isEvalExecutable()) 1231 result.append("eval"); 1232 else { 1233 ASSERT(executable->isProgramExecutable()); 1234 result.append("program"); 1235 } 1236 1237 result.append(" { "); 1238 result.appendNumber(startLine); 1239 result.append(":"); 1240 result.appendNumber(startColumn); 1241 result.append(" - "); 1242 result.appendNumber(endLine); 1243 result.append(":"); 1244 result.appendNumber(endColumn); 1245 result.append(" }"); 1246 1247 return result.toString(); 1248} 1249 1250void Internals::setBatteryStatus(const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec) 1251{ 1252 Document* document = contextDocument(); 1253 if (!document || !document->page()) { 1254 ec = INVALID_ACCESS_ERR; 1255 return; 1256 } 1257 1258#if ENABLE(BATTERY_STATUS) 1259 BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level)); 1260#else 1261 UNUSED_PARAM(eventType); 1262 UNUSED_PARAM(charging); 1263 UNUSED_PARAM(chargingTime); 1264 UNUSED_PARAM(dischargingTime); 1265 UNUSED_PARAM(level); 1266#endif 1267} 1268 1269void Internals::setDeviceProximity(const String& eventType, double value, double min, double max, ExceptionCode& ec) 1270{ 1271 Document* document = contextDocument(); 1272 if (!document || !document->page()) { 1273 ec = INVALID_ACCESS_ERR; 1274 return; 1275 } 1276 1277#if ENABLE(PROXIMITY_EVENTS) 1278 DeviceProximityController::from(document->page())->didChangeDeviceProximity(value, min, max); 1279#else 1280 UNUSED_PARAM(eventType); 1281 UNUSED_PARAM(value); 1282 UNUSED_PARAM(min); 1283 UNUSED_PARAM(max); 1284#endif 1285} 1286 1287void Internals::updateEditorUINowIfScheduled() 1288{ 1289 if (Document* document = contextDocument()) { 1290 if (Frame* frame = document->frame()) 1291 frame->editor().updateEditorUINowIfScheduled(); 1292 } 1293} 1294 1295Node* Internals::findEditingDeleteButton() 1296{ 1297 Document* document = contextDocument(); 1298 if (!document || !document->frame()) 1299 return 0; 1300 1301 updateEditorUINowIfScheduled(); 1302 1303 // FIXME: We shouldn't pollute the id namespace with this name. 1304 return document->getElementById(String(ASCIILiteral("WebKit-Editing-Delete-Button"))); 1305} 1306 1307bool Internals::hasSpellingMarker(int from, int length, ExceptionCode&) 1308{ 1309 Document* document = contextDocument(); 1310 if (!document || !document->frame()) 1311 return 0; 1312 1313 updateEditorUINowIfScheduled(); 1314 1315 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length); 1316} 1317 1318bool Internals::hasAutocorrectedMarker(int from, int length, ExceptionCode&) 1319{ 1320 Document* document = contextDocument(); 1321 if (!document || !document->frame()) 1322 return 0; 1323 1324 updateEditorUINowIfScheduled(); 1325 1326 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length); 1327} 1328 1329void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionCode&) 1330{ 1331 if (!contextDocument() || !contextDocument()->frame()) 1332 return; 1333 1334 if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled()) 1335 contextDocument()->frame()->editor().toggleContinuousSpellChecking(); 1336} 1337 1338void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled, ExceptionCode&) 1339{ 1340 if (!contextDocument() || !contextDocument()->frame()) 1341 return; 1342 1343#if USE(AUTOMATIC_TEXT_REPLACEMENT) 1344 if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled()) 1345 contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution(); 1346#else 1347 UNUSED_PARAM(enabled); 1348#endif 1349} 1350 1351void Internals::setAutomaticLinkDetectionEnabled(bool enabled, ExceptionCode&) 1352{ 1353 if (!contextDocument() || !contextDocument()->frame()) 1354 return; 1355 1356#if USE(AUTOMATIC_TEXT_REPLACEMENT) 1357 if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled()) 1358 contextDocument()->frame()->editor().toggleAutomaticLinkDetection(); 1359#else 1360 UNUSED_PARAM(enabled); 1361#endif 1362} 1363 1364void Internals::setAutomaticDashSubstitutionEnabled(bool enabled, ExceptionCode&) 1365{ 1366 if (!contextDocument() || !contextDocument()->frame()) 1367 return; 1368 1369#if USE(AUTOMATIC_TEXT_REPLACEMENT) 1370 if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled()) 1371 contextDocument()->frame()->editor().toggleAutomaticDashSubstitution(); 1372#else 1373 UNUSED_PARAM(enabled); 1374#endif 1375} 1376 1377void Internals::setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&) 1378{ 1379 if (!contextDocument() || !contextDocument()->frame()) 1380 return; 1381 1382#if USE(AUTOMATIC_TEXT_REPLACEMENT) 1383 if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled()) 1384 contextDocument()->frame()->editor().toggleAutomaticTextReplacement(); 1385#else 1386 UNUSED_PARAM(enabled); 1387#endif 1388} 1389 1390void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&) 1391{ 1392 if (!contextDocument() || !contextDocument()->frame()) 1393 return; 1394 1395#if USE(AUTOMATIC_TEXT_REPLACEMENT) 1396 if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled()) 1397 contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection(); 1398#else 1399 UNUSED_PARAM(enabled); 1400#endif 1401} 1402 1403bool Internals::isOverwriteModeEnabled(ExceptionCode&) 1404{ 1405 Document* document = contextDocument(); 1406 if (!document || !document->frame()) 1407 return 0; 1408 1409 return document->frame()->editor().isOverwriteModeEnabled(); 1410} 1411 1412void Internals::toggleOverwriteModeEnabled(ExceptionCode&) 1413{ 1414 Document* document = contextDocument(); 1415 if (!document || !document->frame()) 1416 return; 1417 1418 document->frame()->editor().toggleOverwriteModeEnabled(); 1419} 1420 1421unsigned Internals::countMatchesForText(const String& text, unsigned findOptions, const String& markMatches, ExceptionCode&) 1422{ 1423 Document* document = contextDocument(); 1424 if (!document || !document->frame()) 1425 return 0; 1426 1427 bool mark = markMatches == "mark"; 1428 return document->frame()->editor().countMatchesForText(text, nullptr, findOptions, 1000, mark, nullptr); 1429} 1430 1431const ProfilesArray& Internals::consoleProfiles() const 1432{ 1433 return contextDocument()->page()->console().profiles(); 1434} 1435 1436unsigned Internals::numberOfLiveNodes() const 1437{ 1438 unsigned nodeCount = 0; 1439 for (auto* document : Document::allDocuments()) 1440 nodeCount += document->referencingNodeCount(); 1441 return nodeCount; 1442} 1443 1444unsigned Internals::numberOfLiveDocuments() const 1445{ 1446 return Document::allDocuments().size(); 1447} 1448 1449#if ENABLE(INSPECTOR) 1450Vector<String> Internals::consoleMessageArgumentCounts() const 1451{ 1452 Document* document = contextDocument(); 1453 if (!document || !document->page()) 1454 return Vector<String>(); 1455 1456 InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page()); 1457 if (!instrumentingAgents) 1458 return Vector<String>(); 1459 1460 InspectorConsoleAgent* consoleAgent = instrumentingAgents->webConsoleAgent(); 1461 if (!consoleAgent) 1462 return Vector<String>(); 1463 1464 Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts(); 1465 Vector<String> result(counts.size()); 1466 for (size_t i = 0; i < counts.size(); i++) 1467 result[i] = String::number(counts[i]); 1468 return result; 1469} 1470 1471PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url) 1472{ 1473 Page* page = contextDocument()->frame()->page(); 1474 ASSERT(page); 1475 1476 DOMWindow* window = page->mainFrame().document()->domWindow(); 1477 ASSERT(window); 1478 1479 m_frontendWindow = window->open(url, "", "", *window, *window); 1480 ASSERT(m_frontendWindow); 1481 1482 Page* frontendPage = m_frontendWindow->document()->page(); 1483 ASSERT(frontendPage); 1484 1485 auto frontendClient = std::make_unique<InspectorFrontendClientDummy>(&page->inspectorController(), frontendPage); 1486 1487 frontendPage->inspectorController().setInspectorFrontendClient(WTF::move(frontendClient)); 1488 1489 m_frontendChannel = adoptPtr(new InspectorFrontendChannelDummy(frontendPage)); 1490 1491 page->inspectorController().connectFrontend(m_frontendChannel.get()); 1492 1493 return m_frontendWindow; 1494} 1495 1496void Internals::closeDummyInspectorFrontend() 1497{ 1498 Page* page = contextDocument()->frame()->page(); 1499 ASSERT(page); 1500 ASSERT(m_frontendWindow); 1501 1502 page->inspectorController().disconnectFrontend(InspectorDisconnectReason::InspectorDestroyed); 1503 1504 m_frontendChannel.release(); 1505 1506 m_frontendWindow->close(m_frontendWindow->scriptExecutionContext()); 1507 m_frontendWindow.release(); 1508} 1509 1510void Internals::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec) 1511{ 1512 Page* page = contextDocument()->frame()->page(); 1513 if (!page) { 1514 ec = INVALID_ACCESS_ERR; 1515 return; 1516 } 1517 1518 page->inspectorController().setProfilerEnabled(enabled); 1519} 1520 1521void Internals::setInspectorIsUnderTest(bool isUnderTest, ExceptionCode& ec) 1522{ 1523 Page* page = contextDocument()->frame()->page(); 1524 if (!page) { 1525 ec = INVALID_ACCESS_ERR; 1526 return; 1527 } 1528 1529 page->inspectorController().setIsUnderTest(isUnderTest); 1530} 1531#endif // ENABLE(INSPECTOR) 1532 1533bool Internals::hasGrammarMarker(int from, int length, ExceptionCode&) 1534{ 1535 Document* document = contextDocument(); 1536 if (!document || !document->frame()) 1537 return 0; 1538 1539 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length); 1540} 1541 1542unsigned Internals::numberOfScrollableAreas(ExceptionCode&) 1543{ 1544 Document* document = contextDocument(); 1545 if (!document || !document->frame()) 1546 return 0; 1547 1548 unsigned count = 0; 1549 Frame* frame = document->frame(); 1550 if (frame->view()->scrollableAreas()) 1551 count += frame->view()->scrollableAreas()->size(); 1552 1553 for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) { 1554 if (child->view() && child->view()->scrollableAreas()) 1555 count += child->view()->scrollableAreas()->size(); 1556 } 1557 1558 return count; 1559} 1560 1561bool Internals::isPageBoxVisible(int pageNumber, ExceptionCode& ec) 1562{ 1563 Document* document = contextDocument(); 1564 if (!document) { 1565 ec = INVALID_ACCESS_ERR; 1566 return false; 1567 } 1568 1569 return document->isPageBoxVisible(pageNumber); 1570} 1571 1572// FIXME: Remove the document argument. It is almost always the same as 1573// contextDocument(), with the exception of a few tests that pass a 1574// different document, and could just make the call through another Internals 1575// instance instead. 1576String Internals::layerTreeAsText(Document* document, ExceptionCode& ec) const 1577{ 1578 return layerTreeAsText(document, 0, ec); 1579} 1580 1581String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionCode& ec) const 1582{ 1583 if (!document || !document->frame()) { 1584 ec = INVALID_ACCESS_ERR; 1585 return String(); 1586 } 1587 1588 LayerTreeFlags layerTreeFlags = 0; 1589 if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS) 1590 layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects; 1591 if (flags & LAYER_TREE_INCLUDES_TILE_CACHES) 1592 layerTreeFlags |= LayerTreeFlagsIncludeTileCaches; 1593 if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS) 1594 layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects; 1595 if (flags & LAYER_TREE_INCLUDES_PAINTING_PHASES) 1596 layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases; 1597 if (flags & LAYER_TREE_INCLUDES_CONTENT_LAYERS) 1598 layerTreeFlags |= LayerTreeFlagsIncludeContentLayers; 1599 1600 return document->frame()->layerTreeAsText(layerTreeFlags); 1601} 1602 1603String Internals::repaintRectsAsText(ExceptionCode& ec) const 1604{ 1605 Document* document = contextDocument(); 1606 if (!document || !document->frame()) { 1607 ec = INVALID_ACCESS_ERR; 1608 return String(); 1609 } 1610 1611 return document->frame()->trackedRepaintRectsAsText(); 1612} 1613 1614String Internals::scrollingStateTreeAsText(ExceptionCode& ec) const 1615{ 1616 Document* document = contextDocument(); 1617 if (!document || !document->frame()) { 1618 ec = INVALID_ACCESS_ERR; 1619 return String(); 1620 } 1621 1622 Page* page = document->page(); 1623 if (!page) 1624 return String(); 1625 1626 return page->scrollingStateTreeAsText(); 1627} 1628 1629String Internals::mainThreadScrollingReasons(ExceptionCode& ec) const 1630{ 1631 Document* document = contextDocument(); 1632 if (!document || !document->frame()) { 1633 ec = INVALID_ACCESS_ERR; 1634 return String(); 1635 } 1636 1637 Page* page = document->page(); 1638 if (!page) 1639 return String(); 1640 1641 return page->synchronousScrollingReasonsAsText(); 1642} 1643 1644PassRefPtr<ClientRectList> Internals::nonFastScrollableRects(ExceptionCode& ec) const 1645{ 1646 Document* document = contextDocument(); 1647 if (!document || !document->frame()) { 1648 ec = INVALID_ACCESS_ERR; 1649 return 0; 1650 } 1651 1652 Page* page = document->page(); 1653 if (!page) 1654 return 0; 1655 1656 return page->nonFastScrollableRects(document->frame()); 1657} 1658 1659void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const 1660{ 1661 Document* document = contextDocument(); 1662 if (!document) { 1663 ec = INVALID_ACCESS_ERR; 1664 return; 1665 } 1666 1667 CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); 1668 if (!cachedResourceLoader) 1669 return; 1670 cachedResourceLoader->garbageCollectDocumentResources(); 1671} 1672 1673void Internals::allowRoundingHacks() const 1674{ 1675 TextRun::setAllowsRoundingHacks(true); 1676} 1677 1678void Internals::insertAuthorCSS(const String& css, ExceptionCode& ec) const 1679{ 1680 Document* document = contextDocument(); 1681 if (!document) { 1682 ec = INVALID_ACCESS_ERR; 1683 return; 1684 } 1685 1686 auto parsedSheet = StyleSheetContents::create(*document); 1687 parsedSheet.get().setIsUserStyleSheet(false); 1688 parsedSheet.get().parseString(css); 1689 document->styleSheetCollection().addAuthorSheet(WTF::move(parsedSheet)); 1690} 1691 1692void Internals::insertUserCSS(const String& css, ExceptionCode& ec) const 1693{ 1694 Document* document = contextDocument(); 1695 if (!document) { 1696 ec = INVALID_ACCESS_ERR; 1697 return; 1698 } 1699 1700 auto parsedSheet = StyleSheetContents::create(*document); 1701 parsedSheet.get().setIsUserStyleSheet(true); 1702 parsedSheet.get().parseString(css); 1703 document->styleSheetCollection().addUserSheet(WTF::move(parsedSheet)); 1704} 1705 1706String Internals::counterValue(Element* element) 1707{ 1708 if (!element) 1709 return String(); 1710 1711 return counterValueForElement(element); 1712} 1713 1714int Internals::pageNumber(Element* element, float pageWidth, float pageHeight) 1715{ 1716 if (!element) 1717 return 0; 1718 1719 return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight)); 1720} 1721 1722Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const 1723{ 1724 Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask); 1725 Vector<String> array; 1726 1727 Vector<IconURL>::const_iterator iter(iconURLs.begin()); 1728 for (; iter != iconURLs.end(); ++iter) 1729 array.append(iter->m_iconURL.string()); 1730 1731 return array; 1732} 1733 1734Vector<String> Internals::shortcutIconURLs() const 1735{ 1736 return iconURLs(contextDocument(), Favicon); 1737} 1738 1739Vector<String> Internals::allIconURLs() const 1740{ 1741 return iconURLs(contextDocument(), Favicon | TouchIcon | TouchPrecomposedIcon); 1742} 1743 1744int Internals::numberOfPages(float pageWidth, float pageHeight) 1745{ 1746 if (!frame()) 1747 return -1; 1748 1749 return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight)); 1750} 1751 1752String Internals::pageProperty(String propertyName, int pageNumber, ExceptionCode& ec) const 1753{ 1754 if (!frame()) { 1755 ec = INVALID_ACCESS_ERR; 1756 return String(); 1757 } 1758 1759 return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber); 1760} 1761 1762String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionCode& ec) const 1763{ 1764 if (!frame()) { 1765 ec = INVALID_ACCESS_ERR; 1766 return String(); 1767 } 1768 1769 return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft); 1770} 1771 1772void Internals::setPageScaleFactor(float scaleFactor, int x, int y, ExceptionCode& ec) 1773{ 1774 Document* document = contextDocument(); 1775 if (!document || !document->page()) { 1776 ec = INVALID_ACCESS_ERR; 1777 return; 1778 } 1779 Page* page = document->page(); 1780 page->setPageScaleFactor(scaleFactor, IntPoint(x, y)); 1781} 1782 1783void Internals::setPageZoomFactor(float zoomFactor, ExceptionCode& ec) 1784{ 1785 Document* document = contextDocument(); 1786 if (!document || !document->frame()) { 1787 ec = INVALID_ACCESS_ERR; 1788 return; 1789 } 1790 Frame* frame = document->frame(); 1791 frame->setPageZoomFactor(zoomFactor); 1792} 1793 1794void Internals::setHeaderHeight(float height) 1795{ 1796 Document* document = contextDocument(); 1797 if (!document || !document->view()) 1798 return; 1799 1800 FrameView* frameView = document->view(); 1801 frameView->setHeaderHeight(height); 1802} 1803 1804void Internals::setFooterHeight(float height) 1805{ 1806 Document* document = contextDocument(); 1807 if (!document || !document->view()) 1808 return; 1809 1810 FrameView* frameView = document->view(); 1811 frameView->setFooterHeight(height); 1812} 1813 1814void Internals::setTopContentInset(float contentInset) 1815{ 1816 Document* document = contextDocument(); 1817 if (!document) 1818 return; 1819 1820 Page* page = document->page(); 1821 page->setTopContentInset(contentInset); 1822} 1823 1824#if ENABLE(FULLSCREEN_API) 1825void Internals::webkitWillEnterFullScreenForElement(Element* element) 1826{ 1827 Document* document = contextDocument(); 1828 if (!document) 1829 return; 1830 document->webkitWillEnterFullScreenForElement(element); 1831} 1832 1833void Internals::webkitDidEnterFullScreenForElement(Element* element) 1834{ 1835 Document* document = contextDocument(); 1836 if (!document) 1837 return; 1838 document->webkitDidEnterFullScreenForElement(element); 1839} 1840 1841void Internals::webkitWillExitFullScreenForElement(Element* element) 1842{ 1843 Document* document = contextDocument(); 1844 if (!document) 1845 return; 1846 document->webkitWillExitFullScreenForElement(element); 1847} 1848 1849void Internals::webkitDidExitFullScreenForElement(Element* element) 1850{ 1851 Document* document = contextDocument(); 1852 if (!document) 1853 return; 1854 document->webkitDidExitFullScreenForElement(element); 1855} 1856#endif 1857 1858void Internals::setApplicationCacheOriginQuota(unsigned long long quota) 1859{ 1860 Document* document = contextDocument(); 1861 if (!document) 1862 return; 1863 cacheStorage().storeUpdatedQuotaForOrigin(document->securityOrigin(), quota); 1864} 1865 1866void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) 1867{ 1868 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme); 1869} 1870 1871void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme) 1872{ 1873 SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme); 1874} 1875 1876PassRefPtr<MallocStatistics> Internals::mallocStatistics() const 1877{ 1878 return MallocStatistics::create(); 1879} 1880 1881PassRefPtr<TypeConversions> Internals::typeConversions() const 1882{ 1883 return TypeConversions::create(); 1884} 1885 1886PassRefPtr<MemoryInfo> Internals::memoryInfo() const 1887{ 1888 return MemoryInfo::create(); 1889} 1890 1891Vector<String> Internals::getReferencedFilePaths() const 1892{ 1893 frame()->loader().history().saveDocumentAndScrollState(); 1894 return FormController::getReferencedFilePaths(frame()->loader().history().currentItem()->documentState()); 1895} 1896 1897void Internals::startTrackingRepaints(ExceptionCode& ec) 1898{ 1899 Document* document = contextDocument(); 1900 if (!document || !document->view()) { 1901 ec = INVALID_ACCESS_ERR; 1902 return; 1903 } 1904 1905 FrameView* frameView = document->view(); 1906 frameView->setTracksRepaints(true); 1907} 1908 1909void Internals::stopTrackingRepaints(ExceptionCode& ec) 1910{ 1911 Document* document = contextDocument(); 1912 if (!document || !document->view()) { 1913 ec = INVALID_ACCESS_ERR; 1914 return; 1915 } 1916 1917 FrameView* frameView = document->view(); 1918 frameView->setTracksRepaints(false); 1919} 1920 1921void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionCode& ec) 1922{ 1923 updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(nullptr, ec); 1924} 1925 1926void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionCode& ec) 1927{ 1928 Document* document; 1929 if (!node) 1930 document = contextDocument(); 1931 else if (node->isDocumentNode()) 1932 document = toDocument(node); 1933 else if (node->hasTagName(HTMLNames::iframeTag)) 1934 document = toHTMLIFrameElement(node)->contentDocument(); 1935 else { 1936 ec = TypeError; 1937 return; 1938 } 1939 1940 document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously); 1941} 1942 1943#if !PLATFORM(IOS) 1944static const char* cursorTypeToString(Cursor::Type cursorType) 1945{ 1946 switch (cursorType) { 1947 case Cursor::Pointer: return "Pointer"; 1948 case Cursor::Cross: return "Cross"; 1949 case Cursor::Hand: return "Hand"; 1950 case Cursor::IBeam: return "IBeam"; 1951 case Cursor::Wait: return "Wait"; 1952 case Cursor::Help: return "Help"; 1953 case Cursor::EastResize: return "EastResize"; 1954 case Cursor::NorthResize: return "NorthResize"; 1955 case Cursor::NorthEastResize: return "NorthEastResize"; 1956 case Cursor::NorthWestResize: return "NorthWestResize"; 1957 case Cursor::SouthResize: return "SouthResize"; 1958 case Cursor::SouthEastResize: return "SouthEastResize"; 1959 case Cursor::SouthWestResize: return "SouthWestResize"; 1960 case Cursor::WestResize: return "WestResize"; 1961 case Cursor::NorthSouthResize: return "NorthSouthResize"; 1962 case Cursor::EastWestResize: return "EastWestResize"; 1963 case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize"; 1964 case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize"; 1965 case Cursor::ColumnResize: return "ColumnResize"; 1966 case Cursor::RowResize: return "RowResize"; 1967 case Cursor::MiddlePanning: return "MiddlePanning"; 1968 case Cursor::EastPanning: return "EastPanning"; 1969 case Cursor::NorthPanning: return "NorthPanning"; 1970 case Cursor::NorthEastPanning: return "NorthEastPanning"; 1971 case Cursor::NorthWestPanning: return "NorthWestPanning"; 1972 case Cursor::SouthPanning: return "SouthPanning"; 1973 case Cursor::SouthEastPanning: return "SouthEastPanning"; 1974 case Cursor::SouthWestPanning: return "SouthWestPanning"; 1975 case Cursor::WestPanning: return "WestPanning"; 1976 case Cursor::Move: return "Move"; 1977 case Cursor::VerticalText: return "VerticalText"; 1978 case Cursor::Cell: return "Cell"; 1979 case Cursor::ContextMenu: return "ContextMenu"; 1980 case Cursor::Alias: return "Alias"; 1981 case Cursor::Progress: return "Progress"; 1982 case Cursor::NoDrop: return "NoDrop"; 1983 case Cursor::Copy: return "Copy"; 1984 case Cursor::None: return "None"; 1985 case Cursor::NotAllowed: return "NotAllowed"; 1986 case Cursor::ZoomIn: return "ZoomIn"; 1987 case Cursor::ZoomOut: return "ZoomOut"; 1988 case Cursor::Grab: return "Grab"; 1989 case Cursor::Grabbing: return "Grabbing"; 1990 case Cursor::Custom: return "Custom"; 1991 } 1992 1993 ASSERT_NOT_REACHED(); 1994 return "UNKNOWN"; 1995} 1996#endif 1997 1998String Internals::getCurrentCursorInfo(ExceptionCode& ec) 1999{ 2000 Document* document = contextDocument(); 2001 if (!document || !document->frame()) { 2002 ec = INVALID_ACCESS_ERR; 2003 return String(); 2004 } 2005 2006#if !PLATFORM(IOS) 2007 Cursor cursor = document->frame()->eventHandler().currentMouseCursor(); 2008 2009 StringBuilder result; 2010 result.append("type="); 2011 result.append(cursorTypeToString(cursor.type())); 2012 result.append(" hotSpot="); 2013 result.appendNumber(cursor.hotSpot().x()); 2014 result.append(","); 2015 result.appendNumber(cursor.hotSpot().y()); 2016 if (cursor.image()) { 2017 FloatSize size = cursor.image()->size(); 2018 result.append(" image="); 2019 result.appendNumber(size.width()); 2020 result.append("x"); 2021 result.appendNumber(size.height()); 2022 } 2023#if ENABLE(MOUSE_CURSOR_SCALE) 2024 if (cursor.imageScaleFactor() != 1) { 2025 result.append(" scale="); 2026 NumberToStringBuffer buffer; 2027 result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true)); 2028 } 2029#endif 2030 return result.toString(); 2031#else 2032 return "FAIL: Cursor details not available on this platform."; 2033#endif 2034} 2035 2036PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const 2037{ 2038 Vector<uint8_t> bytes = value->data(); 2039 return ArrayBuffer::create(bytes.data(), bytes.size()); 2040} 2041 2042PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const 2043{ 2044 Vector<uint8_t> bytes; 2045 bytes.append(static_cast<const uint8_t*>(buffer->data()), buffer->byteLength()); 2046 return SerializedScriptValue::adopt(bytes); 2047} 2048 2049void Internals::setUsesOverlayScrollbars(bool enabled) 2050{ 2051 WebCore::Settings::setUsesOverlayScrollbars(enabled); 2052} 2053 2054void Internals::forceReload(bool endToEnd) 2055{ 2056 frame()->loader().reload(endToEnd); 2057} 2058 2059#if ENABLE(ENCRYPTED_MEDIA_V2) 2060void Internals::initializeMockCDM() 2061{ 2062 CDM::registerCDMFactory(MockCDM::create, MockCDM::supportsKeySystem, MockCDM::supportsKeySystemAndMimeType); 2063} 2064#endif 2065 2066String Internals::markerTextForListItem(Element* element, ExceptionCode& ec) 2067{ 2068 if (!element) { 2069 ec = INVALID_ACCESS_ERR; 2070 return String(); 2071 } 2072 return WebCore::markerTextForListItem(element); 2073} 2074 2075String Internals::getImageSourceURL(Element* element, ExceptionCode& ec) 2076{ 2077 if (!element) { 2078 ec = INVALID_ACCESS_ERR; 2079 return String(); 2080 } 2081 return element->imageSourceURL(); 2082} 2083 2084#if ENABLE(VIDEO) 2085void Internals::simulateAudioInterruption(Node* node) 2086{ 2087#if USE(GSTREAMER) 2088 HTMLMediaElement* element = toHTMLMediaElement(node); 2089 element->player()->simulateAudioInterruption(); 2090#else 2091 UNUSED_PARAM(node); 2092#endif 2093} 2094#endif 2095 2096bool Internals::isSelectPopupVisible(Node* node) 2097{ 2098 if (!isHTMLSelectElement(node)) 2099 return false; 2100 2101 HTMLSelectElement* select = toHTMLSelectElement(node); 2102 2103 auto renderer = select->renderer(); 2104 if (!renderer->isMenuList()) 2105 return false; 2106 2107#if !PLATFORM(IOS) 2108 RenderMenuList* menuList = toRenderMenuList(renderer); 2109 return menuList->popupIsVisible(); 2110#else 2111 return false; 2112#endif // !PLATFORM(IOS) 2113} 2114 2115String Internals::captionsStyleSheetOverride(ExceptionCode& ec) 2116{ 2117 Document* document = contextDocument(); 2118 if (!document || !document->page()) { 2119 ec = INVALID_ACCESS_ERR; 2120 return emptyString(); 2121 } 2122 2123#if ENABLE(VIDEO_TRACK) 2124 return document->page()->group().captionPreferences()->captionsStyleSheetOverride(); 2125#else 2126 return emptyString(); 2127#endif 2128} 2129 2130void Internals::setCaptionsStyleSheetOverride(const String& override, ExceptionCode& ec) 2131{ 2132 Document* document = contextDocument(); 2133 if (!document || !document->page()) { 2134 ec = INVALID_ACCESS_ERR; 2135 return; 2136 } 2137 2138#if ENABLE(VIDEO_TRACK) 2139 document->page()->group().captionPreferences()->setCaptionsStyleSheetOverride(override); 2140#else 2141 UNUSED_PARAM(override); 2142#endif 2143} 2144 2145void Internals::setPrimaryAudioTrackLanguageOverride(const String& language, ExceptionCode& ec) 2146{ 2147 Document* document = contextDocument(); 2148 if (!document || !document->page()) { 2149 ec = INVALID_ACCESS_ERR; 2150 return; 2151 } 2152 2153#if ENABLE(VIDEO_TRACK) 2154 document->page()->group().captionPreferences()->setPrimaryAudioTrackLanguageOverride(language); 2155#else 2156 UNUSED_PARAM(language); 2157#endif 2158} 2159 2160void Internals::setCaptionDisplayMode(const String& mode, ExceptionCode& ec) 2161{ 2162 Document* document = contextDocument(); 2163 if (!document || !document->page()) { 2164 ec = INVALID_ACCESS_ERR; 2165 return; 2166 } 2167 2168#if ENABLE(VIDEO_TRACK) 2169 CaptionUserPreferences* captionPreferences = document->page()->group().captionPreferences(); 2170 2171 if (equalIgnoringCase(mode, "Automatic")) 2172 captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::Automatic); 2173 else if (equalIgnoringCase(mode, "ForcedOnly")) 2174 captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly); 2175 else if (equalIgnoringCase(mode, "AlwaysOn")) 2176 captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn); 2177 else 2178 ec = SYNTAX_ERR; 2179#else 2180 UNUSED_PARAM(mode); 2181#endif 2182} 2183 2184#if ENABLE(VIDEO) 2185PassRefPtr<TimeRanges> Internals::createTimeRanges(Float32Array* startTimes, Float32Array* endTimes) 2186{ 2187 ASSERT(startTimes && endTimes); 2188 ASSERT(startTimes->length() == endTimes->length()); 2189 RefPtr<TimeRanges> ranges = TimeRanges::create(); 2190 2191 unsigned count = std::min(startTimes->length(), endTimes->length()); 2192 for (unsigned i = 0; i < count; ++i) 2193 ranges->add(startTimes->item(i), endTimes->item(i)); 2194 return ranges; 2195} 2196 2197double Internals::closestTimeToTimeRanges(double time, TimeRanges* ranges) 2198{ 2199 return ranges->nearest(time); 2200} 2201#endif 2202 2203PassRefPtr<ClientRect> Internals::selectionBounds(ExceptionCode& ec) 2204{ 2205 Document* document = contextDocument(); 2206 if (!document || !document->frame()) { 2207 ec = INVALID_ACCESS_ERR; 2208 return ClientRect::create(); 2209 } 2210 2211 return ClientRect::create(document->frame()->selection().selectionBounds()); 2212} 2213 2214#if ENABLE(VIBRATION) 2215bool Internals::isVibrating() 2216{ 2217 Page* page = contextDocument()->page(); 2218 ASSERT(page); 2219 2220 return Vibration::from(page)->isVibrating(); 2221} 2222#endif 2223 2224bool Internals::isPluginUnavailabilityIndicatorObscured(Element* element, ExceptionCode& ec) 2225{ 2226 if (!element) { 2227 ec = INVALID_ACCESS_ERR; 2228 return false; 2229 } 2230 2231 auto renderer = element->renderer(); 2232 if (!renderer || !renderer->isEmbeddedObject()) { 2233 ec = INVALID_ACCESS_ERR; 2234 return false; 2235 } 2236 2237 RenderEmbeddedObject* embed = toRenderEmbeddedObject(renderer); 2238 return embed->isReplacementObscured(); 2239} 2240 2241bool Internals::isPluginSnapshotted(Element* element, ExceptionCode& ec) 2242{ 2243 if (!element) { 2244 ec = INVALID_ACCESS_ERR; 2245 return false; 2246 } 2247 HTMLPlugInElement* pluginElement = toHTMLPlugInElement(element); 2248 return pluginElement->displayState() <= HTMLPlugInElement::DisplayingSnapshot; 2249} 2250 2251#if ENABLE(MEDIA_SOURCE) 2252void Internals::initializeMockMediaSource() 2253{ 2254#if USE(AVFOUNDATION) 2255 WebCore::Settings::setAVFoundationEnabled(false); 2256#endif 2257 MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine); 2258} 2259 2260Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer* buffer, const AtomicString& trackID) 2261{ 2262 if (!buffer) 2263 return Vector<String>(); 2264 2265 return buffer->bufferedSamplesForTrackID(trackID); 2266} 2267#endif 2268 2269#if ENABLE(VIDEO) 2270void Internals::beginMediaSessionInterruption() 2271{ 2272 MediaSessionManager::sharedManager().beginInterruption(MediaSession::SystemInterruption); 2273} 2274 2275void Internals::endMediaSessionInterruption(const String& flagsString) 2276{ 2277 MediaSession::EndInterruptionFlags flags = MediaSession::NoFlags; 2278 2279 if (equalIgnoringCase(flagsString, "MayResumePlaying")) 2280 flags = MediaSession::MayResumePlaying; 2281 2282 MediaSessionManager::sharedManager().endInterruption(flags); 2283} 2284 2285void Internals::applicationWillEnterForeground() const 2286{ 2287 MediaSessionManager::sharedManager().applicationWillEnterForeground(); 2288} 2289 2290void Internals::applicationWillEnterBackground() const 2291{ 2292 MediaSessionManager::sharedManager().applicationWillEnterBackground(); 2293} 2294 2295void Internals::setMediaSessionRestrictions(const String& mediaTypeString, const String& restrictionsString, ExceptionCode& ec) 2296{ 2297 MediaSession::MediaType mediaType = MediaSession::None; 2298 if (equalIgnoringCase(mediaTypeString, "Video")) 2299 mediaType = MediaSession::Video; 2300 else if (equalIgnoringCase(mediaTypeString, "Audio")) 2301 mediaType = MediaSession::Audio; 2302 else if (equalIgnoringCase(mediaTypeString, "WebAudio")) 2303 mediaType = MediaSession::WebAudio; 2304 else { 2305 ec = INVALID_ACCESS_ERR; 2306 return; 2307 } 2308 2309 MediaSessionManager::SessionRestrictions restrictions = MediaSessionManager::sharedManager().restrictions(mediaType); 2310 MediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions); 2311 2312 restrictions = MediaSessionManager::NoRestrictions; 2313 2314 if (equalIgnoringCase(restrictionsString, "ConcurrentPlaybackNotPermitted")) 2315 restrictions = MediaSessionManager::ConcurrentPlaybackNotPermitted; 2316 if (equalIgnoringCase(restrictionsString, "InlineVideoPlaybackRestricted")) 2317 restrictions += MediaSessionManager::InlineVideoPlaybackRestricted; 2318 if (equalIgnoringCase(restrictionsString, "MetadataPreloadingNotPermitted")) 2319 restrictions += MediaSessionManager::MetadataPreloadingNotPermitted; 2320 if (equalIgnoringCase(restrictionsString, "AutoPreloadingNotPermitted")) 2321 restrictions += MediaSessionManager::AutoPreloadingNotPermitted; 2322 if (equalIgnoringCase(restrictionsString, "BackgroundPlaybackNotPermitted")) 2323 restrictions += MediaSessionManager::BackgroundPlaybackNotPermitted; 2324 2325 MediaSessionManager::sharedManager().addRestriction(mediaType, restrictions); 2326} 2327 2328void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec) 2329{ 2330 MediaSession::RemoteControlCommandType command; 2331 2332 if (equalIgnoringCase(commandString, "Play")) 2333 command = MediaSession::PlayCommand; 2334 else if (equalIgnoringCase(commandString, "Pause")) 2335 command = MediaSession::PauseCommand; 2336 else if (equalIgnoringCase(commandString, "Stop")) 2337 command = MediaSession::StopCommand; 2338 else if (equalIgnoringCase(commandString, "TogglePlayPause")) 2339 command = MediaSession::TogglePlayPauseCommand; 2340 else if (equalIgnoringCase(commandString, "BeginSeekingBackward")) 2341 command = MediaSession::BeginSeekingBackwardCommand; 2342 else if (equalIgnoringCase(commandString, "EndSeekingBackward")) 2343 command = MediaSession::EndSeekingBackwardCommand; 2344 else if (equalIgnoringCase(commandString, "BeginSeekingForward")) 2345 command = MediaSession::BeginSeekingForwardCommand; 2346 else if (equalIgnoringCase(commandString, "EndSeekingForward")) 2347 command = MediaSession::EndSeekingForwardCommand; 2348 else { 2349 ec = INVALID_ACCESS_ERR; 2350 return; 2351 } 2352 2353 MediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command); 2354} 2355#endif // ENABLE(VIDEO) 2356 2357void Internals::simulateSystemSleep() const 2358{ 2359#if ENABLE(VIDEO) 2360 MediaSessionManager::sharedManager().systemWillSleep(); 2361#endif 2362} 2363 2364void Internals::simulateSystemWake() const 2365{ 2366#if ENABLE(VIDEO) 2367 MediaSessionManager::sharedManager().systemDidWake(); 2368#endif 2369} 2370 2371} 2372