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