diff options
Diffstat (limited to 'Source/WebCore/inspector/PageScriptDebugServer.cpp')
-rw-r--r-- | Source/WebCore/inspector/PageScriptDebugServer.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/Source/WebCore/inspector/PageScriptDebugServer.cpp b/Source/WebCore/inspector/PageScriptDebugServer.cpp new file mode 100644 index 000000000..b3ae44b4a --- /dev/null +++ b/Source/WebCore/inspector/PageScriptDebugServer.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2013-2014 Apple Inc. All rights reserved. + * Copyright (c) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PageScriptDebugServer.h" + +#include "CommonVM.h" +#include "Document.h" +#include "EventLoop.h" +#include "FrameView.h" +#include "InspectorController.h" +#include "InspectorFrontendClient.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMWindowCustom.h" +#include "MainFrame.h" +#include "Page.h" +#include "PageGroup.h" +#include "PluginViewBase.h" +#include "ScriptController.h" +#include "Timer.h" +#include <runtime/JSLock.h> +#include <wtf/MainThread.h> +#include <wtf/StdLibExtras.h> + +#if PLATFORM(IOS) +#include "WebCoreThreadInternal.h" +#endif + +using namespace JSC; +using namespace Inspector; + +namespace WebCore { + +PageScriptDebugServer::PageScriptDebugServer(Page& page) + : ScriptDebugServer(WebCore::commonVM()) + , m_page(page) +{ +} + +void PageScriptDebugServer::attachDebugger() +{ + m_page.setDebugger(this); +} + +void PageScriptDebugServer::detachDebugger(bool isBeingDestroyed) +{ + m_page.setDebugger(nullptr); + if (!isBeingDestroyed) + recompileAllJSFunctions(); +} + +void PageScriptDebugServer::recompileAllJSFunctions() +{ + JSLockHolder lock(vm()); + Debugger::recompileAllJSFunctions(); +} + +void PageScriptDebugServer::didPause(JSGlobalObject*) +{ + setJavaScriptPaused(m_page.group(), true); +} + +void PageScriptDebugServer::didContinue(JSGlobalObject*) +{ + setJavaScriptPaused(m_page.group(), false); +} + +void PageScriptDebugServer::runEventLoopWhilePaused() +{ +#if PLATFORM(IOS) + // On iOS, running an EventLoop causes us to run a nested WebRunLoop. + // Since the WebThread is autoreleased at the end of run loop iterations + // we need to gracefully handle releasing and reacquiring the lock. + if (WebThreadIsEnabled()) { + ASSERT(WebThreadIsLockedOrDisabled()); + JSC::JSLock::DropAllLocks dropAllLocks(vm()); + WebRunLoopEnableNested(); + + runEventLoopWhilePausedInternal(); + + WebRunLoopDisableNested(); + ASSERT(WebThreadIsLockedOrDisabled()); + return; + } +#endif + + runEventLoopWhilePausedInternal(); +} + +void PageScriptDebugServer::runEventLoopWhilePausedInternal() +{ + TimerBase::fireTimersInNestedEventLoop(); + + m_page.incrementNestedRunLoopCount(); + + EventLoop loop; + while (!m_doneProcessingDebuggerEvents && !loop.ended()) + loop.cycle(); + + m_page.decrementNestedRunLoopCount(); +} + +bool PageScriptDebugServer::isContentScript(ExecState* exec) const +{ + return ¤tWorld(exec) != &mainThreadNormalWorld(); +} + +void PageScriptDebugServer::reportException(ExecState* exec, JSC::Exception* exception) const +{ + WebCore::reportException(exec, exception); +} + +void PageScriptDebugServer::setJavaScriptPaused(const PageGroup& pageGroup, bool paused) +{ + setMainThreadCallbacksPaused(paused); + + for (auto& page : pageGroup.pages()) { + page->setDefersLoading(paused); + + for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) + setJavaScriptPaused(*frame, paused); + + if (auto* frontendClient = page->inspectorController().inspectorFrontendClient()) { + if (paused) + frontendClient->pagePaused(); + else + frontendClient->pageUnpaused(); + } + } +} + +void PageScriptDebugServer::setJavaScriptPaused(Frame& frame, bool paused) +{ + if (!frame.script().canExecuteScripts(NotAboutToExecuteScript)) + return; + + frame.script().setPaused(paused); + + ASSERT(frame.document()); + auto& document = *frame.document(); + if (paused) { + document.suspendScriptedAnimationControllerCallbacks(); + document.suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); + } else { + document.resumeActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); + document.resumeScriptedAnimationControllerCallbacks(); + } + + if (auto* view = frame.view()) { + for (auto& child : view->children()) { + if (!is<PluginViewBase>(child.get())) + continue; + downcast<PluginViewBase>(child.get()).setJavaScriptPaused(paused); + } + } +} + +} // namespace WebCore |