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