2008-05-21 Alp Toker <alp@nuanti.com>
[WebKit-https.git] / WebCore / page / InspectorController.cpp
1 /*
2  * Copyright (C) 2007 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "InspectorController.h"
31
32 #include "CString.h"
33 #include "CachedResource.h"
34 #include "Console.h"
35 #include "DOMWindow.h"
36 #include "DocLoader.h"
37 #include "Document.h"
38 #include "DocumentLoader.h"
39 #include "Element.h"
40 #include "FloatConversion.h"
41 #include "FloatRect.h"
42 #include "Frame.h"
43 #include "FrameLoader.h"
44 #include "FrameTree.h"
45 #include "FrameView.h"
46 #include "GraphicsContext.h"
47 #include "HTMLFrameOwnerElement.h"
48 #include "InspectorClient.h"
49 #include "JavaScriptCallFrame.h"
50 #include "JSDOMWindow.h"
51 #include "JSInspectedObjectWrapper.h"
52 #include "JSInspectorCallbackWrapper.h"
53 #include "JSJavaScriptCallFrame.h"
54 #include "JSNode.h"
55 #include "JSRange.h"
56 #include "JavaScriptDebugServer.h"
57 #include "JavaScriptProfile.h"
58 #include "Page.h"
59 #include "Range.h"
60 #include "ResourceRequest.h"
61 #include "ResourceResponse.h"
62 #include "Settings.h"
63 #include "SharedBuffer.h"
64 #include "SystemTime.h"
65 #include "TextEncoding.h"
66 #include "TextIterator.h"
67 #include "kjs_proxy.h"
68 #include <JavaScriptCore/APICast.h>
69 #include <JavaScriptCore/JSLock.h>
70 #include <JavaScriptCore/JSRetainPtr.h>
71 #include <JavaScriptCore/JSStringRef.h>
72 #include <kjs/ustring.h>
73 #include <profiler/Profile.h>
74 #include <profiler/Profiler.h>
75 #include <wtf/RefCounted.h>
76
77 #if ENABLE(DATABASE)
78 #include "Database.h"
79 #include "JSDatabase.h"
80 #endif
81
82 using namespace KJS;
83 using namespace std;
84
85 namespace WebCore {
86
87 static JSRetainPtr<JSStringRef> jsStringRef(const char* str)
88 {
89     return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(str));
90 }
91
92 static JSRetainPtr<JSStringRef> jsStringRef(const SourceProvider& str)
93 {
94     return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithCharacters(str.data(), str.length()));
95 }
96
97 static JSRetainPtr<JSStringRef> jsStringRef(const String& str)
98 {
99     return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithCharacters(str.characters(), str.length()));
100 }
101
102 static JSRetainPtr<JSStringRef> jsStringRef(const UString& str)
103 {
104     JSLock lock;
105     return JSRetainPtr<JSStringRef>(toRef(str.rep()));
106 }
107
108 static String toString(JSContextRef context, JSValueRef value, JSValueRef* exception)
109 {
110     ASSERT_ARG(value, value);
111     if (!value)
112         return String();
113     JSRetainPtr<JSStringRef> scriptString(Adopt, JSValueToStringCopy(context, value, exception));
114     if (exception && *exception)
115         return String();
116     return String(JSStringGetCharactersPtr(scriptString.get()), JSStringGetLength(scriptString.get()));
117 }
118
119 #define HANDLE_EXCEPTION(context, exception) handleException((context), (exception), __LINE__)
120
121 JSValueRef InspectorController::callSimpleFunction(JSContextRef context, JSObjectRef thisObject, const char* functionName) const
122 {
123     JSValueRef exception = 0;
124     return callFunction(context, thisObject, functionName, 0, 0, exception);
125 }
126
127 JSValueRef InspectorController::callFunction(JSContextRef context, JSObjectRef thisObject, const char* functionName, size_t argumentCount, const JSValueRef arguments[], JSValueRef& exception) const
128 {
129     ASSERT_ARG(context, context);
130     ASSERT_ARG(thisObject, thisObject);
131
132     if (exception)
133         return JSValueMakeUndefined(context);
134
135     JSValueRef functionProperty = JSObjectGetProperty(context, thisObject, jsStringRef(functionName).get(), &exception);
136     if (HANDLE_EXCEPTION(context, exception))
137         return JSValueMakeUndefined(context);
138
139     JSObjectRef function = JSValueToObject(context, functionProperty, &exception);
140     if (HANDLE_EXCEPTION(context, exception))
141         return JSValueMakeUndefined(context);
142
143     JSValueRef result = JSObjectCallAsFunction(context, function, thisObject, argumentCount, arguments, &exception);
144     if (HANDLE_EXCEPTION(context, exception))
145         return JSValueMakeUndefined(context);
146
147     return result;
148 }
149
150 // ConsoleMessage Struct
151
152 struct ConsoleMessage {
153     ConsoleMessage(MessageSource s, MessageLevel l, const String& m, unsigned li, const String& u)
154         : source(s)
155         , level(l)
156         , message(m)
157         , line(li)
158         , url(u)
159     {
160     }
161
162     ConsoleMessage(MessageSource s, MessageLevel l, ExecState* exec, const List& args, unsigned li, const String& u)
163         : source(s)
164         , level(l)
165         , wrappedArguments(args.size())
166         , line(li)
167         , url(u)
168     {
169         JSLock lock;
170         for (unsigned i = 0; i < args.size(); ++i)
171             wrappedArguments[i] = JSInspectedObjectWrapper::wrap(exec, args[i]);
172     }
173
174     MessageSource source;
175     MessageLevel level;
176     String message;
177     Vector<ProtectedPtr<JSValue> > wrappedArguments;
178     unsigned line;
179     String url;
180 };
181
182 // XMLHttpRequestResource Class
183
184 struct XMLHttpRequestResource {
185     XMLHttpRequestResource(KJS::UString& sourceString)
186     {
187         KJS::JSLock lock;
188         this->sourceString = sourceString.rep();
189     }
190
191     ~XMLHttpRequestResource()
192     {
193         KJS::JSLock lock;
194         sourceString.clear();
195     }
196
197     RefPtr<KJS::UString::Rep> sourceString;
198 };
199
200 // InspectorResource Struct
201
202 struct InspectorResource : public RefCounted<InspectorResource> {
203     // Keep these in sync with WebInspector.Resource.Type
204     enum Type {
205         Doc,
206         Stylesheet,
207         Image,
208         Font,
209         Script,
210         XHR,
211         Other
212     };
213
214     static PassRefPtr<InspectorResource> create(long long identifier, DocumentLoader* documentLoader, Frame* frame)
215     {
216         return adoptRef(new InspectorResource(identifier, documentLoader, frame));
217     }
218     
219     ~InspectorResource()
220     {
221         setScriptObject(0, 0);
222     }
223
224     Type type() const
225     {
226         if (xmlHttpRequestResource)
227             return XHR;
228
229         if (requestURL == loader->requestURL())
230             return Doc;
231
232         if (loader->frameLoader() && requestURL == loader->frameLoader()->iconURL())
233             return Image;
234
235         CachedResource* cachedResource = frame->document()->docLoader()->cachedResource(requestURL.string());
236         if (!cachedResource)
237             return Other;
238
239         switch (cachedResource->type()) {
240             case CachedResource::ImageResource:
241                 return Image;
242             case CachedResource::FontResource:
243                 return Font;
244             case CachedResource::CSSStyleSheet:
245 #if ENABLE(XSLT)
246             case CachedResource::XSLStyleSheet:
247 #endif
248                 return Stylesheet;
249             case CachedResource::Script:
250                 return Script;
251             default:
252                 return Other;
253         }
254     }
255
256     void setScriptObject(JSContextRef context, JSObjectRef newScriptObject)
257     {
258         if (scriptContext && scriptObject)
259             JSValueUnprotect(scriptContext, scriptObject);
260
261         scriptObject = newScriptObject;
262         scriptContext = context;
263
264         ASSERT((context && newScriptObject) || (!context && !newScriptObject));
265         if (context && newScriptObject)
266             JSValueProtect(context, newScriptObject);
267     }
268
269     void setXMLHttpRequestProperties(KJS::UString& data)
270     {
271         xmlHttpRequestResource.set(new XMLHttpRequestResource(data));
272     }
273     
274     String sourceString() const
275      {
276          if (xmlHttpRequestResource)
277             return KJS::UString(xmlHttpRequestResource->sourceString);
278
279         RefPtr<SharedBuffer> buffer;
280         String textEncodingName;
281
282         if (requestURL == loader->requestURL()) {
283             buffer = loader->mainResourceData();
284             textEncodingName = frame->document()->inputEncoding();
285         } else {
286             CachedResource* cachedResource = frame->document()->docLoader()->cachedResource(requestURL.string());
287             if (!cachedResource)
288                 return String();
289
290             buffer = cachedResource->data();
291             textEncodingName = cachedResource->encoding();
292         }
293
294         if (!buffer)
295             return String();
296
297         TextEncoding encoding(textEncodingName);
298         if (!encoding.isValid())
299             encoding = WindowsLatin1Encoding();
300         return encoding.decode(buffer->data(), buffer->size());
301      }
302
303     long long identifier;
304     RefPtr<DocumentLoader> loader;
305     RefPtr<Frame> frame;
306     OwnPtr<XMLHttpRequestResource> xmlHttpRequestResource;
307     KURL requestURL;
308     HTTPHeaderMap requestHeaderFields;
309     HTTPHeaderMap responseHeaderFields;
310     String mimeType;
311     String suggestedFilename;
312     JSContextRef scriptContext;
313     JSObjectRef scriptObject;
314     long long expectedContentLength;
315     bool cached;
316     bool finished;
317     bool failed;
318     int length;
319     int responseStatusCode;
320     double startTime;
321     double responseReceivedTime;
322     double endTime;
323
324 protected:
325     InspectorResource(long long identifier, DocumentLoader* documentLoader, Frame* frame)
326         : identifier(identifier)
327         , loader(documentLoader)
328         , frame(frame)
329         , xmlHttpRequestResource(0)
330         , scriptContext(0)
331         , scriptObject(0)
332         , expectedContentLength(0)
333         , cached(false)
334         , finished(false)
335         , failed(false)
336         , length(0)
337         , responseStatusCode(0)
338         , startTime(-1.0)
339         , responseReceivedTime(-1.0)
340         , endTime(-1.0)
341     {
342     }
343 };
344
345 // InspectorDatabaseResource Struct
346
347 #if ENABLE(DATABASE)
348 struct InspectorDatabaseResource : public RefCounted<InspectorDatabaseResource> {
349     static PassRefPtr<InspectorDatabaseResource> create(Database* database, const String& domain, const String& name, const String& version)
350     {
351         return adoptRef(new InspectorDatabaseResource(database, domain, name, version));
352     }
353
354     void setScriptObject(JSContextRef context, JSObjectRef newScriptObject)
355     {
356         if (scriptContext && scriptObject)
357             JSValueUnprotect(scriptContext, scriptObject);
358
359         scriptObject = newScriptObject;
360         scriptContext = context;
361
362         ASSERT((context && newScriptObject) || (!context && !newScriptObject));
363         if (context && newScriptObject)
364             JSValueProtect(context, newScriptObject);
365     }
366
367     RefPtr<Database> database;
368     String domain;
369     String name;
370     String version;
371     JSContextRef scriptContext;
372     JSObjectRef scriptObject;
373     
374 private:
375     InspectorDatabaseResource(Database* database, const String& domain, const String& name, const String& version)
376         : database(database)
377         , domain(domain)
378         , name(name)
379         , version(version)
380         , scriptContext(0)
381         , scriptObject(0)
382     {
383     }
384 };
385 #endif
386
387 // JavaScript Callbacks
388
389 static bool addSourceToFrame(const String& mimeType, const String& source, Node* frameNode)
390 {
391     ASSERT_ARG(frameNode, frameNode);
392
393     if (!frameNode)
394         return false;
395
396     if (!frameNode->attached()) {
397         ASSERT_NOT_REACHED();
398         return false;
399     }
400
401     ASSERT(frameNode->isElementNode());
402     if (!frameNode->isElementNode())
403         return false;
404
405     Element* element = static_cast<Element*>(frameNode);
406     ASSERT(element->isFrameOwnerElement());
407     if (!element->isFrameOwnerElement())
408         return false;
409
410     HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element);
411     ASSERT(frameOwner->contentFrame());
412     if (!frameOwner->contentFrame())
413         return false;
414
415     FrameLoader* loader = frameOwner->contentFrame()->loader();
416
417     loader->setResponseMIMEType(mimeType);
418     loader->begin();
419     loader->write(source);
420     loader->end();
421
422     return true;
423 }
424
425 static JSValueRef addResourceSourceToFrame(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
426 {
427     JSValueRef undefined = JSValueMakeUndefined(ctx);
428
429     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
430     if (argumentCount < 2 || !controller)
431         return undefined;
432
433     JSValueRef identifierValue = arguments[0];
434     if (!JSValueIsNumber(ctx, identifierValue))
435         return undefined;
436
437     long long identifier = static_cast<long long>(JSValueToNumber(ctx, identifierValue, exception));
438     if (exception && *exception)
439         return undefined;
440
441     RefPtr<InspectorResource> resource = controller->resources().get(identifier);
442     ASSERT(resource);
443     if (!resource)
444         return undefined;
445
446     String sourceString = resource->sourceString();
447     if (sourceString.isEmpty())
448         return undefined;
449
450     addSourceToFrame(resource->mimeType, sourceString, toNode(toJS(arguments[1])));
451
452     return undefined;
453 }
454
455 static JSValueRef addSourceToFrame(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
456 {
457     JSValueRef undefined = JSValueMakeUndefined(ctx);
458
459     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
460     if (argumentCount < 3 || !controller)
461         return undefined;
462
463     JSValueRef mimeTypeValue = arguments[0];
464     if (!JSValueIsString(ctx, mimeTypeValue))
465         return undefined;
466
467     JSValueRef sourceValue = arguments[1];
468     if (!JSValueIsString(ctx, sourceValue))
469         return undefined;
470
471     String mimeType = toString(ctx, mimeTypeValue, exception);
472     if (mimeType.isEmpty())
473         return undefined;
474
475     String source = toString(ctx, sourceValue, exception);
476     if (source.isEmpty())
477         return undefined;
478
479     addSourceToFrame(mimeType, source, toNode(toJS(arguments[2])));
480
481     return undefined;
482 }
483
484 static JSValueRef getResourceDocumentNode(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
485 {
486     JSValueRef undefined = JSValueMakeUndefined(ctx);
487
488     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
489     if (!argumentCount || argumentCount > 1 || !controller)
490         return undefined;
491
492     JSValueRef identifierValue = arguments[0];
493     if (!JSValueIsNumber(ctx, identifierValue))
494         return undefined;
495
496     long long identifier = static_cast<long long>(JSValueToNumber(ctx, identifierValue, exception));
497     if (exception && *exception)
498         return undefined;
499
500     RefPtr<InspectorResource> resource = controller->resources().get(identifier);
501     ASSERT(resource);
502     if (!resource)
503         return undefined;
504
505     Frame* frame = resource->frame.get();
506
507     Document* document = frame->document();
508     if (!document)
509         return undefined;
510
511     if (document->isPluginDocument() || document->isImageDocument())
512         return undefined;
513
514     ExecState* exec = toJSDOMWindowShell(resource->frame.get())->window()->globalExec();
515
516     KJS::JSLock lock;
517     JSValueRef documentValue = toRef(JSInspectedObjectWrapper::wrap(exec, toJS(exec, document)));
518     return documentValue;
519 }
520
521 static JSValueRef highlightDOMNode(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
522 {
523     JSValueRef undefined = JSValueMakeUndefined(context);
524
525     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
526     if (argumentCount < 1 || !controller)
527         return undefined;
528
529     JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(toJS(arguments[0]));
530     if (!wrapper)
531         return undefined;
532     Node* node = toNode(wrapper->unwrappedObject());
533     if (!node)
534         return undefined;
535
536     controller->highlight(node);
537
538     return undefined;
539 }
540
541 static JSValueRef hideDOMNodeHighlight(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
542 {
543     JSValueRef undefined = JSValueMakeUndefined(context);
544
545     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
546     if (argumentCount || !controller)
547         return undefined;
548
549     controller->hideHighlight();
550
551     return undefined;
552 }
553
554 static JSValueRef loaded(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
555 {
556     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
557     if (!controller)
558         return JSValueMakeUndefined(ctx);
559
560     controller->scriptObjectReady();
561     return JSValueMakeUndefined(ctx);
562 }
563
564 static JSValueRef unloading(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
565 {
566     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
567     if (!controller)
568         return JSValueMakeUndefined(ctx);
569
570     controller->close();
571     return JSValueMakeUndefined(ctx);
572 }
573
574 static JSValueRef attach(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
575 {
576     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
577     if (!controller)
578         return JSValueMakeUndefined(ctx);
579
580     controller->attachWindow();
581     return JSValueMakeUndefined(ctx);
582 }
583
584 static JSValueRef detach(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
585 {
586     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
587     if (!controller)
588         return JSValueMakeUndefined(ctx);
589
590     controller->detachWindow();
591     return JSValueMakeUndefined(ctx);
592 }
593
594 static JSValueRef search(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
595 {
596     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
597     if (!controller)
598         return JSValueMakeUndefined(ctx);
599
600     if (argumentCount < 2 || !JSValueIsString(ctx, arguments[1]))
601         return JSValueMakeUndefined(ctx);
602
603     Node* node = toNode(toJS(arguments[0]));
604     if (!node)
605         return JSValueMakeUndefined(ctx);
606
607     String target = toString(ctx, arguments[1], exception);
608
609     JSObjectRef global = JSContextGetGlobalObject(ctx);
610
611     JSValueRef arrayProperty = JSObjectGetProperty(ctx, global, jsStringRef("Array").get(), exception);
612     if (exception && *exception)
613         return JSValueMakeUndefined(ctx);
614
615     JSObjectRef arrayConstructor = JSValueToObject(ctx, arrayProperty, exception);
616     if (exception && *exception)
617         return JSValueMakeUndefined(ctx);
618
619     JSObjectRef result = JSObjectCallAsConstructor(ctx, arrayConstructor, 0, 0, exception);
620     if (exception && *exception)
621         return JSValueMakeUndefined(ctx);
622
623     JSValueRef pushProperty = JSObjectGetProperty(ctx, result, jsStringRef("push").get(), exception);
624     if (exception && *exception)
625         return JSValueMakeUndefined(ctx);
626
627     JSObjectRef pushFunction = JSValueToObject(ctx, pushProperty, exception);
628     if (exception && *exception)
629         return JSValueMakeUndefined(ctx);
630
631     RefPtr<Range> searchRange(rangeOfContents(node));
632
633     ExceptionCode ec = 0;
634     do {
635         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false));
636         if (resultRange->collapsed(ec))
637             break;
638
639         // A non-collapsed result range can in some funky whitespace cases still not
640         // advance the range's start position (4509328). Break to avoid infinite loop.
641         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
642         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
643             break;
644
645         KJS::JSLock lock;
646         JSValueRef arg0 = toRef(toJS(toJS(ctx), resultRange.get()));
647         JSObjectCallAsFunction(ctx, pushFunction, result, 1, &arg0, exception);
648         if (exception && *exception)
649             return JSValueMakeUndefined(ctx);
650
651         setStart(searchRange.get(), newStart);
652     } while (true);
653
654     return result;
655 }
656
657 #if ENABLE(DATABASE)
658 static JSValueRef databaseTableNames(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
659 {
660     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
661     if (!controller)
662         return JSValueMakeUndefined(ctx);
663
664     if (argumentCount < 1)
665         return JSValueMakeUndefined(ctx);
666
667     JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(toJS(arguments[0]));
668     if (!wrapper)
669         return JSValueMakeUndefined(ctx);
670
671     Database* database = toDatabase(wrapper->unwrappedObject());
672     if (!database)
673         return JSValueMakeUndefined(ctx);
674
675     JSObjectRef global = JSContextGetGlobalObject(ctx);
676
677     JSValueRef arrayProperty = JSObjectGetProperty(ctx, global, jsStringRef("Array").get(), exception);
678     if (exception && *exception)
679         return JSValueMakeUndefined(ctx);
680
681     JSObjectRef arrayConstructor = JSValueToObject(ctx, arrayProperty, exception);
682     if (exception && *exception)
683         return JSValueMakeUndefined(ctx);
684
685     JSObjectRef result = JSObjectCallAsConstructor(ctx, arrayConstructor, 0, 0, exception);
686     if (exception && *exception)
687         return JSValueMakeUndefined(ctx);
688
689     JSValueRef pushProperty = JSObjectGetProperty(ctx, result, jsStringRef("push").get(), exception);
690     if (exception && *exception)
691         return JSValueMakeUndefined(ctx);
692
693     JSObjectRef pushFunction = JSValueToObject(ctx, pushProperty, exception);
694     if (exception && *exception)
695         return JSValueMakeUndefined(ctx);
696
697     Vector<String> tableNames = database->tableNames();
698     unsigned length = tableNames.size();
699     for (unsigned i = 0; i < length; ++i) {
700         String tableName = tableNames[i];
701         JSValueRef tableNameValue = JSValueMakeString(ctx, jsStringRef(tableName).get());
702
703         JSValueRef pushArguments[] = { tableNameValue };
704         JSObjectCallAsFunction(ctx, pushFunction, result, 1, pushArguments, exception);
705         if (exception && *exception)
706             return JSValueMakeUndefined(ctx);
707     }
708
709     return result;
710 }
711 #endif
712
713 static JSValueRef inspectedWindow(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
714 {
715     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
716     if (!controller)
717         return JSValueMakeUndefined(ctx);
718
719     JSDOMWindow* inspectedWindow = toJSDOMWindow(controller->inspectedPage()->mainFrame());
720     JSLock lock;
721     return toRef(JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), inspectedWindow));
722 }
723
724 static JSValueRef localizedStrings(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
725 {
726     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
727     if (!controller)
728         return JSValueMakeUndefined(ctx);
729
730     String url = controller->localizedStringsURL();
731     if (url.isNull())
732         return JSValueMakeNull(ctx);
733
734     return JSValueMakeString(ctx, jsStringRef(url).get());
735 }
736
737 static JSValueRef platform(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
738 {
739 #if PLATFORM(MAC)
740 #ifdef BUILDING_ON_TIGER
741     static const String platform = "mac-tiger";
742 #else
743     static const String platform = "mac-leopard";
744 #endif
745 #elif PLATFORM(WIN_OS)
746     static const String platform = "windows";
747 #elif PLATFORM(QT)
748     static const String platform = "qt";
749 #elif PLATFORM(GTK)
750     static const String platform = "gtk";
751 #elif PLATFORM(WX)
752     static const String platform = "wx";
753 #else
754     static const String platform = "unknown";
755 #endif
756
757     JSValueRef platformValue = JSValueMakeString(ctx, jsStringRef(platform).get());
758
759     return platformValue;
760 }
761
762 static JSValueRef moveByUnrestricted(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
763 {
764     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
765     if (!controller)
766         return JSValueMakeUndefined(ctx);
767
768     if (argumentCount < 2)
769         return JSValueMakeUndefined(ctx);
770
771     double x = JSValueToNumber(ctx, arguments[0], exception);
772     if (exception && *exception)
773         return JSValueMakeUndefined(ctx);
774
775     double y = JSValueToNumber(ctx, arguments[1], exception);
776     if (exception && *exception)
777         return JSValueMakeUndefined(ctx);
778
779     controller->moveWindowBy(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y));
780
781     return JSValueMakeUndefined(ctx);
782 }
783
784 static JSValueRef wrapCallback(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
785 {
786     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
787     if (!controller)
788         return JSValueMakeUndefined(ctx);
789
790     if (argumentCount < 1)
791         return JSValueMakeUndefined(ctx);
792
793     JSLock lock;
794     return toRef(JSInspectorCallbackWrapper::wrap(toJS(ctx), toJS(arguments[0])));
795 }
796
797 static JSValueRef startDebuggingAndReloadInspectedPage(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
798 {
799     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
800     if (!controller)
801         return JSValueMakeUndefined(ctx);
802
803     controller->startDebuggingAndReloadInspectedPage();
804
805     return JSValueMakeUndefined(ctx);
806 }
807
808 static JSValueRef stopDebugging(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
809 {
810     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
811     if (!controller)
812         return JSValueMakeUndefined(ctx);
813
814     controller->stopDebugging();
815
816     return JSValueMakeUndefined(ctx);
817 }
818
819 static JSValueRef debuggerAttached(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
820 {
821     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
822     if (!controller)
823         return JSValueMakeUndefined(ctx);
824     return JSValueMakeBoolean(ctx, controller->debuggerAttached());
825 }
826
827 static JSValueRef currentCallFrame(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
828 {
829     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
830     if (!controller)
831         return JSValueMakeUndefined(ctx);
832
833     JavaScriptCallFrame* callFrame = controller->currentCallFrame();
834     if (!callFrame || !callFrame->isValid())
835         return JSValueMakeNull(ctx);
836
837     ExecState* globalExec = callFrame->scopeChain()->globalObject()->globalExec();
838
839     JSLock lock;
840     return toRef(JSInspectedObjectWrapper::wrap(globalExec, toJS(toJS(ctx), callFrame)));
841 }
842
843 static JSValueRef pauseOnExceptions(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
844 {
845     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
846     if (!controller)
847         return JSValueMakeUndefined(ctx);
848     return JSValueMakeBoolean(ctx, controller->pauseOnExceptions());
849 }
850
851 static JSValueRef setPauseOnExceptions(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
852 {
853     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
854     if (!controller)
855         return JSValueMakeUndefined(ctx);
856
857     if (argumentCount < 1)
858         return JSValueMakeUndefined(ctx);
859
860     controller->setPauseOnExceptions(JSValueToBoolean(ctx, arguments[0]));
861
862     return JSValueMakeUndefined(ctx);
863 }
864
865 static JSValueRef pauseInDebugger(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
866 {
867     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
868     if (!controller)
869         return JSValueMakeUndefined(ctx);
870
871     controller->pauseInDebugger();
872
873     return JSValueMakeUndefined(ctx);
874 }
875
876 static JSValueRef resumeDebugger(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
877 {
878     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
879     if (!controller)
880         return JSValueMakeUndefined(ctx);
881
882     controller->resumeDebugger();
883
884     return JSValueMakeUndefined(ctx);
885 }
886
887 static JSValueRef stepOverStatementInDebugger(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
888 {
889     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
890     if (!controller)
891         return JSValueMakeUndefined(ctx);
892
893     controller->stepOverStatementInDebugger();
894
895     return JSValueMakeUndefined(ctx);
896 }
897
898 static JSValueRef stepIntoStatementInDebugger(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
899 {
900     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
901     if (!controller)
902         return JSValueMakeUndefined(ctx);
903
904     controller->stepIntoStatementInDebugger();
905
906     return JSValueMakeUndefined(ctx);
907 }
908
909 static JSValueRef stepOutOfFunctionInDebugger(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
910 {
911     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
912     if (!controller)
913         return JSValueMakeUndefined(ctx);
914
915     controller->stepOutOfFunctionInDebugger();
916
917     return JSValueMakeUndefined(ctx);
918 }
919
920 static JSValueRef addBreakpoint(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
921 {
922     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
923     if (!controller)
924         return JSValueMakeUndefined(ctx);
925
926     if (argumentCount < 2)
927         return JSValueMakeUndefined(ctx);
928
929     double sourceID = JSValueToNumber(ctx, arguments[0], exception);
930     if (exception && *exception)
931         return JSValueMakeUndefined(ctx);
932
933     double lineNumber = JSValueToNumber(ctx, arguments[1], exception);
934     if (exception && *exception)
935         return JSValueMakeUndefined(ctx);
936
937     controller->addBreakpoint(static_cast<int>(sourceID), static_cast<unsigned>(lineNumber));
938
939     return JSValueMakeUndefined(ctx);
940 }
941
942 static JSValueRef removeBreakpoint(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
943 {
944     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
945     if (!controller)
946         return JSValueMakeUndefined(ctx);
947
948     if (argumentCount < 2)
949         return JSValueMakeUndefined(ctx);
950
951     double sourceID = JSValueToNumber(ctx, arguments[0], exception);
952     if (exception && *exception)
953         return JSValueMakeUndefined(ctx);
954
955     double lineNumber = JSValueToNumber(ctx, arguments[1], exception);
956     if (exception && *exception)
957         return JSValueMakeUndefined(ctx);
958
959     controller->removeBreakpoint(static_cast<int>(sourceID), static_cast<unsigned>(lineNumber));
960
961     return JSValueMakeUndefined(ctx);
962 }
963
964 // Profiles
965
966 static JSValueRef profiles(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* exception)
967 {
968     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
969     if (!controller)
970         return JSValueMakeUndefined(ctx);
971
972     JSLock lock;
973
974     const Vector<RefPtr<Profile> >& profiles = controller->profiles();
975
976     JSObjectRef global = JSContextGetGlobalObject(ctx);
977
978     JSValueRef arrayProperty = JSObjectGetProperty(ctx, global, jsStringRef("Array").get(), exception);
979     if (exception && *exception)
980         return JSValueMakeUndefined(ctx);
981
982     JSObjectRef arrayConstructor = JSValueToObject(ctx, arrayProperty, exception);
983     if (exception && *exception)
984         return JSValueMakeUndefined(ctx);
985
986     JSObjectRef result = JSObjectCallAsConstructor(ctx, arrayConstructor, 0, 0, exception);
987     if (exception && *exception)
988         return JSValueMakeUndefined(ctx);
989
990     JSValueRef pushProperty = JSObjectGetProperty(ctx, result, jsStringRef("push").get(), exception);
991     if (exception && *exception)
992         return JSValueMakeUndefined(ctx);
993
994     JSObjectRef pushFunction = JSValueToObject(ctx, pushProperty, exception);
995     if (exception && *exception)
996         return JSValueMakeUndefined(ctx);
997
998     for (size_t i = 0; i < profiles.size(); ++i) {
999         JSValueRef arg0 = toRef(toJS(toJS(ctx), profiles[i].get()));
1000         JSObjectCallAsFunction(ctx, pushFunction, result, 1, &arg0, exception);
1001         if (exception && *exception)
1002             return JSValueMakeUndefined(ctx);
1003     }
1004
1005     return result;
1006 }
1007
1008 // InspectorController Class
1009
1010 InspectorController::InspectorController(Page* page, InspectorClient* client)
1011     : m_inspectedPage(page)
1012     , m_client(client)
1013     , m_page(0)
1014     , m_scriptObject(0)
1015     , m_controllerScriptObject(0)
1016     , m_scriptContext(0)
1017     , m_windowVisible(false)
1018     , m_debuggerAttached(false)
1019     , m_showAfterVisible(FocusedNodeDocumentPanel)
1020     , m_nextIdentifier(-2)
1021 {
1022     ASSERT_ARG(page, page);
1023     ASSERT_ARG(client, client);
1024 }
1025
1026 InspectorController::~InspectorController()
1027 {
1028     m_client->inspectorDestroyed();
1029
1030     if (m_scriptContext) {
1031         JSValueRef exception = 0;
1032
1033         JSObjectRef global = JSContextGetGlobalObject(m_scriptContext);
1034         JSValueRef controllerProperty = JSObjectGetProperty(m_scriptContext, global, jsStringRef("InspectorController").get(), &exception);
1035         if (!HANDLE_EXCEPTION(m_scriptContext, exception)) {
1036             if (JSObjectRef controller = JSValueToObject(m_scriptContext, controllerProperty, &exception)) {
1037                 if (!HANDLE_EXCEPTION(m_scriptContext, exception))
1038                     JSObjectSetPrivate(controller, 0);
1039             }
1040         }
1041     }
1042
1043     if (m_page)
1044         m_page->setParentInspectorController(0);
1045
1046     // m_inspectedPage should have been cleared in inspectedPageDestroyed().
1047     ASSERT(!m_inspectedPage);
1048
1049     deleteAllValues(m_frameResources);
1050     deleteAllValues(m_consoleMessages);
1051 }
1052
1053 void InspectorController::inspectedPageDestroyed()
1054 {
1055     ASSERT(m_inspectedPage);
1056     stopDebugging();
1057     m_inspectedPage = 0;
1058 }
1059
1060 bool InspectorController::enabled() const
1061 {
1062     if (!m_inspectedPage)
1063         return false;
1064
1065     return m_inspectedPage->settings()->developerExtrasEnabled();
1066 }
1067
1068 String InspectorController::localizedStringsURL()
1069 {
1070     if (!enabled())
1071         return String();
1072     return m_client->localizedStringsURL();
1073 }
1074
1075 // Trying to inspect something in a frame with JavaScript disabled would later lead to
1076 // crashes trying to create JavaScript wrappers. Some day we could fix this issue, but
1077 // for now prevent crashes here by never targeting a node in such a frame.
1078 static bool canPassNodeToJavaScript(Node* node)
1079 {
1080     if (!node)
1081         return false;
1082     Frame* frame = node->document()->frame();
1083     return frame && frame->scriptProxy()->isEnabled();
1084 }
1085
1086 void InspectorController::inspect(Node* node)
1087 {
1088     if (!canPassNodeToJavaScript(node) || !enabled())
1089         return;
1090
1091     show();
1092
1093     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
1094         node = node->parentNode();
1095     m_nodeToFocus = node;
1096
1097     if (!m_scriptObject) {
1098         m_showAfterVisible = FocusedNodeDocumentPanel;
1099         return;
1100     }
1101
1102     if (windowVisible())
1103         focusNode();
1104 }
1105
1106 void InspectorController::focusNode()
1107 {
1108     if (!enabled())
1109         return;
1110
1111     ASSERT(m_scriptContext);
1112     ASSERT(m_scriptObject);
1113     ASSERT(m_nodeToFocus);
1114
1115     Frame* frame = m_nodeToFocus->document()->frame();
1116     if (!frame)
1117         return;
1118
1119     ExecState* exec = toJSDOMWindow(frame)->globalExec();
1120
1121     JSValueRef arg0;
1122
1123     {
1124         KJS::JSLock lock;
1125         arg0 = toRef(JSInspectedObjectWrapper::wrap(exec, toJS(exec, m_nodeToFocus.get())));
1126     }
1127
1128     m_nodeToFocus = 0;
1129
1130     JSValueRef exception = 0;
1131     callFunction(m_scriptContext, m_scriptObject, "updateFocusedNode", 1, &arg0, exception);
1132 }
1133
1134 void InspectorController::highlight(Node* node)
1135 {
1136     if (!enabled())
1137         return;
1138     ASSERT_ARG(node, node);
1139     m_highlightedNode = node;
1140     m_client->highlight(node);
1141 }
1142
1143 void InspectorController::hideHighlight()
1144 {
1145     if (!enabled())
1146         return;
1147     m_client->hideHighlight();
1148 }
1149
1150 bool InspectorController::windowVisible()
1151 {
1152     return m_windowVisible;
1153 }
1154
1155 void InspectorController::setWindowVisible(bool visible)
1156 {
1157     if (visible == m_windowVisible)
1158         return;
1159
1160     m_windowVisible = visible;
1161
1162     if (!m_scriptContext || !m_scriptObject)
1163         return;
1164
1165     if (m_windowVisible) {
1166         populateScriptObjects();
1167         if (m_nodeToFocus)
1168             focusNode();
1169         if (m_showAfterVisible == ConsolePanel)
1170             showConsole();
1171         else if (m_showAfterVisible == TimelinePanel)
1172             showTimeline();
1173     } else
1174         resetScriptObjects();
1175
1176     m_showAfterVisible = FocusedNodeDocumentPanel;
1177 }
1178
1179 void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, ExecState* exec, const List& arguments, unsigned lineNumber, const String& sourceURL)
1180 {
1181     if (!enabled())
1182         return;
1183
1184     addConsoleMessage(new ConsoleMessage(source, level, exec, arguments, lineNumber, sourceURL));
1185 }
1186
1187 void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID)
1188 {
1189     if (!enabled())
1190         return;
1191
1192     addConsoleMessage(new ConsoleMessage(source, level, message, lineNumber, sourceID));
1193 }
1194
1195 void InspectorController::addConsoleMessage(ConsoleMessage* consoleMessage)
1196 {
1197     ASSERT(enabled());
1198     ASSERT_ARG(consoleMessage, consoleMessage);
1199
1200     m_consoleMessages.append(consoleMessage);
1201
1202     if (windowVisible())
1203         addScriptConsoleMessage(consoleMessage);
1204 }
1205
1206 void InspectorController::addProfile(PassRefPtr<Profile> prpProfile)
1207 {
1208     if (!enabled())
1209         return;
1210
1211     RefPtr<Profile> profile = prpProfile;
1212     m_profiles.append(profile);
1213
1214     if (windowVisible())
1215         addScriptProfile(profile.get());
1216 }
1217
1218 void InspectorController::attachWindow()
1219 {
1220     if (!enabled())
1221         return;
1222     m_client->attachWindow();
1223 }
1224
1225 void InspectorController::detachWindow()
1226 {
1227     if (!enabled())
1228         return;
1229     m_client->detachWindow();
1230 }
1231
1232 void InspectorController::windowScriptObjectAvailable()
1233 {
1234     if (!m_page || !enabled())
1235         return;
1236
1237     m_scriptContext = toRef(m_page->mainFrame()->scriptProxy()->globalObject()->globalExec());
1238
1239     JSObjectRef global = JSContextGetGlobalObject(m_scriptContext);
1240     ASSERT(global);
1241
1242     static JSStaticFunction staticFunctions[] = {
1243         { "addResourceSourceToFrame", addResourceSourceToFrame, kJSPropertyAttributeNone },
1244         { "addSourceToFrame", addSourceToFrame, kJSPropertyAttributeNone },
1245         { "getResourceDocumentNode", getResourceDocumentNode, kJSPropertyAttributeNone },
1246         { "highlightDOMNode", highlightDOMNode, kJSPropertyAttributeNone },
1247         { "hideDOMNodeHighlight", hideDOMNodeHighlight, kJSPropertyAttributeNone },
1248         { "loaded", loaded, kJSPropertyAttributeNone },
1249         { "windowUnloading", unloading, kJSPropertyAttributeNone },
1250         { "attach", attach, kJSPropertyAttributeNone },
1251         { "detach", detach, kJSPropertyAttributeNone },
1252         { "search", search, kJSPropertyAttributeNone },
1253 #if ENABLE(DATABASE)
1254         { "databaseTableNames", databaseTableNames, kJSPropertyAttributeNone },
1255 #endif
1256         { "inspectedWindow", inspectedWindow, kJSPropertyAttributeNone },
1257         { "localizedStringsURL", localizedStrings, kJSPropertyAttributeNone },
1258         { "platform", platform, kJSPropertyAttributeNone },
1259         { "moveByUnrestricted", moveByUnrestricted, kJSPropertyAttributeNone },
1260         { "wrapCallback", wrapCallback, kJSPropertyAttributeNone },
1261         { "startDebuggingAndReloadInspectedPage", WebCore::startDebuggingAndReloadInspectedPage, kJSPropertyAttributeNone },
1262         { "stopDebugging", WebCore::stopDebugging, kJSPropertyAttributeNone },
1263         { "debuggerAttached", WebCore::debuggerAttached, kJSPropertyAttributeNone },
1264         { "profiles", WebCore::profiles, kJSPropertyAttributeNone },
1265         { "currentCallFrame", WebCore::currentCallFrame, kJSPropertyAttributeNone },
1266         { "pauseOnExceptions", WebCore::pauseOnExceptions, kJSPropertyAttributeNone },
1267         { "setPauseOnExceptions", WebCore::setPauseOnExceptions, kJSPropertyAttributeNone },
1268         { "pauseInDebugger", WebCore::pauseInDebugger, kJSPropertyAttributeNone },
1269         { "resumeDebugger", WebCore::resumeDebugger, kJSPropertyAttributeNone },
1270         { "stepOverStatementInDebugger", WebCore::stepOverStatementInDebugger, kJSPropertyAttributeNone },
1271         { "stepIntoStatementInDebugger", WebCore::stepIntoStatementInDebugger, kJSPropertyAttributeNone },
1272         { "stepOutOfFunctionInDebugger", WebCore::stepOutOfFunctionInDebugger, kJSPropertyAttributeNone },
1273         { "addBreakpoint", WebCore::addBreakpoint, kJSPropertyAttributeNone },
1274         { "removeBreakpoint", WebCore::removeBreakpoint, kJSPropertyAttributeNone },
1275         { 0, 0, 0 }
1276     };
1277
1278     JSClassDefinition inspectorControllerDefinition = {
1279         0, kJSClassAttributeNone, "InspectorController", 0, 0, staticFunctions,
1280         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1281     };
1282
1283     JSClassRef controllerClass = JSClassCreate(&inspectorControllerDefinition);
1284     ASSERT(controllerClass);
1285
1286     m_controllerScriptObject = JSObjectMake(m_scriptContext, controllerClass, reinterpret_cast<void*>(this));
1287     ASSERT(m_controllerScriptObject);
1288
1289     JSObjectSetProperty(m_scriptContext, global, jsStringRef("InspectorController").get(), m_controllerScriptObject, kJSPropertyAttributeNone, 0);
1290 }
1291
1292 void InspectorController::scriptObjectReady()
1293 {
1294     ASSERT(m_scriptContext);
1295     if (!m_scriptContext)
1296         return;
1297
1298     JSObjectRef global = JSContextGetGlobalObject(m_scriptContext);
1299     ASSERT(global);
1300
1301     JSValueRef exception = 0;
1302
1303     JSValueRef inspectorValue = JSObjectGetProperty(m_scriptContext, global, jsStringRef("WebInspector").get(), &exception);
1304     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1305         return;
1306
1307     ASSERT(inspectorValue);
1308     if (!inspectorValue)
1309         return;
1310
1311     m_scriptObject = JSValueToObject(m_scriptContext, inspectorValue, &exception);
1312     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1313         return;
1314
1315     ASSERT(m_scriptObject);
1316
1317     JSValueProtect(m_scriptContext, m_scriptObject);
1318
1319     // Make sure our window is visible now that the page loaded
1320     showWindow();
1321 }
1322
1323 void InspectorController::show()
1324 {
1325     if (!enabled())
1326         return;
1327
1328     if (!m_page) {
1329         m_page = m_client->createPage();
1330         if (!m_page)
1331             return;
1332         m_page->setParentInspectorController(this);
1333
1334         // showWindow() will be called after the page loads in scriptObjectReady()
1335         return;
1336     }
1337
1338     showWindow();
1339 }
1340
1341 void InspectorController::showConsole()
1342 {
1343     if (!enabled())
1344         return;
1345
1346     show();
1347
1348     if (!m_scriptObject) {
1349         m_showAfterVisible = ConsolePanel;
1350         return;
1351     }
1352
1353     callSimpleFunction(m_scriptContext, m_scriptObject, "showConsole");
1354 }
1355
1356 void InspectorController::showTimeline()
1357 {
1358     if (!enabled())
1359         return;
1360
1361     show();
1362
1363     if (!m_scriptObject) {
1364         m_showAfterVisible = TimelinePanel;
1365         return;
1366     }
1367
1368     callSimpleFunction(m_scriptContext, m_scriptObject, "showTimeline");
1369 }
1370
1371 void InspectorController::close()
1372 {
1373     if (!enabled())
1374         return;
1375
1376     closeWindow();
1377
1378     ASSERT(m_scriptContext && m_scriptObject);
1379     JSValueUnprotect(m_scriptContext, m_scriptObject);
1380
1381     m_scriptObject = 0;
1382     m_scriptContext = 0;
1383 }
1384
1385 void InspectorController::showWindow()
1386 {
1387     ASSERT(enabled());
1388
1389     m_client->showWindow();
1390 }
1391
1392 void InspectorController::closeWindow()
1393 {
1394     stopDebugging();
1395     m_client->closeWindow();
1396 }
1397
1398 static void addHeaders(JSContextRef context, JSObjectRef object, const HTTPHeaderMap& headers, JSValueRef* exception)
1399 {
1400     ASSERT_ARG(context, context);
1401     ASSERT_ARG(object, object);
1402
1403     HTTPHeaderMap::const_iterator end = headers.end();
1404     for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it) {
1405         JSValueRef value = JSValueMakeString(context, jsStringRef(it->second).get());
1406         JSObjectSetProperty(context, object, jsStringRef(it->first).get(), value, kJSPropertyAttributeNone, exception);
1407         if (exception && *exception)
1408             return;
1409     }
1410 }
1411
1412 static JSObjectRef scriptObjectForRequest(JSContextRef context, const InspectorResource* resource, JSValueRef* exception)
1413 {
1414     ASSERT_ARG(context, context);
1415
1416     JSObjectRef object = JSObjectMake(context, 0, 0);
1417     addHeaders(context, object, resource->requestHeaderFields, exception);
1418
1419     return object;
1420 }
1421
1422 static JSObjectRef scriptObjectForResponse(JSContextRef context, const InspectorResource* resource, JSValueRef* exception)
1423 {
1424     ASSERT_ARG(context, context);
1425
1426     JSObjectRef object = JSObjectMake(context, 0, 0);
1427     addHeaders(context, object, resource->responseHeaderFields, exception);
1428
1429     return object;
1430 }
1431
1432 JSObjectRef InspectorController::addScriptResource(InspectorResource* resource)
1433 {
1434     ASSERT_ARG(resource, resource);
1435
1436     ASSERT(m_scriptContext);
1437     ASSERT(m_scriptObject);
1438     if (!m_scriptContext || !m_scriptObject)
1439         return 0;
1440
1441     if (!resource->scriptObject) {
1442         JSValueRef exception = 0;
1443
1444         JSValueRef resourceProperty = JSObjectGetProperty(m_scriptContext, m_scriptObject, jsStringRef("Resource").get(), &exception);
1445         if (HANDLE_EXCEPTION(m_scriptContext, exception))
1446             return 0;
1447
1448         JSObjectRef resourceConstructor = JSValueToObject(m_scriptContext, resourceProperty, &exception);
1449         if (HANDLE_EXCEPTION(m_scriptContext, exception))
1450             return 0;
1451
1452         JSValueRef urlValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->requestURL.string()).get());
1453         JSValueRef domainValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->requestURL.host()).get());
1454         JSValueRef pathValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->requestURL.path()).get());
1455         JSValueRef lastPathComponentValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->requestURL.lastPathComponent()).get());
1456
1457         JSValueRef identifier = JSValueMakeNumber(m_scriptContext, resource->identifier);
1458         JSValueRef mainResource = JSValueMakeBoolean(m_scriptContext, m_mainResource == resource);
1459         JSValueRef cached = JSValueMakeBoolean(m_scriptContext, resource->cached);
1460
1461         JSObjectRef scriptObject = scriptObjectForRequest(m_scriptContext, resource, &exception);
1462         if (HANDLE_EXCEPTION(m_scriptContext, exception))
1463             return 0;
1464
1465         JSValueRef arguments[] = { scriptObject, urlValue, domainValue, pathValue, lastPathComponentValue, identifier, mainResource, cached };
1466         JSObjectRef result = JSObjectCallAsConstructor(m_scriptContext, resourceConstructor, 8, arguments, &exception);
1467         if (HANDLE_EXCEPTION(m_scriptContext, exception))
1468             return 0;
1469
1470         ASSERT(result);
1471
1472         resource->setScriptObject(m_scriptContext, result);
1473     }
1474
1475     JSValueRef exception = 0;
1476     callFunction(m_scriptContext, m_scriptObject, "addResource", 1, &resource->scriptObject, exception);
1477
1478     if (exception)
1479         return 0;
1480
1481     return resource->scriptObject;
1482 }
1483
1484 JSObjectRef InspectorController::addAndUpdateScriptResource(InspectorResource* resource)
1485 {
1486     ASSERT_ARG(resource, resource);
1487
1488     JSObjectRef scriptResource = addScriptResource(resource);
1489     if (!scriptResource)
1490         return 0;
1491
1492     updateScriptResourceResponse(resource);
1493     updateScriptResource(resource, resource->length);
1494     updateScriptResource(resource, resource->startTime, resource->responseReceivedTime, resource->endTime);
1495     updateScriptResource(resource, resource->finished, resource->failed);
1496     return scriptResource;
1497 }
1498
1499 void InspectorController::removeScriptResource(InspectorResource* resource)
1500 {
1501     ASSERT(m_scriptContext);
1502     ASSERT(m_scriptObject);
1503     if (!m_scriptContext || !m_scriptObject)
1504         return;
1505
1506     ASSERT(resource);
1507     ASSERT(resource->scriptObject);
1508     if (!resource || !resource->scriptObject)
1509         return;
1510
1511     JSObjectRef scriptObject = resource->scriptObject;
1512     resource->setScriptObject(0, 0);
1513
1514     JSValueRef exception = 0;
1515     callFunction(m_scriptContext, m_scriptObject, "removeResource", 1, &scriptObject, exception);
1516 }
1517
1518 static void updateResourceRequest(InspectorResource* resource, const ResourceRequest& request)
1519 {
1520     resource->requestHeaderFields = request.httpHeaderFields();
1521     resource->requestURL = request.url();
1522 }
1523
1524 static void updateResourceResponse(InspectorResource* resource, const ResourceResponse& response)
1525 {
1526     resource->expectedContentLength = response.expectedContentLength();
1527     resource->mimeType = response.mimeType();
1528     resource->responseHeaderFields = response.httpHeaderFields();
1529     resource->responseStatusCode = response.httpStatusCode();
1530     resource->suggestedFilename = response.suggestedFilename();
1531 }
1532
1533 void InspectorController::updateScriptResourceRequest(InspectorResource* resource)
1534 {
1535     ASSERT(resource->scriptObject);
1536     ASSERT(m_scriptContext);
1537     if (!resource->scriptObject || !m_scriptContext)
1538         return;
1539
1540     JSValueRef urlValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->requestURL.string()).get());
1541     JSValueRef domainValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->requestURL.host()).get());
1542     JSValueRef pathValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->requestURL.path()).get());
1543     JSValueRef lastPathComponentValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->requestURL.lastPathComponent()).get());
1544
1545     JSValueRef mainResourceValue = JSValueMakeBoolean(m_scriptContext, m_mainResource == resource);
1546
1547     JSValueRef exception = 0;
1548
1549     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("url").get(), urlValue, kJSPropertyAttributeNone, &exception);
1550     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1551         return;
1552
1553     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("domain").get(), domainValue, kJSPropertyAttributeNone, &exception);
1554     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1555         return;
1556
1557     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("path").get(), pathValue, kJSPropertyAttributeNone, &exception);
1558     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1559         return;
1560
1561     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("lastPathComponent").get(), lastPathComponentValue, kJSPropertyAttributeNone, &exception);
1562     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1563         return;
1564
1565     JSObjectRef scriptObject = scriptObjectForRequest(m_scriptContext, resource, &exception);
1566     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1567         return;
1568
1569     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("requestHeaders").get(), scriptObject, kJSPropertyAttributeNone, &exception);
1570     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1571         return;
1572
1573     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("mainResource").get(), mainResourceValue, kJSPropertyAttributeNone, &exception);
1574     HANDLE_EXCEPTION(m_scriptContext, exception);
1575 }
1576
1577 void InspectorController::updateScriptResourceResponse(InspectorResource* resource)
1578 {
1579     ASSERT(resource->scriptObject);
1580     ASSERT(m_scriptContext);
1581     if (!resource->scriptObject || !m_scriptContext)
1582         return;
1583
1584     JSValueRef mimeTypeValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->mimeType).get());
1585
1586     JSValueRef suggestedFilenameValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->suggestedFilename).get());
1587
1588     JSValueRef expectedContentLengthValue = JSValueMakeNumber(m_scriptContext, static_cast<double>(resource->expectedContentLength));
1589     JSValueRef statusCodeValue = JSValueMakeNumber(m_scriptContext, resource->responseStatusCode);
1590
1591     JSValueRef exception = 0;
1592
1593     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("mimeType").get(), mimeTypeValue, kJSPropertyAttributeNone, &exception);
1594     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1595         return;
1596
1597     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("suggestedFilename").get(), suggestedFilenameValue, kJSPropertyAttributeNone, &exception);
1598     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1599         return;
1600
1601     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("expectedContentLength").get(), expectedContentLengthValue, kJSPropertyAttributeNone, &exception);
1602     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1603         return;
1604
1605     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("statusCode").get(), statusCodeValue, kJSPropertyAttributeNone, &exception);
1606     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1607         return;
1608
1609     JSObjectRef scriptObject = scriptObjectForResponse(m_scriptContext, resource, &exception);
1610     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1611         return;
1612
1613     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("responseHeaders").get(), scriptObject, kJSPropertyAttributeNone, &exception);
1614     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1615         return;
1616
1617     JSValueRef typeValue = JSValueMakeNumber(m_scriptContext, resource->type());
1618     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("type").get(), typeValue, kJSPropertyAttributeNone, &exception);
1619     HANDLE_EXCEPTION(m_scriptContext, exception);
1620 }
1621
1622 void InspectorController::updateScriptResource(InspectorResource* resource, int length)
1623 {
1624     ASSERT(resource->scriptObject);
1625     ASSERT(m_scriptContext);
1626     if (!resource->scriptObject || !m_scriptContext)
1627         return;
1628
1629     JSValueRef lengthValue = JSValueMakeNumber(m_scriptContext, length);
1630
1631     JSValueRef exception = 0;
1632
1633     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("contentLength").get(), lengthValue, kJSPropertyAttributeNone, &exception);
1634     HANDLE_EXCEPTION(m_scriptContext, exception);
1635 }
1636
1637 void InspectorController::updateScriptResource(InspectorResource* resource, bool finished, bool failed)
1638 {
1639     ASSERT(resource->scriptObject);
1640     ASSERT(m_scriptContext);
1641     if (!resource->scriptObject || !m_scriptContext)
1642         return;
1643
1644     JSValueRef failedValue = JSValueMakeBoolean(m_scriptContext, failed);
1645     JSValueRef finishedValue = JSValueMakeBoolean(m_scriptContext, finished);
1646
1647     JSValueRef exception = 0;
1648
1649     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("failed").get(), failedValue, kJSPropertyAttributeNone, &exception);
1650     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1651         return;
1652
1653     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("finished").get(), finishedValue, kJSPropertyAttributeNone, &exception);
1654     HANDLE_EXCEPTION(m_scriptContext, exception);
1655 }
1656
1657 void InspectorController::updateScriptResource(InspectorResource* resource, double startTime, double responseReceivedTime, double endTime)
1658 {
1659     ASSERT(resource->scriptObject);
1660     ASSERT(m_scriptContext);
1661     if (!resource->scriptObject || !m_scriptContext)
1662         return;
1663
1664     JSValueRef startTimeValue = JSValueMakeNumber(m_scriptContext, startTime);
1665     JSValueRef responseReceivedTimeValue = JSValueMakeNumber(m_scriptContext, responseReceivedTime);
1666     JSValueRef endTimeValue = JSValueMakeNumber(m_scriptContext, endTime);
1667
1668     JSValueRef exception = 0;
1669
1670     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("startTime").get(), startTimeValue, kJSPropertyAttributeNone, &exception);
1671     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1672         return;
1673
1674     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("responseReceivedTime").get(), responseReceivedTimeValue, kJSPropertyAttributeNone, &exception);
1675     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1676         return;
1677
1678     JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("endTime").get(), endTimeValue, kJSPropertyAttributeNone, &exception);
1679     HANDLE_EXCEPTION(m_scriptContext, exception);
1680 }
1681
1682 void InspectorController::populateScriptObjects()
1683 {
1684     ASSERT(m_scriptContext);
1685     if (!m_scriptContext)
1686         return;
1687
1688     ResourcesMap::iterator resourcesEnd = m_resources.end();
1689     for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it)
1690         addAndUpdateScriptResource(it->second.get());
1691
1692     unsigned messageCount = m_consoleMessages.size();
1693     for (unsigned i = 0; i < messageCount; ++i)
1694         addScriptConsoleMessage(m_consoleMessages[i]);
1695
1696 #if ENABLE(DATABASE)
1697     DatabaseResourcesSet::iterator databasesEnd = m_databaseResources.end();
1698     for (DatabaseResourcesSet::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it)
1699         addDatabaseScriptResource((*it).get());
1700 #endif
1701 }
1702
1703 #if ENABLE(DATABASE)
1704 JSObjectRef InspectorController::addDatabaseScriptResource(InspectorDatabaseResource* resource)
1705 {
1706     ASSERT_ARG(resource, resource);
1707
1708     if (resource->scriptObject)
1709         return resource->scriptObject;
1710
1711     ASSERT(m_scriptContext);
1712     ASSERT(m_scriptObject);
1713     if (!m_scriptContext || !m_scriptObject)
1714         return 0;
1715
1716     Frame* frame = resource->database->document()->frame();
1717     if (!frame)
1718         return 0;
1719
1720     JSValueRef exception = 0;
1721
1722     JSValueRef databaseProperty = JSObjectGetProperty(m_scriptContext, m_scriptObject, jsStringRef("Database").get(), &exception);
1723     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1724         return 0;
1725
1726     JSObjectRef databaseConstructor = JSValueToObject(m_scriptContext, databaseProperty, &exception);
1727     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1728         return 0;
1729
1730     ExecState* exec = toJSDOMWindow(frame)->globalExec();
1731
1732     JSValueRef database;
1733
1734     {
1735         KJS::JSLock lock;
1736         database = toRef(JSInspectedObjectWrapper::wrap(exec, toJS(exec, resource->database.get())));
1737     }
1738
1739     JSValueRef domainValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->domain).get());
1740     JSValueRef nameValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->name).get());
1741     JSValueRef versionValue = JSValueMakeString(m_scriptContext, jsStringRef(resource->version).get());
1742
1743     JSValueRef arguments[] = { database, domainValue, nameValue, versionValue };
1744     JSObjectRef result = JSObjectCallAsConstructor(m_scriptContext, databaseConstructor, 4, arguments, &exception);
1745     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1746         return 0;
1747
1748     ASSERT(result);
1749
1750     callFunction(m_scriptContext, m_scriptObject, "addDatabase", 1, &result, exception);
1751
1752     if (exception)
1753         return 0;
1754
1755     resource->setScriptObject(m_scriptContext, result);
1756
1757     return result;
1758 }
1759
1760 void InspectorController::removeDatabaseScriptResource(InspectorDatabaseResource* resource)
1761 {
1762     ASSERT(m_scriptContext);
1763     ASSERT(m_scriptObject);
1764     if (!m_scriptContext || !m_scriptObject)
1765         return;
1766
1767     ASSERT(resource);
1768     ASSERT(resource->scriptObject);
1769     if (!resource || !resource->scriptObject)
1770         return;
1771
1772     JSObjectRef scriptObject = resource->scriptObject;
1773     resource->setScriptObject(0, 0);
1774
1775     JSValueRef exception = 0;
1776     callFunction(m_scriptContext, m_scriptObject, "removeDatabase", 1, &scriptObject, exception);
1777 }
1778 #endif
1779
1780 void InspectorController::addScriptConsoleMessage(const ConsoleMessage* message)
1781 {
1782     ASSERT_ARG(message, message);
1783
1784     JSValueRef exception = 0;
1785
1786     JSValueRef messageConstructorProperty = JSObjectGetProperty(m_scriptContext, m_scriptObject, jsStringRef("ConsoleMessage").get(), &exception);
1787     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1788         return;
1789
1790     JSObjectRef messageConstructor = JSValueToObject(m_scriptContext, messageConstructorProperty, &exception);
1791     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1792         return;
1793
1794     JSValueRef sourceValue = JSValueMakeNumber(m_scriptContext, message->source);
1795     JSValueRef levelValue = JSValueMakeNumber(m_scriptContext, message->level);
1796     JSValueRef lineValue = JSValueMakeNumber(m_scriptContext, message->line);
1797     JSValueRef urlValue = JSValueMakeString(m_scriptContext, jsStringRef(message->url).get());
1798
1799     static const unsigned maximumMessageArguments = 256;
1800     JSValueRef arguments[maximumMessageArguments];
1801     unsigned argumentCount = 0;
1802     arguments[argumentCount++] = sourceValue;
1803     arguments[argumentCount++] = levelValue;
1804     arguments[argumentCount++] = lineValue;
1805     arguments[argumentCount++] = urlValue;
1806
1807     if (!message->wrappedArguments.isEmpty()) {
1808         unsigned remainingSpaceInArguments = maximumMessageArguments - argumentCount;
1809         unsigned argumentsToAdd = min(remainingSpaceInArguments, static_cast<unsigned>(message->wrappedArguments.size()));
1810         for (unsigned i = 0; i < argumentsToAdd; ++i)
1811             arguments[argumentCount++] = toRef(message->wrappedArguments[i]);
1812     } else {
1813         JSValueRef messageValue = JSValueMakeString(m_scriptContext, jsStringRef(message->message).get());
1814         arguments[argumentCount++] = messageValue;
1815     }
1816
1817     JSObjectRef messageObject = JSObjectCallAsConstructor(m_scriptContext, messageConstructor, argumentCount, arguments, &exception);
1818     if (HANDLE_EXCEPTION(m_scriptContext, exception))
1819         return;
1820
1821     callFunction(m_scriptContext, m_scriptObject, "addMessageToConsole", 1, &messageObject, exception);
1822 }
1823
1824 void InspectorController::addScriptProfile(Profile* profile)
1825 {
1826     JSLock lock;
1827     JSValueRef exception = 0;
1828     JSValueRef profileObject = toRef(toJS(toJS(m_scriptContext), profile));
1829     callFunction(m_scriptContext, m_scriptObject, "addProfile", 1, &profileObject, exception);
1830 }
1831
1832 void InspectorController::resetScriptObjects()
1833 {
1834     if (!m_scriptContext || !m_scriptObject)
1835         return;
1836
1837     ResourcesMap::iterator resourcesEnd = m_resources.end();
1838     for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) {
1839         InspectorResource* resource = it->second.get();
1840         resource->setScriptObject(0, 0);
1841     }
1842
1843 #if ENABLE(DATABASE)
1844     DatabaseResourcesSet::iterator databasesEnd = m_databaseResources.end();
1845     for (DatabaseResourcesSet::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it) {
1846         InspectorDatabaseResource* resource = (*it).get();
1847         resource->setScriptObject(0, 0);
1848     }
1849 #endif
1850
1851     callSimpleFunction(m_scriptContext, m_scriptObject, "reset");
1852 }
1853
1854 void InspectorController::pruneResources(ResourcesMap* resourceMap, DocumentLoader* loaderToKeep)
1855 {
1856     ASSERT_ARG(resourceMap, resourceMap);
1857
1858     ResourcesMap mapCopy(*resourceMap);
1859     ResourcesMap::iterator end = mapCopy.end();
1860     for (ResourcesMap::iterator it = mapCopy.begin(); it != end; ++it) {
1861         InspectorResource* resource = (*it).second.get();
1862         if (resource == m_mainResource)
1863             continue;
1864
1865         if (!loaderToKeep || resource->loader != loaderToKeep) {
1866             removeResource(resource);
1867             if (windowVisible() && resource->scriptObject)
1868                 removeScriptResource(resource);
1869         }
1870     }
1871 }
1872
1873 void InspectorController::didCommitLoad(DocumentLoader* loader)
1874 {
1875     if (!enabled())
1876         return;
1877
1878     ASSERT(m_inspectedPage);
1879
1880     if (loader->frame() == m_inspectedPage->mainFrame()) {
1881         m_client->inspectedURLChanged(loader->url().string());
1882
1883         deleteAllValues(m_consoleMessages);
1884         m_consoleMessages.clear();
1885
1886         m_profiles.clear();
1887
1888 #if ENABLE(DATABASE)
1889         m_databaseResources.clear();
1890 #endif
1891
1892         if (windowVisible()) {
1893             resetScriptObjects();
1894
1895             if (!loader->isLoadingFromCachedPage()) {
1896                 ASSERT(m_mainResource && m_mainResource->loader == loader);
1897                 // We don't add the main resource until its load is committed. This is
1898                 // needed to keep the load for a user-entered URL from showing up in the
1899                 // list of resources for the page they are navigating away from.
1900                 addAndUpdateScriptResource(m_mainResource.get());
1901             } else {
1902                 // Pages loaded from the page cache are committed before
1903                 // m_mainResource is the right resource for this load, so we
1904                 // clear it here. It will be re-assigned in
1905                 // identifierForInitialRequest.
1906                 m_mainResource = 0;
1907             }
1908         }
1909     }
1910
1911     for (Frame* frame = loader->frame(); frame; frame = frame->tree()->traverseNext(loader->frame()))
1912         if (ResourcesMap* resourceMap = m_frameResources.get(frame))
1913             pruneResources(resourceMap, loader);
1914 }
1915
1916 void InspectorController::frameDetachedFromParent(Frame* frame)
1917 {
1918     if (!enabled())
1919         return;
1920     if (ResourcesMap* resourceMap = m_frameResources.get(frame))
1921         removeAllResources(resourceMap);
1922 }
1923
1924 void InspectorController::addResource(InspectorResource* resource)
1925 {
1926     m_resources.set(resource->identifier, resource);
1927
1928     Frame* frame = resource->frame.get();
1929     ResourcesMap* resourceMap = m_frameResources.get(frame);
1930     if (resourceMap)
1931         resourceMap->set(resource->identifier, resource);
1932     else {
1933         resourceMap = new ResourcesMap;
1934         resourceMap->set(resource->identifier, resource);
1935         m_frameResources.set(frame, resourceMap);
1936     }
1937 }
1938
1939 void InspectorController::removeResource(InspectorResource* resource)
1940 {
1941     m_resources.remove(resource->identifier);
1942
1943     Frame* frame = resource->frame.get();
1944     ResourcesMap* resourceMap = m_frameResources.get(frame);
1945     if (!resourceMap) {
1946         ASSERT_NOT_REACHED();
1947         return;
1948     }
1949
1950     resourceMap->remove(resource->identifier);
1951     if (resourceMap->isEmpty()) {
1952         m_frameResources.remove(frame);
1953         delete resourceMap;
1954     }
1955 }
1956
1957 void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
1958 {
1959     if (!enabled())
1960         return;
1961
1962     RefPtr<InspectorResource> resource = InspectorResource::create(m_nextIdentifier--, loader, loader->frame());
1963     resource->finished = true;
1964
1965     updateResourceRequest(resource.get(), request);
1966     updateResourceResponse(resource.get(), response);
1967
1968     resource->length = length;
1969     resource->cached = true;
1970     resource->startTime = currentTime();
1971     resource->responseReceivedTime = resource->startTime;
1972     resource->endTime = resource->startTime;
1973
1974     ASSERT(m_inspectedPage);
1975
1976     if (loader->frame() == m_inspectedPage->mainFrame() && request.url() == loader->requestURL())
1977         m_mainResource = resource;
1978
1979     addResource(resource.get());
1980
1981     if (windowVisible())
1982         addAndUpdateScriptResource(resource.get());
1983 }
1984
1985 void InspectorController::identifierForInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
1986 {
1987     if (!enabled())
1988         return;
1989
1990     RefPtr<InspectorResource> resource = InspectorResource::create(identifier, loader, loader->frame());
1991
1992     updateResourceRequest(resource.get(), request);
1993
1994     ASSERT(m_inspectedPage);
1995
1996     if (loader->frame() == m_inspectedPage->mainFrame() && request.url() == loader->requestURL())
1997         m_mainResource = resource;
1998
1999     addResource(resource.get());
2000
2001     if (windowVisible() && loader->isLoadingFromCachedPage() && resource == m_mainResource)
2002         addAndUpdateScriptResource(resource.get());
2003 }
2004
2005 void InspectorController::willSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
2006 {
2007     if (!enabled())
2008         return;
2009
2010     InspectorResource* resource = m_resources.get(identifier).get();
2011     if (!resource)
2012         return;
2013
2014     resource->startTime = currentTime();
2015
2016     if (!redirectResponse.isNull()) {
2017         updateResourceRequest(resource, request);
2018         updateResourceResponse(resource, redirectResponse);
2019     }
2020
2021     if (resource != m_mainResource && windowVisible()) {
2022         if (!resource->scriptObject)
2023             addScriptResource(resource);
2024         else
2025             updateScriptResourceRequest(resource);
2026
2027         updateScriptResource(resource, resource->startTime, resource->responseReceivedTime, resource->endTime);
2028
2029         if (!redirectResponse.isNull())
2030             updateScriptResourceResponse(resource);
2031     }
2032 }
2033
2034 void InspectorController::didReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response)
2035 {
2036     if (!enabled())
2037         return;
2038
2039     InspectorResource* resource = m_resources.get(identifier).get();
2040     if (!resource)
2041         return;
2042
2043     updateResourceResponse(resource, response);
2044
2045     resource->responseReceivedTime = currentTime();
2046
2047     if (windowVisible() && resource->scriptObject) {
2048         updateScriptResourceResponse(resource);
2049         updateScriptResource(resource, resource->startTime, resource->responseReceivedTime, resource->endTime);
2050     }
2051 }
2052
2053 void InspectorController::didReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived)
2054 {
2055     if (!enabled())
2056         return;
2057
2058     InspectorResource* resource = m_resources.get(identifier).get();
2059     if (!resource)
2060         return;
2061
2062     resource->length += lengthReceived;
2063
2064     if (windowVisible() && resource->scriptObject)
2065         updateScriptResource(resource, resource->length);
2066 }
2067
2068 void InspectorController::didFinishLoading(DocumentLoader* loader, unsigned long identifier)
2069 {
2070     if (!enabled())
2071         return;
2072
2073     RefPtr<InspectorResource> resource = m_resources.get(identifier);
2074     if (!resource)
2075         return;
2076
2077     removeResource(resource.get());
2078
2079     resource->finished = true;
2080     resource->endTime = currentTime();
2081
2082     addResource(resource.get());
2083
2084     if (windowVisible() && resource->scriptObject) {
2085         updateScriptResource(resource.get(), resource->startTime, resource->responseReceivedTime, resource->endTime);
2086         updateScriptResource(resource.get(), resource->finished);
2087     }
2088 }
2089
2090 void InspectorController::didFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& /*error*/)
2091 {
2092     if (!enabled())
2093         return;
2094
2095     RefPtr<InspectorResource> resource = m_resources.get(identifier);
2096     if (!resource)
2097         return;
2098
2099     removeResource(resource.get());
2100
2101     resource->finished = true;
2102     resource->failed = true;
2103     resource->endTime = currentTime();
2104
2105     addResource(resource.get());
2106
2107     if (windowVisible() && resource->scriptObject) {
2108         updateScriptResource(resource.get(), resource->startTime, resource->responseReceivedTime, resource->endTime);
2109         updateScriptResource(resource.get(), resource->finished, resource->failed);
2110     }
2111 }
2112
2113 void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, KJS::UString& sourceString)
2114 {
2115     if (!enabled())
2116         return;
2117
2118     InspectorResource* resource = m_resources.get(identifier).get();
2119     if (!resource)
2120         return;
2121
2122     resource->setXMLHttpRequestProperties(sourceString);
2123 }
2124
2125
2126 #if ENABLE(DATABASE)
2127 void InspectorController::didOpenDatabase(Database* database, const String& domain, const String& name, const String& version)
2128 {
2129     if (!enabled())
2130         return;
2131
2132     RefPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::create(database, domain, name, version);
2133
2134     m_databaseResources.add(resource);
2135
2136     if (windowVisible())
2137         addDatabaseScriptResource(resource.get());
2138 }
2139 #endif
2140
2141 void InspectorController::moveWindowBy(float x, float y) const
2142 {
2143     if (!m_page || !enabled())
2144         return;
2145
2146     FloatRect frameRect = m_page->chrome()->windowRect();
2147     frameRect.move(x, y);
2148     m_page->chrome()->setWindowRect(frameRect);
2149 }
2150
2151 void InspectorController::startDebuggingAndReloadInspectedPage()
2152 {
2153     ASSERT(m_inspectedPage);
2154
2155     JavaScriptDebugServer::shared().addListener(this, m_inspectedPage);
2156     m_debuggerAttached = true;
2157     JavaScriptDebugServer::shared().clearBreakpoints();
2158     m_inspectedPage->mainFrame()->loader()->reload();
2159 }
2160
2161 void InspectorController::stopDebugging()
2162 {
2163     ASSERT(m_inspectedPage);
2164
2165     JavaScriptDebugServer::shared().removeListener(this, m_inspectedPage);
2166     m_debuggerAttached = false;
2167 }
2168
2169 JavaScriptCallFrame* InspectorController::currentCallFrame() const
2170 {
2171     return JavaScriptDebugServer::shared().currentCallFrame();
2172 }
2173
2174 bool InspectorController::pauseOnExceptions()
2175 {
2176     return JavaScriptDebugServer::shared().pauseOnExceptions();
2177 }
2178
2179 void InspectorController::setPauseOnExceptions(bool pause)
2180 {
2181     JavaScriptDebugServer::shared().setPauseOnExceptions(pause);
2182 }
2183
2184 void InspectorController::pauseInDebugger()
2185 {
2186     if (!m_debuggerAttached)
2187         return;
2188     JavaScriptDebugServer::shared().pauseProgram();
2189 }
2190
2191 void InspectorController::resumeDebugger()
2192 {
2193     if (!m_debuggerAttached)
2194         return;
2195     JavaScriptDebugServer::shared().continueProgram();
2196 }
2197
2198 void InspectorController::stepOverStatementInDebugger()
2199 {
2200     if (!m_debuggerAttached)
2201         return;
2202     JavaScriptDebugServer::shared().stepOverStatement();
2203 }
2204
2205 void InspectorController::stepIntoStatementInDebugger()
2206 {
2207     if (!m_debuggerAttached)
2208         return;
2209     JavaScriptDebugServer::shared().stepIntoStatement();
2210 }
2211
2212 void InspectorController::stepOutOfFunctionInDebugger()
2213 {
2214     if (!m_debuggerAttached)
2215         return;
2216     JavaScriptDebugServer::shared().stepOutOfFunction();
2217 }
2218
2219 void InspectorController::addBreakpoint(int sourceID, unsigned lineNumber)
2220 {
2221     JavaScriptDebugServer::shared().addBreakpoint(sourceID, lineNumber);
2222 }
2223
2224 void InspectorController::removeBreakpoint(int sourceID, unsigned lineNumber)
2225 {
2226     JavaScriptDebugServer::shared().removeBreakpoint(sourceID, lineNumber);
2227 }
2228
2229 static void drawOutlinedRect(GraphicsContext& context, const IntRect& rect, const Color& fillColor)
2230 {
2231     static const int outlineThickness = 1;
2232     static const Color outlineColor(62, 86, 180, 228);
2233
2234     IntRect outline = rect;
2235     outline.inflate(outlineThickness);
2236
2237     context.clearRect(outline);
2238
2239     context.save();
2240     context.clipOut(rect);
2241     context.fillRect(outline, outlineColor);
2242     context.restore();
2243
2244     context.fillRect(rect, fillColor);
2245 }
2246
2247 static void drawHighlightForBoxes(GraphicsContext& context, const Vector<IntRect>& lineBoxRects, const IntRect& contentBox, const IntRect& paddingBox, const IntRect& borderBox, const IntRect& marginBox)
2248 {
2249     static const Color contentBoxColor(125, 173, 217, 128);
2250     static const Color paddingBoxColor(125, 173, 217, 160);
2251     static const Color borderBoxColor(125, 173, 217, 192);
2252     static const Color marginBoxColor(125, 173, 217, 228);
2253
2254     if (!lineBoxRects.isEmpty()) {
2255         for (size_t i = 0; i < lineBoxRects.size(); ++i)
2256             drawOutlinedRect(context, lineBoxRects[i], contentBoxColor);
2257         return;
2258     }
2259
2260     if (marginBox != borderBox)
2261         drawOutlinedRect(context, marginBox, marginBoxColor);
2262     if (borderBox != paddingBox)
2263         drawOutlinedRect(context, borderBox, borderBoxColor);
2264     if (paddingBox != contentBox)
2265         drawOutlinedRect(context, paddingBox, paddingBoxColor);
2266     drawOutlinedRect(context, contentBox, contentBoxColor);
2267 }
2268
2269 static inline void convertFromFrameToMainFrame(Frame* frame, IntRect& rect)
2270 {
2271     rect = frame->page()->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(rect));
2272 }
2273
2274 void InspectorController::drawNodeHighlight(GraphicsContext& context) const
2275 {
2276     if (!m_highlightedNode)
2277         return;
2278
2279     RenderObject* renderer = m_highlightedNode->renderer();
2280     Frame* containingFrame = m_highlightedNode->document()->frame();
2281     if (!renderer || !containingFrame)
2282         return;
2283
2284     IntRect contentBox = renderer->absoluteContentBox();
2285     IntRect boundingBox = renderer->absoluteBoundingBoxRect();
2286
2287     // FIXME: Should we add methods to RenderObject to obtain these rects?
2288     IntRect paddingBox(contentBox.x() - renderer->paddingLeft(), contentBox.y() - renderer->paddingTop(), contentBox.width() + renderer->paddingLeft() + renderer->paddingRight(), contentBox.height() + renderer->paddingTop() + renderer->paddingBottom());
2289     IntRect borderBox(paddingBox.x() - renderer->borderLeft(), paddingBox.y() - renderer->borderTop(), paddingBox.width() + renderer->borderLeft() + renderer->borderRight(), paddingBox.height() + renderer->borderTop() + renderer->borderBottom());
2290     IntRect marginBox(borderBox.x() - renderer->marginLeft(), borderBox.y() - renderer->marginTop(), borderBox.width() + renderer->marginLeft() + renderer->marginRight(), borderBox.height() + renderer->marginTop() + renderer->marginBottom());
2291
2292     convertFromFrameToMainFrame(containingFrame, contentBox);
2293     convertFromFrameToMainFrame(containingFrame, paddingBox);
2294     convertFromFrameToMainFrame(containingFrame, borderBox);
2295     convertFromFrameToMainFrame(containingFrame, marginBox);
2296     convertFromFrameToMainFrame(containingFrame, boundingBox);
2297
2298     Vector<IntRect> lineBoxRects;
2299     if (renderer->isInline() || (renderer->isText() && !m_highlightedNode->isSVGElement())) {
2300         // FIXME: We should show margins/padding/border for inlines.
2301         renderer->addLineBoxRects(lineBoxRects);
2302     }
2303
2304     for (unsigned i = 0; i < lineBoxRects.size(); ++i)
2305         convertFromFrameToMainFrame(containingFrame, lineBoxRects[i]);
2306
2307     if (lineBoxRects.isEmpty() && contentBox.isEmpty()) {
2308         // If we have no line boxes and our content box is empty, we'll just draw our bounding box.
2309         // This can happen, e.g., with an <a> enclosing an <img style="float:right">.
2310         // FIXME: Can we make this better/more accurate? The <a> in the above case has no
2311         // width/height but the highlight makes it appear to be the size of the <img>.
2312         lineBoxRects.append(boundingBox);
2313     }
2314
2315     ASSERT(m_inspectedPage);
2316
2317     FrameView* view = m_inspectedPage->mainFrame()->view();
2318     FloatRect overlayRect = view->visibleContentRect();
2319
2320     if (!overlayRect.contains(boundingBox) && !boundingBox.contains(enclosingIntRect(overlayRect))) {
2321         Element* element;
2322         if (m_highlightedNode->isElementNode())
2323             element = static_cast<Element*>(m_highlightedNode.get());
2324         else
2325             element = static_cast<Element*>(m_highlightedNode->parent());
2326         element->scrollIntoViewIfNeeded();
2327         overlayRect = view->visibleContentRect();
2328     }
2329
2330     context.translate(-overlayRect.x(), -overlayRect.y());
2331
2332     drawHighlightForBoxes(context, lineBoxRects, contentBox, paddingBox, borderBox, marginBox);
2333 }
2334
2335 bool InspectorController::handleException(JSContextRef context, JSValueRef exception, unsigned lineNumber) const
2336 {
2337     if (!exception)
2338         return false;
2339
2340     if (!m_page)
2341         return true;
2342
2343     String message = toString(context, exception, 0);
2344     String file(__FILE__);
2345
2346     if (JSObjectRef exceptionObject = JSValueToObject(context, exception, 0)) {
2347         JSValueRef lineValue = JSObjectGetProperty(context, exceptionObject, jsStringRef("line").get(), NULL);
2348         if (lineValue)
2349             lineNumber = static_cast<unsigned>(JSValueToNumber(context, lineValue, 0));
2350
2351         JSValueRef fileValue = JSObjectGetProperty(context, exceptionObject, jsStringRef("sourceURL").get(), NULL);
2352         if (fileValue)
2353             file = toString(context, fileValue, 0);
2354     }
2355
2356     m_page->mainFrame()->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, lineNumber, file);
2357     return true;
2358 }
2359
2360 // JavaScriptDebugListener functions
2361
2362 void InspectorController::didParseSource(ExecState*, const SourceProvider& source, int startingLineNumber, const UString& sourceURL, int sourceID)
2363 {
2364     JSValueRef sourceIDValue = JSValueMakeNumber(m_scriptContext, sourceID);
2365     JSValueRef sourceURLValue = JSValueMakeString(m_scriptContext, jsStringRef(sourceURL).get());
2366     JSValueRef sourceValue = JSValueMakeString(m_scriptContext, jsStringRef(source).get());
2367     JSValueRef startingLineNumberValue = JSValueMakeNumber(m_scriptContext, startingLineNumber);
2368
2369     JSValueRef exception = 0;
2370     JSValueRef arguments[] = { sourceIDValue, sourceURLValue, sourceValue, startingLineNumberValue };
2371     callFunction(m_scriptContext, m_scriptObject, "parsedScriptSource", 4, arguments, exception);
2372 }
2373
2374 void InspectorController::failedToParseSource(ExecState*, const SourceProvider& source, int startingLineNumber, const UString& sourceURL, int errorLine, const UString& errorMessage)
2375 {
2376     JSValueRef sourceURLValue = JSValueMakeString(m_scriptContext, jsStringRef(sourceURL).get());
2377     JSValueRef sourceValue = JSValueMakeString(m_scriptContext, jsStringRef(source.data()).get());
2378     JSValueRef startingLineNumberValue = JSValueMakeNumber(m_scriptContext, startingLineNumber);
2379     JSValueRef errorLineValue = JSValueMakeNumber(m_scriptContext, errorLine);
2380     JSValueRef errorMessageValue = JSValueMakeString(m_scriptContext, jsStringRef(errorMessage).get());
2381
2382     JSValueRef exception = 0;
2383     JSValueRef arguments[] = { sourceURLValue, sourceValue, startingLineNumberValue, errorLineValue, errorMessageValue };
2384     callFunction(m_scriptContext, m_scriptObject, "failedToParseScriptSource", 5, arguments, exception);
2385 }
2386
2387 void InspectorController::didPause()
2388 {
2389     JSValueRef exception = 0;
2390     callFunction(m_scriptContext, m_scriptObject, "pausedScript", 0, 0, exception);
2391 }
2392
2393 } // namespace WebCore