Home | History | Annotate | Download | only in inspector
      1 /*
      2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Matt Lilek <webkit (at) mattlilek.com>
      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  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     15  *     its contributors may be used to endorse or promote products derived
     16  *     from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include "config.h"
     31 #include "InspectorBackend.h"
     32 
     33 #if ENABLE(INSPECTOR)
     34 
     35 #if ENABLE(DATABASE)
     36 #include "Database.h"
     37 #endif
     38 
     39 #include "Element.h"
     40 #include "Frame.h"
     41 #include "FrameLoader.h"
     42 #include "HTMLFrameOwnerElement.h"
     43 #include "InjectedScript.h"
     44 #include "InjectedScriptHost.h"
     45 #include "InspectorClient.h"
     46 #include "InspectorController.h"
     47 #include "InspectorDOMAgent.h"
     48 #include "InspectorFrontend.h"
     49 #include "InspectorResource.h"
     50 #include "Pasteboard.h"
     51 #include "ScriptArray.h"
     52 #include "SerializedScriptValue.h"
     53 
     54 #if ENABLE(DOM_STORAGE)
     55 #include "Storage.h"
     56 #endif
     57 
     58 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
     59 #include "JavaScriptCallFrame.h"
     60 #include "JavaScriptDebugServer.h"
     61 using namespace JSC;
     62 #endif
     63 
     64 #include "markup.h"
     65 
     66 #include <wtf/RefPtr.h>
     67 #include <wtf/StdLibExtras.h>
     68 
     69 using namespace std;
     70 
     71 namespace WebCore {
     72 
     73 InspectorBackend::InspectorBackend(InspectorController* inspectorController)
     74     : m_inspectorController(inspectorController)
     75 {
     76 }
     77 
     78 InspectorBackend::~InspectorBackend()
     79 {
     80 }
     81 
     82 void InspectorBackend::saveFrontendSettings(const String& settings)
     83 {
     84     if (m_inspectorController)
     85         m_inspectorController->setSetting(InspectorController::FrontendSettingsSettingName, settings);
     86 }
     87 
     88 void InspectorBackend::storeLastActivePanel(const String& panelName)
     89 {
     90     if (m_inspectorController)
     91         m_inspectorController->storeLastActivePanel(panelName);
     92 }
     93 
     94 void InspectorBackend::toggleNodeSearch()
     95 {
     96     if (m_inspectorController)
     97         m_inspectorController->toggleSearchForNodeInPage();
     98 }
     99 
    100 bool InspectorBackend::searchingForNode()
    101 {
    102     if (m_inspectorController)
    103         return m_inspectorController->searchingForNodeInPage();
    104     return false;
    105 }
    106 
    107 bool InspectorBackend::resourceTrackingEnabled() const
    108 {
    109     if (m_inspectorController)
    110         return m_inspectorController->resourceTrackingEnabled();
    111     return false;
    112 }
    113 
    114 void InspectorBackend::enableResourceTracking(bool always)
    115 {
    116     if (m_inspectorController)
    117         m_inspectorController->enableResourceTracking(always);
    118 }
    119 
    120 void InspectorBackend::disableResourceTracking(bool always)
    121 {
    122     if (m_inspectorController)
    123         m_inspectorController->disableResourceTracking(always);
    124 }
    125 
    126 void InspectorBackend::getResourceContent(long callId, unsigned long identifier)
    127 {
    128     InspectorFrontend* frontend = inspectorFrontend();
    129     if (!frontend)
    130         return;
    131 
    132     RefPtr<InspectorResource> resource = m_inspectorController->resources().get(identifier);
    133     if (resource)
    134         frontend->didGetResourceContent(callId, resource->sourceString());
    135     else
    136         frontend->didGetResourceContent(callId, "");
    137 }
    138 
    139 void InspectorBackend::startTimelineProfiler()
    140 {
    141     if (m_inspectorController)
    142         m_inspectorController->startTimelineProfiler();
    143 }
    144 
    145 void InspectorBackend::stopTimelineProfiler()
    146 {
    147     if (m_inspectorController)
    148         m_inspectorController->stopTimelineProfiler();
    149 }
    150 
    151 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
    152 bool InspectorBackend::debuggerEnabled() const
    153 {
    154     if (m_inspectorController)
    155         return m_inspectorController->debuggerEnabled();
    156     return false;
    157 }
    158 
    159 void InspectorBackend::enableDebugger(bool always)
    160 {
    161     if (m_inspectorController)
    162         m_inspectorController->enableDebuggerFromFrontend(always);
    163 }
    164 
    165 void InspectorBackend::disableDebugger(bool always)
    166 {
    167     if (m_inspectorController)
    168         m_inspectorController->disableDebugger(always);
    169 }
    170 
    171 void InspectorBackend::addBreakpoint(const String& sourceID, unsigned lineNumber, const String& condition)
    172 {
    173     intptr_t sourceIDValue = sourceID.toIntPtr();
    174     JavaScriptDebugServer::shared().addBreakpoint(sourceIDValue, lineNumber, condition);
    175 }
    176 
    177 void InspectorBackend::updateBreakpoint(const String& sourceID, unsigned lineNumber, const String& condition)
    178 {
    179     intptr_t sourceIDValue = sourceID.toIntPtr();
    180     JavaScriptDebugServer::shared().updateBreakpoint(sourceIDValue, lineNumber, condition);
    181 }
    182 
    183 void InspectorBackend::removeBreakpoint(const String& sourceID, unsigned lineNumber)
    184 {
    185     intptr_t sourceIDValue = sourceID.toIntPtr();
    186     JavaScriptDebugServer::shared().removeBreakpoint(sourceIDValue, lineNumber);
    187 }
    188 
    189 void InspectorBackend::pauseInDebugger()
    190 {
    191     JavaScriptDebugServer::shared().pauseProgram();
    192 }
    193 
    194 void InspectorBackend::resumeDebugger()
    195 {
    196     if (m_inspectorController)
    197         m_inspectorController->resumeDebugger();
    198 }
    199 
    200 void InspectorBackend::stepOverStatementInDebugger()
    201 {
    202     JavaScriptDebugServer::shared().stepOverStatement();
    203 }
    204 
    205 void InspectorBackend::stepIntoStatementInDebugger()
    206 {
    207     JavaScriptDebugServer::shared().stepIntoStatement();
    208 }
    209 
    210 void InspectorBackend::stepOutOfFunctionInDebugger()
    211 {
    212     JavaScriptDebugServer::shared().stepOutOfFunction();
    213 }
    214 
    215 long InspectorBackend::pauseOnExceptionsState()
    216 {
    217     return JavaScriptDebugServer::shared().pauseOnExceptionsState();
    218 }
    219 
    220 void InspectorBackend::setPauseOnExceptionsState(long pauseState)
    221 {
    222     JavaScriptDebugServer::shared().setPauseOnExceptionsState(static_cast<JavaScriptDebugServer::PauseOnExceptionsState>(pauseState));
    223 }
    224 
    225 JavaScriptCallFrame* InspectorBackend::currentCallFrame() const
    226 {
    227     return JavaScriptDebugServer::shared().currentCallFrame();
    228 }
    229 #endif
    230 
    231 #if ENABLE(JAVASCRIPT_DEBUGGER)
    232 bool InspectorBackend::profilerEnabled()
    233 {
    234     if (m_inspectorController)
    235         return m_inspectorController->profilerEnabled();
    236     return false;
    237 }
    238 
    239 void InspectorBackend::enableProfiler(bool always)
    240 {
    241     if (m_inspectorController)
    242         m_inspectorController->enableProfiler(always);
    243 }
    244 
    245 void InspectorBackend::disableProfiler(bool always)
    246 {
    247     if (m_inspectorController)
    248         m_inspectorController->disableProfiler(always);
    249 }
    250 
    251 void InspectorBackend::startProfiling()
    252 {
    253     if (m_inspectorController)
    254         m_inspectorController->startUserInitiatedProfiling();
    255 }
    256 
    257 void InspectorBackend::stopProfiling()
    258 {
    259     if (m_inspectorController)
    260         m_inspectorController->stopUserInitiatedProfiling();
    261 }
    262 
    263 void InspectorBackend::getProfileHeaders(long callId)
    264 {
    265     if (m_inspectorController)
    266         m_inspectorController->getProfileHeaders(callId);
    267 }
    268 
    269 void InspectorBackend::getProfile(long callId, unsigned uid)
    270 {
    271     if (m_inspectorController)
    272         m_inspectorController->getProfile(callId, uid);
    273 }
    274 #endif
    275 
    276 void InspectorBackend::setInjectedScriptSource(const String& source)
    277 {
    278     if (m_inspectorController)
    279         m_inspectorController->injectedScriptHost()->setInjectedScriptSource(source);
    280 }
    281 
    282 void InspectorBackend::dispatchOnInjectedScript(long callId, long injectedScriptId, const String& methodName, const String& arguments, bool async)
    283 {
    284     InspectorFrontend* frontend = inspectorFrontend();
    285     if (!frontend)
    286         return;
    287 
    288     // FIXME: explicitly pass injectedScriptId along with node id to the frontend.
    289     bool injectedScriptIdIsNodeId = injectedScriptId <= 0;
    290 
    291     InjectedScript injectedScript;
    292     if (injectedScriptIdIsNodeId)
    293         injectedScript = m_inspectorController->injectedScriptForNodeId(-injectedScriptId);
    294     else
    295         injectedScript = m_inspectorController->injectedScriptHost()->injectedScriptForId(injectedScriptId);
    296 
    297     if (injectedScript.hasNoValue())
    298         return;
    299 
    300     RefPtr<SerializedScriptValue> result;
    301     bool hadException = false;
    302     injectedScript.dispatch(callId, methodName, arguments, async, &result, &hadException);
    303     if (async)
    304         return;  // InjectedScript will return result asynchronously by means of ::reportDidDispatchOnInjectedScript.
    305     frontend->didDispatchOnInjectedScript(callId, result.get(), hadException);
    306 }
    307 
    308 void InspectorBackend::getChildNodes(long callId, long nodeId)
    309 {
    310     if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
    311         domAgent->getChildNodes(callId, nodeId);
    312 }
    313 
    314 void InspectorBackend::setAttribute(long callId, long elementId, const String& name, const String& value)
    315 {
    316     if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
    317         domAgent->setAttribute(callId, elementId, name, value);
    318 }
    319 
    320 void InspectorBackend::removeAttribute(long callId, long elementId, const String& name)
    321 {
    322     if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
    323         domAgent->removeAttribute(callId, elementId, name);
    324 }
    325 
    326 void InspectorBackend::setTextNodeValue(long callId, long nodeId, const String& value)
    327 {
    328     if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
    329         domAgent->setTextNodeValue(callId, nodeId, value);
    330 }
    331 
    332 void InspectorBackend::getEventListenersForNode(long callId, long nodeId)
    333 {
    334     if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
    335         domAgent->getEventListenersForNode(callId, nodeId);
    336 }
    337 
    338 void InspectorBackend::copyNode(long nodeId)
    339 {
    340     Node* node = nodeForId(nodeId);
    341     if (!node)
    342         return;
    343     String markup = createMarkup(node);
    344     Pasteboard::generalPasteboard()->writePlainText(markup);
    345 }
    346 
    347 void InspectorBackend::removeNode(long callId, long nodeId)
    348 {
    349     InspectorFrontend* frontend = inspectorFrontend();
    350     if (!frontend)
    351         return;
    352 
    353     Node* node = nodeForId(nodeId);
    354     if (!node) {
    355         // Use -1 to denote an error condition.
    356         frontend->didRemoveNode(callId, -1);
    357         return;
    358     }
    359 
    360     Node* parentNode = node->parentNode();
    361     if (!parentNode) {
    362         frontend->didRemoveNode(callId, -1);
    363         return;
    364     }
    365 
    366     ExceptionCode code;
    367     parentNode->removeChild(node, code);
    368     if (code) {
    369         frontend->didRemoveNode(callId, -1);
    370         return;
    371     }
    372 
    373     frontend->didRemoveNode(callId, nodeId);
    374 }
    375 
    376 void InspectorBackend::highlightDOMNode(long nodeId)
    377 {
    378     if (Node* node = nodeForId(nodeId))
    379         m_inspectorController->highlight(node);
    380 }
    381 
    382 void InspectorBackend::hideDOMNodeHighlight()
    383 {
    384     if (m_inspectorController)
    385         m_inspectorController->hideHighlight();
    386 }
    387 
    388 void InspectorBackend::getCookies(long callId)
    389 {
    390     if (!m_inspectorController)
    391         return;
    392     m_inspectorController->getCookies(callId);
    393 }
    394 
    395 void InspectorBackend::deleteCookie(const String& cookieName, const String& domain)
    396 {
    397     if (!m_inspectorController)
    398         return;
    399     m_inspectorController->deleteCookie(cookieName, domain);
    400 }
    401 
    402 void InspectorBackend::releaseWrapperObjectGroup(long injectedScriptId, const String& objectGroup)
    403 {
    404     if (!m_inspectorController)
    405         return;
    406     m_inspectorController->injectedScriptHost()->releaseWrapperObjectGroup(injectedScriptId, objectGroup);
    407 }
    408 
    409 void InspectorBackend::didEvaluateForTestInFrontend(long callId, const String& jsonResult)
    410 {
    411     if (m_inspectorController)
    412         m_inspectorController->didEvaluateForTestInFrontend(callId, jsonResult);
    413 }
    414 
    415 #if ENABLE(DATABASE)
    416 void InspectorBackend::getDatabaseTableNames(long callId, long databaseId)
    417 {
    418     if (InspectorFrontend* frontend = inspectorFrontend()) {
    419         ScriptArray result = frontend->newScriptArray();
    420         Database* database = m_inspectorController->databaseForId(databaseId);
    421         if (database) {
    422             Vector<String> tableNames = database->tableNames();
    423             unsigned length = tableNames.size();
    424             for (unsigned i = 0; i < length; ++i)
    425                 result.set(i, tableNames[i]);
    426         }
    427         frontend->didGetDatabaseTableNames(callId, result);
    428     }
    429 }
    430 #endif
    431 
    432 #if ENABLE(DOM_STORAGE)
    433 void InspectorBackend::getDOMStorageEntries(long callId, long storageId)
    434 {
    435     if (m_inspectorController)
    436         m_inspectorController->getDOMStorageEntries(callId, storageId);
    437 }
    438 
    439 void InspectorBackend::setDOMStorageItem(long callId, long storageId, const String& key, const String& value)
    440 {
    441     if (m_inspectorController)
    442         m_inspectorController->setDOMStorageItem(callId, storageId, key, value);
    443 }
    444 
    445 void InspectorBackend::removeDOMStorageItem(long callId, long storageId, const String& key)
    446 {
    447     if (m_inspectorController)
    448         m_inspectorController->removeDOMStorageItem(callId, storageId, key);
    449 }
    450 #endif
    451 
    452 InspectorDOMAgent* InspectorBackend::inspectorDOMAgent()
    453 {
    454     if (!m_inspectorController)
    455         return 0;
    456     return m_inspectorController->domAgent();
    457 }
    458 
    459 InspectorFrontend* InspectorBackend::inspectorFrontend()
    460 {
    461     if (!m_inspectorController)
    462         return 0;
    463     return m_inspectorController->m_frontend.get();
    464 }
    465 
    466 Node* InspectorBackend::nodeForId(long nodeId)
    467 {
    468     if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
    469         return domAgent->nodeForId(nodeId);
    470     return 0;
    471 }
    472 
    473 } // namespace WebCore
    474 
    475 #endif // ENABLE(INSPECTOR)
    476