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