1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google 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 * 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 "InspectorFrontend.h"
32
33 #if ENABLE(INSPECTOR)
34
35 #include "ConsoleMessage.h"
36 #include "Frame.h"
37 #include "InjectedScript.h"
38 #include "InjectedScriptHost.h"
39 #include "InspectorController.h"
40 #include "Node.h"
41 #include "ScriptFunctionCall.h"
42 #include "ScriptObject.h"
43 #include "ScriptState.h"
44 #include "ScriptString.h"
45 #include "ScriptValue.h"
46 #include "SerializedScriptValue.h"
47 #include <wtf/OwnPtr.h>
48
49 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
50 #include <parser/SourceCode.h>
51 #include <runtime/JSValue.h>
52 #include <runtime/UString.h>
53 #endif
54
55 namespace WebCore {
56
InspectorFrontend(InspectorController * inspectorController,ScriptObject webInspector)57 InspectorFrontend::InspectorFrontend(InspectorController* inspectorController, ScriptObject webInspector)
58 : m_inspectorController(inspectorController)
59 , m_webInspector(webInspector)
60 {
61 }
62
~InspectorFrontend()63 InspectorFrontend::~InspectorFrontend()
64 {
65 m_webInspector = ScriptObject();
66 }
67
newScriptArray()68 ScriptArray InspectorFrontend::newScriptArray()
69 {
70 return ScriptArray::createNew(scriptState());
71 }
72
newScriptObject()73 ScriptObject InspectorFrontend::newScriptObject()
74 {
75 return ScriptObject::createNew(scriptState());
76 }
77
didCommitLoad()78 void InspectorFrontend::didCommitLoad()
79 {
80 callSimpleFunction("didCommitLoad");
81 }
82
populateFrontendSettings(const String & settings)83 void InspectorFrontend::populateFrontendSettings(const String& settings)
84 {
85 ScriptFunctionCall function(m_webInspector, "dispatch");
86 function.appendArgument("populateFrontendSettings");
87 function.appendArgument(settings);
88 function.call();
89 }
90
updateConsoleMessageExpiredCount(unsigned count)91 void InspectorFrontend::updateConsoleMessageExpiredCount(unsigned count)
92 {
93 ScriptFunctionCall function(m_webInspector, "dispatch");
94 function.appendArgument("updateConsoleMessageExpiredCount");
95 function.appendArgument(count);
96 function.call();
97 }
98
addConsoleMessage(const ScriptObject & messageObj,const Vector<ScriptString> & frames,ScriptState * scriptState,const Vector<ScriptValue> arguments,const String & message)99 void InspectorFrontend::addConsoleMessage(const ScriptObject& messageObj, const Vector<ScriptString>& frames, ScriptState* scriptState, const Vector<ScriptValue> arguments, const String& message)
100 {
101 ScriptFunctionCall function(m_webInspector, "dispatch");
102 function.appendArgument("addConsoleMessage");
103 function.appendArgument(messageObj);
104 if (!frames.isEmpty()) {
105 for (unsigned i = 0; i < frames.size(); ++i)
106 function.appendArgument(frames[i]);
107 } else if (!arguments.isEmpty()) {
108 InjectedScript injectedScript = m_inspectorController->injectedScriptHost()->injectedScriptFor(scriptState);
109 for (unsigned i = 0; i < arguments.size(); ++i) {
110 RefPtr<SerializedScriptValue> serializedValue = injectedScript.wrapForConsole(arguments[i]);
111 ScriptValue scriptValue = ScriptValue::deserialize(this->scriptState(), serializedValue.get());
112 if (scriptValue.hasNoValue()) {
113 ASSERT_NOT_REACHED();
114 return;
115 }
116 function.appendArgument(scriptValue);
117 }
118 } else {
119 function.appendArgument(message);
120 }
121 function.call();
122 }
123
updateConsoleMessageRepeatCount(unsigned count)124 void InspectorFrontend::updateConsoleMessageRepeatCount(unsigned count)
125 {
126 ScriptFunctionCall function(m_webInspector, "dispatch");
127 function.appendArgument("updateConsoleMessageRepeatCount");
128 function.appendArgument(count);
129 function.call();
130 }
131
clearConsoleMessages()132 void InspectorFrontend::clearConsoleMessages()
133 {
134 callSimpleFunction("clearConsoleMessages");
135 }
136
updateResource(unsigned long identifier,const ScriptObject & resourceObj)137 bool InspectorFrontend::updateResource(unsigned long identifier, const ScriptObject& resourceObj)
138 {
139 ScriptFunctionCall function(m_webInspector, "dispatch");
140 function.appendArgument("updateResource");
141 function.appendArgument(identifier);
142 function.appendArgument(resourceObj);
143 bool hadException = false;
144 function.call(hadException);
145 return !hadException;
146 }
147
removeResource(unsigned long identifier)148 void InspectorFrontend::removeResource(unsigned long identifier)
149 {
150 ScriptFunctionCall function(m_webInspector, "dispatch");
151 function.appendArgument("removeResource");
152 function.appendArgument(identifier);
153 function.call();
154 }
155
didGetResourceContent(int callId,const String & content)156 void InspectorFrontend::didGetResourceContent(int callId, const String& content)
157 {
158 ScriptFunctionCall function(m_webInspector, "dispatch");
159 function.appendArgument("didGetResourceContent");
160 function.appendArgument(callId);
161 function.appendArgument(content);
162 function.call();
163 }
164
updateFocusedNode(long nodeId)165 void InspectorFrontend::updateFocusedNode(long nodeId)
166 {
167 ScriptFunctionCall function(m_webInspector, "dispatch");
168 function.appendArgument("updateFocusedNode");
169 function.appendArgument(nodeId);
170 function.call();
171 }
172
setAttachedWindow(bool attached)173 void InspectorFrontend::setAttachedWindow(bool attached)
174 {
175 ScriptFunctionCall function(m_webInspector, "dispatch");
176 function.appendArgument("setAttachedWindow");
177 function.appendArgument(attached);
178 function.call();
179 }
180
showPanel(int panel)181 void InspectorFrontend::showPanel(int panel)
182 {
183 const char* showFunctionName;
184 switch (panel) {
185 case InspectorController::ConsolePanel:
186 showFunctionName = "showConsolePanel";
187 break;
188 case InspectorController::ElementsPanel:
189 showFunctionName = "showElementsPanel";
190 break;
191 case InspectorController::ResourcesPanel:
192 showFunctionName = "showResourcesPanel";
193 break;
194 case InspectorController::ScriptsPanel:
195 showFunctionName = "showScriptsPanel";
196 break;
197 case InspectorController::TimelinePanel:
198 showFunctionName = "showTimelinePanel";
199 break;
200 case InspectorController::ProfilesPanel:
201 showFunctionName = "showProfilesPanel";
202 break;
203 case InspectorController::StoragePanel:
204 showFunctionName = "showStoragePanel";
205 break;
206 default:
207 ASSERT_NOT_REACHED();
208 showFunctionName = 0;
209 }
210
211 if (showFunctionName)
212 callSimpleFunction(showFunctionName);
213 }
214
populateInterface()215 void InspectorFrontend::populateInterface()
216 {
217 callSimpleFunction("populateInterface");
218 }
219
reset()220 void InspectorFrontend::reset()
221 {
222 callSimpleFunction("reset");
223 }
224
resourceTrackingWasEnabled()225 void InspectorFrontend::resourceTrackingWasEnabled()
226 {
227 callSimpleFunction("resourceTrackingWasEnabled");
228 }
229
resourceTrackingWasDisabled()230 void InspectorFrontend::resourceTrackingWasDisabled()
231 {
232 callSimpleFunction("resourceTrackingWasDisabled");
233 }
234
timelineProfilerWasStarted()235 void InspectorFrontend::timelineProfilerWasStarted()
236 {
237 callSimpleFunction("timelineProfilerWasStarted");
238 }
239
timelineProfilerWasStopped()240 void InspectorFrontend::timelineProfilerWasStopped()
241 {
242 callSimpleFunction("timelineProfilerWasStopped");
243 }
244
addRecordToTimeline(const ScriptObject & record)245 void InspectorFrontend::addRecordToTimeline(const ScriptObject& record)
246 {
247 ScriptFunctionCall function(m_webInspector, "dispatch");
248 function.appendArgument("addRecordToTimeline");
249 function.appendArgument(record);
250 function.call();
251 }
252
253 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
attachDebuggerWhenShown()254 void InspectorFrontend::attachDebuggerWhenShown()
255 {
256 callSimpleFunction("attachDebuggerWhenShown");
257 }
258
debuggerWasEnabled()259 void InspectorFrontend::debuggerWasEnabled()
260 {
261 callSimpleFunction("debuggerWasEnabled");
262 }
263
debuggerWasDisabled()264 void InspectorFrontend::debuggerWasDisabled()
265 {
266 callSimpleFunction("debuggerWasDisabled");
267 }
268
parsedScriptSource(const JSC::SourceCode & source)269 void InspectorFrontend::parsedScriptSource(const JSC::SourceCode& source)
270 {
271 ScriptFunctionCall function(m_webInspector, "dispatch");
272 function.appendArgument("parsedScriptSource");
273 function.appendArgument(JSC::UString(JSC::UString::from(source.provider()->asID())));
274 function.appendArgument(source.provider()->url());
275 function.appendArgument(JSC::UString(source.data(), source.length()));
276 function.appendArgument(source.firstLine());
277 function.call();
278 }
279
failedToParseScriptSource(const JSC::SourceCode & source,int errorLine,const JSC::UString & errorMessage)280 void InspectorFrontend::failedToParseScriptSource(const JSC::SourceCode& source, int errorLine, const JSC::UString& errorMessage)
281 {
282 ScriptFunctionCall function(m_webInspector, "dispatch");
283 function.appendArgument("failedToParseScriptSource");
284 function.appendArgument(source.provider()->url());
285 function.appendArgument(JSC::UString(source.data(), source.length()));
286 function.appendArgument(source.firstLine());
287 function.appendArgument(errorLine);
288 function.appendArgument(errorMessage);
289 function.call();
290 }
291
pausedScript(SerializedScriptValue * callFrames)292 void InspectorFrontend::pausedScript(SerializedScriptValue* callFrames)
293 {
294 ScriptValue callFramesValue = ScriptValue::deserialize(scriptState(), callFrames);
295 ScriptFunctionCall function(m_webInspector, "dispatch");
296 function.appendArgument("pausedScript");
297 function.appendArgument(callFramesValue);
298 function.call();
299 }
300
resumedScript()301 void InspectorFrontend::resumedScript()
302 {
303 callSimpleFunction("resumedScript");
304 }
305 #endif
306
307 #if ENABLE(JAVASCRIPT_DEBUGGER)
profilerWasEnabled()308 void InspectorFrontend::profilerWasEnabled()
309 {
310 callSimpleFunction("profilerWasEnabled");
311 }
312
profilerWasDisabled()313 void InspectorFrontend::profilerWasDisabled()
314 {
315 callSimpleFunction("profilerWasDisabled");
316 }
317
addProfileHeader(const ScriptValue & profile)318 void InspectorFrontend::addProfileHeader(const ScriptValue& profile)
319 {
320 ScriptFunctionCall function(m_webInspector, "dispatch");
321 function.appendArgument("addProfileHeader");
322 function.appendArgument(profile);
323 function.call();
324 }
325
setRecordingProfile(bool isProfiling)326 void InspectorFrontend::setRecordingProfile(bool isProfiling)
327 {
328 ScriptFunctionCall function(m_webInspector, "dispatch");
329 function.appendArgument("setRecordingProfile");
330 function.appendArgument(isProfiling);
331 function.call();
332 }
333
didGetProfileHeaders(int callId,const ScriptArray & headers)334 void InspectorFrontend::didGetProfileHeaders(int callId, const ScriptArray& headers)
335 {
336 ScriptFunctionCall function(m_webInspector, "dispatch");
337 function.appendArgument("didGetProfileHeaders");
338 function.appendArgument(callId);
339 function.appendArgument(headers);
340 function.call();
341 }
342
didGetProfile(int callId,const ScriptValue & profile)343 void InspectorFrontend::didGetProfile(int callId, const ScriptValue& profile)
344 {
345 ScriptFunctionCall function(m_webInspector, "dispatch");
346 function.appendArgument("didGetProfile");
347 function.appendArgument(callId);
348 function.appendArgument(profile);
349 function.call();
350 }
351 #endif
352
setDocument(const ScriptObject & root)353 void InspectorFrontend::setDocument(const ScriptObject& root)
354 {
355 ScriptFunctionCall function(m_webInspector, "dispatch");
356 function.appendArgument("setDocument");
357 function.appendArgument(root);
358 function.call();
359 }
360
setDetachedRoot(const ScriptObject & root)361 void InspectorFrontend::setDetachedRoot(const ScriptObject& root)
362 {
363 ScriptFunctionCall function(m_webInspector, "dispatch");
364 function.appendArgument("setDetachedRoot");
365 function.appendArgument(root);
366 function.call();
367 }
368
setChildNodes(int parentId,const ScriptArray & nodes)369 void InspectorFrontend::setChildNodes(int parentId, const ScriptArray& nodes)
370 {
371 ScriptFunctionCall function(m_webInspector, "dispatch");
372 function.appendArgument("setChildNodes");
373 function.appendArgument(parentId);
374 function.appendArgument(nodes);
375 function.call();
376 }
377
childNodeCountUpdated(int id,int newValue)378 void InspectorFrontend::childNodeCountUpdated(int id, int newValue)
379 {
380 ScriptFunctionCall function(m_webInspector, "dispatch");
381 function.appendArgument("childNodeCountUpdated");
382 function.appendArgument(id);
383 function.appendArgument(newValue);
384 function.call();
385 }
386
childNodeInserted(int parentId,int prevId,const ScriptObject & node)387 void InspectorFrontend::childNodeInserted(int parentId, int prevId, const ScriptObject& node)
388 {
389 ScriptFunctionCall function(m_webInspector, "dispatch");
390 function.appendArgument("childNodeInserted");
391 function.appendArgument(parentId);
392 function.appendArgument(prevId);
393 function.appendArgument(node);
394 function.call();
395 }
396
childNodeRemoved(int parentId,int id)397 void InspectorFrontend::childNodeRemoved(int parentId, int id)
398 {
399 ScriptFunctionCall function(m_webInspector, "dispatch");
400 function.appendArgument("childNodeRemoved");
401 function.appendArgument(parentId);
402 function.appendArgument(id);
403 function.call();
404 }
405
attributesUpdated(int id,const ScriptArray & attributes)406 void InspectorFrontend::attributesUpdated(int id, const ScriptArray& attributes)
407 {
408 ScriptFunctionCall function(m_webInspector, "dispatch");
409 function.appendArgument("attributesUpdated");
410 function.appendArgument(id);
411 function.appendArgument(attributes);
412 function.call();
413 }
414
didRemoveNode(int callId,int nodeId)415 void InspectorFrontend::didRemoveNode(int callId, int nodeId)
416 {
417 ScriptFunctionCall function(m_webInspector, "dispatch");
418 function.appendArgument("didRemoveNode");
419 function.appendArgument(callId);
420 function.appendArgument(nodeId);
421 function.call();
422 }
423
didGetChildNodes(int callId)424 void InspectorFrontend::didGetChildNodes(int callId)
425 {
426 ScriptFunctionCall function(m_webInspector, "dispatch");
427 function.appendArgument("didGetChildNodes");
428 function.appendArgument(callId);
429 function.call();
430 }
431
didApplyDomChange(int callId,bool success)432 void InspectorFrontend::didApplyDomChange(int callId, bool success)
433 {
434 ScriptFunctionCall function(m_webInspector, "dispatch");
435 function.appendArgument("didApplyDomChange");
436 function.appendArgument(callId);
437 function.appendArgument(success);
438 function.call();
439 }
440
didGetEventListenersForNode(int callId,int nodeId,ScriptArray & listenersArray)441 void InspectorFrontend::didGetEventListenersForNode(int callId, int nodeId, ScriptArray& listenersArray)
442 {
443 ScriptFunctionCall function(m_webInspector, "dispatch");
444 function.appendArgument("didGetEventListenersForNode");
445 function.appendArgument(callId);
446 function.appendArgument(nodeId);
447 function.appendArgument(listenersArray);
448 function.call();
449 }
450
didGetCookies(int callId,const ScriptArray & cookies,const String & cookiesString)451 void InspectorFrontend::didGetCookies(int callId, const ScriptArray& cookies, const String& cookiesString)
452 {
453 ScriptFunctionCall function(m_webInspector, "dispatch");
454 function.appendArgument("didGetCookies");
455 function.appendArgument(callId);
456 function.appendArgument(cookies);
457 function.appendArgument(cookiesString);
458 function.call();
459 }
460
didDispatchOnInjectedScript(int callId,SerializedScriptValue * result,bool isException)461 void InspectorFrontend::didDispatchOnInjectedScript(int callId, SerializedScriptValue* result, bool isException)
462 {
463 ScriptFunctionCall function(m_webInspector, "dispatch");
464 function.appendArgument("didDispatchOnInjectedScript");
465 function.appendArgument(callId);
466 if (isException)
467 function.appendArgument("");
468 else {
469 ScriptValue resultValue = ScriptValue::deserialize(scriptState(), result);
470 function.appendArgument(resultValue);
471 }
472 function.appendArgument(isException);
473 function.call();
474 }
475
476 #if ENABLE(DATABASE)
addDatabase(const ScriptObject & dbObject)477 bool InspectorFrontend::addDatabase(const ScriptObject& dbObject)
478 {
479 ScriptFunctionCall function(m_webInspector, "dispatch");
480 function.appendArgument("addDatabase");
481 function.appendArgument(dbObject);
482 bool hadException = false;
483 function.call(hadException);
484 return !hadException;
485 }
486
selectDatabase(int databaseId)487 void InspectorFrontend::selectDatabase(int databaseId)
488 {
489 ScriptFunctionCall function(m_webInspector, "dispatch");
490 function.appendArgument("selectDatabase");
491 function.appendArgument(databaseId);
492 function.call();
493 }
didGetDatabaseTableNames(int callId,const ScriptArray & tableNames)494 void InspectorFrontend::didGetDatabaseTableNames(int callId, const ScriptArray& tableNames)
495 {
496 ScriptFunctionCall function(m_webInspector, "dispatch");
497 function.appendArgument("didGetDatabaseTableNames");
498 function.appendArgument(callId);
499 function.appendArgument(tableNames);
500 function.call();
501 }
502 #endif
503
504 #if ENABLE(DOM_STORAGE)
addDOMStorage(const ScriptObject & domStorageObj)505 bool InspectorFrontend::addDOMStorage(const ScriptObject& domStorageObj)
506 {
507 ScriptFunctionCall function(m_webInspector, "dispatch");
508 function.appendArgument("addDOMStorage");
509 function.appendArgument(domStorageObj);
510 bool hadException = false;
511 function.call(hadException);
512 return !hadException;
513 }
514
selectDOMStorage(int storageId)515 void InspectorFrontend::selectDOMStorage(int storageId)
516 {
517 ScriptFunctionCall function(m_webInspector, "dispatch");
518 function.appendArgument("selectDOMStorage");
519 function.appendArgument(storageId);
520 function.call();
521 }
522
didGetDOMStorageEntries(int callId,const ScriptArray & entries)523 void InspectorFrontend::didGetDOMStorageEntries(int callId, const ScriptArray& entries)
524 {
525 ScriptFunctionCall function(m_webInspector, "dispatch");
526 function.appendArgument("didGetDOMStorageEntries");
527 function.appendArgument(callId);
528 function.appendArgument(entries);
529 function.call();
530 }
531
didSetDOMStorageItem(int callId,bool success)532 void InspectorFrontend::didSetDOMStorageItem(int callId, bool success)
533 {
534 ScriptFunctionCall function(m_webInspector, "dispatch");
535 function.appendArgument("didSetDOMStorageItem");
536 function.appendArgument(callId);
537 function.appendArgument(success);
538 function.call();
539 }
540
didRemoveDOMStorageItem(int callId,bool success)541 void InspectorFrontend::didRemoveDOMStorageItem(int callId, bool success)
542 {
543 ScriptFunctionCall function(m_webInspector, "dispatch");
544 function.appendArgument("didRemoveDOMStorageItem");
545 function.appendArgument(callId);
546 function.appendArgument(success);
547 function.call();
548 }
549
updateDOMStorage(int storageId)550 void InspectorFrontend::updateDOMStorage(int storageId)
551 {
552 ScriptFunctionCall function(m_webInspector, "dispatch");
553 function.appendArgument("updateDOMStorage");
554 function.appendArgument(storageId);
555 function.call();
556 }
557 #endif
558
addNodesToSearchResult(const String & nodeIds)559 void InspectorFrontend::addNodesToSearchResult(const String& nodeIds)
560 {
561 ScriptFunctionCall function(m_webInspector, "dispatch");
562 function.appendArgument("addNodesToSearchResult");
563 function.appendArgument(nodeIds);
564 function.call();
565 }
566
contextMenuItemSelected(int itemId)567 void InspectorFrontend::contextMenuItemSelected(int itemId)
568 {
569 ScriptFunctionCall function(m_webInspector, "dispatch");
570 function.appendArgument("contextMenuItemSelected");
571 function.appendArgument(itemId);
572 function.call();
573 }
574
contextMenuCleared()575 void InspectorFrontend::contextMenuCleared()
576 {
577 callSimpleFunction("contextMenuCleared");
578 }
579
evaluateForTestInFrontend(int callId,const String & script)580 void InspectorFrontend::evaluateForTestInFrontend(int callId, const String& script)
581 {
582 ScriptFunctionCall function(m_webInspector, "dispatch");
583 function.appendArgument("evaluateForTestInFrontend");
584 function.appendArgument(callId);
585 function.appendArgument(script);
586 function.call();
587 }
588
callSimpleFunction(const String & functionName)589 void InspectorFrontend::callSimpleFunction(const String& functionName)
590 {
591 ScriptFunctionCall function(m_webInspector, "dispatch");
592 function.appendArgument(functionName);
593 function.call();
594 }
595
596 } // namespace WebCore
597
598 #endif // ENABLE(INSPECTOR)
599