12bde8e466a4451c7319e3a072d118917957d6554Steve Block/*
22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (c) 2011 Google Inc. All rights reserved.
32bde8e466a4451c7319e3a072d118917957d6554Steve Block *
42bde8e466a4451c7319e3a072d118917957d6554Steve Block * Redistribution and use in source and binary forms, with or without
52bde8e466a4451c7319e3a072d118917957d6554Steve Block * modification, are permitted provided that the following conditions are
62bde8e466a4451c7319e3a072d118917957d6554Steve Block * met:
72bde8e466a4451c7319e3a072d118917957d6554Steve Block *
82bde8e466a4451c7319e3a072d118917957d6554Steve Block *     * Redistributions of source code must retain the above copyright
92bde8e466a4451c7319e3a072d118917957d6554Steve Block * notice, this list of conditions and the following disclaimer.
102bde8e466a4451c7319e3a072d118917957d6554Steve Block *     * Redistributions in binary form must reproduce the above
112bde8e466a4451c7319e3a072d118917957d6554Steve Block * copyright notice, this list of conditions and the following disclaimer
122bde8e466a4451c7319e3a072d118917957d6554Steve Block * in the documentation and/or other materials provided with the
132bde8e466a4451c7319e3a072d118917957d6554Steve Block * distribution.
142bde8e466a4451c7319e3a072d118917957d6554Steve Block *     * Neither the name of Google Inc. nor the names of its
152bde8e466a4451c7319e3a072d118917957d6554Steve Block * contributors may be used to endorse or promote products derived from
162bde8e466a4451c7319e3a072d118917957d6554Steve Block * this software without specific prior written permission.
172bde8e466a4451c7319e3a072d118917957d6554Steve Block *
182bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
192bde8e466a4451c7319e3a072d118917957d6554Steve Block * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
202bde8e466a4451c7319e3a072d118917957d6554Steve Block * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
212bde8e466a4451c7319e3a072d118917957d6554Steve Block * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
222bde8e466a4451c7319e3a072d118917957d6554Steve Block * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
232bde8e466a4451c7319e3a072d118917957d6554Steve Block * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
242bde8e466a4451c7319e3a072d118917957d6554Steve Block * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252bde8e466a4451c7319e3a072d118917957d6554Steve Block * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262bde8e466a4451c7319e3a072d118917957d6554Steve Block * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
272bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
282bde8e466a4451c7319e3a072d118917957d6554Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292bde8e466a4451c7319e3a072d118917957d6554Steve Block */
302bde8e466a4451c7319e3a072d118917957d6554Steve Block
312bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "config.h"
322bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "PageScriptDebugServer.h"
332bde8e466a4451c7319e3a072d118917957d6554Steve Block
342bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(JAVASCRIPT_DEBUGGER)
352bde8e466a4451c7319e3a072d118917957d6554Steve Block
362bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "Frame.h"
372bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "FrameView.h"
382bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "JSDOMWindowCustom.h"
392bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "Page.h"
402bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "PageGroup.h"
412bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "PluginView.h"
422bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "ScriptDebugListener.h"
432bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "Widget.h"
442bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <runtime/JSLock.h>
452bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/MainThread.h>
462bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/OwnPtr.h>
472bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/PassOwnPtr.h>
482bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/StdLibExtras.h>
492bde8e466a4451c7319e3a072d118917957d6554Steve Block
502bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing namespace JSC;
512bde8e466a4451c7319e3a072d118917957d6554Steve Block
522bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace WebCore {
532bde8e466a4451c7319e3a072d118917957d6554Steve Block
542bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic Page* toPage(JSGlobalObject* globalObject)
552bde8e466a4451c7319e3a072d118917957d6554Steve Block{
562bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT_ARG(globalObject, globalObject);
572bde8e466a4451c7319e3a072d118917957d6554Steve Block
582bde8e466a4451c7319e3a072d118917957d6554Steve Block    JSDOMWindow* window = asJSDOMWindow(globalObject);
592bde8e466a4451c7319e3a072d118917957d6554Steve Block    Frame* frame = window->impl()->frame();
602bde8e466a4451c7319e3a072d118917957d6554Steve Block    return frame ? frame->page() : 0;
612bde8e466a4451c7319e3a072d118917957d6554Steve Block}
622bde8e466a4451c7319e3a072d118917957d6554Steve Block
632bde8e466a4451c7319e3a072d118917957d6554Steve BlockPageScriptDebugServer& PageScriptDebugServer::shared()
642bde8e466a4451c7319e3a072d118917957d6554Steve Block{
652bde8e466a4451c7319e3a072d118917957d6554Steve Block    DEFINE_STATIC_LOCAL(PageScriptDebugServer, server, ());
662bde8e466a4451c7319e3a072d118917957d6554Steve Block    return server;
672bde8e466a4451c7319e3a072d118917957d6554Steve Block}
682bde8e466a4451c7319e3a072d118917957d6554Steve Block
692bde8e466a4451c7319e3a072d118917957d6554Steve BlockPageScriptDebugServer::PageScriptDebugServer()
702bde8e466a4451c7319e3a072d118917957d6554Steve Block    : ScriptDebugServer()
712bde8e466a4451c7319e3a072d118917957d6554Steve Block{
722bde8e466a4451c7319e3a072d118917957d6554Steve Block}
732bde8e466a4451c7319e3a072d118917957d6554Steve Block
742bde8e466a4451c7319e3a072d118917957d6554Steve BlockPageScriptDebugServer::~PageScriptDebugServer()
752bde8e466a4451c7319e3a072d118917957d6554Steve Block{
762bde8e466a4451c7319e3a072d118917957d6554Steve Block    deleteAllValues(m_pageListenersMap);
772bde8e466a4451c7319e3a072d118917957d6554Steve Block}
782bde8e466a4451c7319e3a072d118917957d6554Steve Block
792bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page)
802bde8e466a4451c7319e3a072d118917957d6554Steve Block{
812bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT_ARG(listener, listener);
822bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT_ARG(page, page);
832bde8e466a4451c7319e3a072d118917957d6554Steve Block
842bde8e466a4451c7319e3a072d118917957d6554Steve Block    pair<PageListenersMap::iterator, bool> result = m_pageListenersMap.add(page, 0);
852bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (result.second)
862bde8e466a4451c7319e3a072d118917957d6554Steve Block        result.first->second = new ListenerSet;
872bde8e466a4451c7319e3a072d118917957d6554Steve Block
882bde8e466a4451c7319e3a072d118917957d6554Steve Block    ListenerSet* listeners = result.first->second;
892bde8e466a4451c7319e3a072d118917957d6554Steve Block    listeners->add(listener);
902bde8e466a4451c7319e3a072d118917957d6554Steve Block
912bde8e466a4451c7319e3a072d118917957d6554Steve Block    recompileAllJSFunctionsSoon();
922bde8e466a4451c7319e3a072d118917957d6554Steve Block    page->setDebugger(this);
932bde8e466a4451c7319e3a072d118917957d6554Steve Block}
942bde8e466a4451c7319e3a072d118917957d6554Steve Block
952bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page)
962bde8e466a4451c7319e3a072d118917957d6554Steve Block{
972bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT_ARG(listener, listener);
982bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT_ARG(page, page);
992bde8e466a4451c7319e3a072d118917957d6554Steve Block
1002bde8e466a4451c7319e3a072d118917957d6554Steve Block    PageListenersMap::iterator it = m_pageListenersMap.find(page);
1012bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (it == m_pageListenersMap.end())
1022bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
1032bde8e466a4451c7319e3a072d118917957d6554Steve Block
1042bde8e466a4451c7319e3a072d118917957d6554Steve Block    ListenerSet* listeners = it->second;
1052bde8e466a4451c7319e3a072d118917957d6554Steve Block    listeners->remove(listener);
1062bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (listeners->isEmpty()) {
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_pageListenersMap.remove(it);
1082bde8e466a4451c7319e3a072d118917957d6554Steve Block        delete listeners;
1092bde8e466a4451c7319e3a072d118917957d6554Steve Block        didRemoveLastListener(page);
1102bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1112bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1122bde8e466a4451c7319e3a072d118917957d6554Steve Block
1132bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::recompileAllJSFunctions(Timer<ScriptDebugServer>*)
1142bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1152bde8e466a4451c7319e3a072d118917957d6554Steve Block    JSLock lock(SilenceAssertionsOnly);
1162bde8e466a4451c7319e3a072d118917957d6554Steve Block    // If JavaScript stack is not empty postpone recompilation.
1172bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (JSDOMWindow::commonJSGlobalData()->dynamicGlobalObject)
1182bde8e466a4451c7319e3a072d118917957d6554Steve Block        recompileAllJSFunctionsSoon();
1192bde8e466a4451c7319e3a072d118917957d6554Steve Block    else
1202bde8e466a4451c7319e3a072d118917957d6554Steve Block        Debugger::recompileAllJSFunctions(JSDOMWindow::commonJSGlobalData());
1212bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1222bde8e466a4451c7319e3a072d118917957d6554Steve Block
1232bde8e466a4451c7319e3a072d118917957d6554Steve BlockScriptDebugServer::ListenerSet* PageScriptDebugServer::getListenersForGlobalObject(JSGlobalObject* globalObject)
1242bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1252bde8e466a4451c7319e3a072d118917957d6554Steve Block    Page* page = toPage(globalObject);
1262bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!page)
1272bde8e466a4451c7319e3a072d118917957d6554Steve Block        return 0;
1282bde8e466a4451c7319e3a072d118917957d6554Steve Block    return m_pageListenersMap.get(page);
1292bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1302bde8e466a4451c7319e3a072d118917957d6554Steve Block
1312bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::didPause(JSC::JSGlobalObject* globalObject)
1322bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1332bde8e466a4451c7319e3a072d118917957d6554Steve Block    Page* page = toPage(globalObject);
1342bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_pausedPage = page;
1352bde8e466a4451c7319e3a072d118917957d6554Steve Block    setJavaScriptPaused(page->group(), true);
1362bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1372bde8e466a4451c7319e3a072d118917957d6554Steve Block
1382bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::didContinue(JSC::JSGlobalObject* globalObject)
1392bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1402bde8e466a4451c7319e3a072d118917957d6554Steve Block    Page* page = toPage(globalObject);
1412bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_pausedPage = 0;
1422bde8e466a4451c7319e3a072d118917957d6554Steve Block    setJavaScriptPaused(page->group(), false);
1432bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1442bde8e466a4451c7319e3a072d118917957d6554Steve Block
1452bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::didRemoveLastListener(Page* page)
1462bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1472bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (m_pausedPage == page)
1482bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_doneProcessingDebuggerEvents = true;
1492bde8e466a4451c7319e3a072d118917957d6554Steve Block
1502bde8e466a4451c7319e3a072d118917957d6554Steve Block    recompileAllJSFunctionsSoon();
1512bde8e466a4451c7319e3a072d118917957d6554Steve Block    page->setDebugger(0);
1522bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1532bde8e466a4451c7319e3a072d118917957d6554Steve Block
1542bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::setJavaScriptPaused(const PageGroup& pageGroup, bool paused)
1552bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1562bde8e466a4451c7319e3a072d118917957d6554Steve Block    setMainThreadCallbacksPaused(paused);
1572bde8e466a4451c7319e3a072d118917957d6554Steve Block
1582bde8e466a4451c7319e3a072d118917957d6554Steve Block    const HashSet<Page*>& pages = pageGroup.pages();
1592bde8e466a4451c7319e3a072d118917957d6554Steve Block
1602bde8e466a4451c7319e3a072d118917957d6554Steve Block    HashSet<Page*>::const_iterator end = pages.end();
1612bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it)
1622bde8e466a4451c7319e3a072d118917957d6554Steve Block        setJavaScriptPaused(*it, paused);
1632bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1642bde8e466a4451c7319e3a072d118917957d6554Steve Block
1652bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::setJavaScriptPaused(Page* page, bool paused)
1662bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1672bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT_ARG(page, page);
1682bde8e466a4451c7319e3a072d118917957d6554Steve Block
1692bde8e466a4451c7319e3a072d118917957d6554Steve Block    page->setDefersLoading(paused);
1702bde8e466a4451c7319e3a072d118917957d6554Steve Block
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
1722bde8e466a4451c7319e3a072d118917957d6554Steve Block        setJavaScriptPaused(frame, paused);
1732bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1742bde8e466a4451c7319e3a072d118917957d6554Steve Block
1752bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused)
1762bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1772bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT_ARG(frame, frame);
1782bde8e466a4451c7319e3a072d118917957d6554Steve Block
1792bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
1802bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
1812bde8e466a4451c7319e3a072d118917957d6554Steve Block
1822bde8e466a4451c7319e3a072d118917957d6554Steve Block    frame->script()->setPaused(paused);
1832bde8e466a4451c7319e3a072d118917957d6554Steve Block
1842bde8e466a4451c7319e3a072d118917957d6554Steve Block    Document* document = frame->document();
1852bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (paused) {
1862bde8e466a4451c7319e3a072d118917957d6554Steve Block        document->suspendScriptedAnimationControllerCallbacks();
1872bde8e466a4451c7319e3a072d118917957d6554Steve Block        document->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused);
1882bde8e466a4451c7319e3a072d118917957d6554Steve Block    } else {
1892bde8e466a4451c7319e3a072d118917957d6554Steve Block        document->resumeActiveDOMObjects();
1902bde8e466a4451c7319e3a072d118917957d6554Steve Block        document->resumeScriptedAnimationControllerCallbacks();
1912bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1922bde8e466a4451c7319e3a072d118917957d6554Steve Block
1932bde8e466a4451c7319e3a072d118917957d6554Steve Block    setJavaScriptPaused(frame->view(), paused);
1942bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1952bde8e466a4451c7319e3a072d118917957d6554Steve Block
1962bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid PageScriptDebugServer::setJavaScriptPaused(FrameView* view, bool paused)
1972bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1982bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!view)
1992bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
2002bde8e466a4451c7319e3a072d118917957d6554Steve Block
2012bde8e466a4451c7319e3a072d118917957d6554Steve Block    const HashSet<RefPtr<Widget> >* children = view->children();
2022bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(children);
2032bde8e466a4451c7319e3a072d118917957d6554Steve Block
2042bde8e466a4451c7319e3a072d118917957d6554Steve Block    HashSet<RefPtr<Widget> >::const_iterator end = children->end();
2052bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
2062bde8e466a4451c7319e3a072d118917957d6554Steve Block        Widget* widget = (*it).get();
2072bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!widget->isPluginView())
2082bde8e466a4451c7319e3a072d118917957d6554Steve Block            continue;
2092bde8e466a4451c7319e3a072d118917957d6554Steve Block        static_cast<PluginView*>(widget)->setJavaScriptPaused(paused);
2102bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2112bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2122bde8e466a4451c7319e3a072d118917957d6554Steve Block
2132bde8e466a4451c7319e3a072d118917957d6554Steve Block} // namespace WebCore
2142bde8e466a4451c7319e3a072d118917957d6554Steve Block
2152bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif // ENABLE(JAVASCRIPT_DEBUGGER)
216