2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "InspectorController.h"
34 #include "CachedResource.h"
36 #include "DOMWindow.h"
37 #include "DocLoader.h"
39 #include "DocumentLoader.h"
41 #include "FloatConversion.h"
42 #include "FloatRect.h"
44 #include "FrameLoader.h"
45 #include "FrameTree.h"
46 #include "FrameView.h"
47 #include "GraphicsContext.h"
48 #include "HitTestResult.h"
49 #include "HTMLFrameOwnerElement.h"
50 #include "InspectorClient.h"
51 #include "JSDOMWindow.h"
52 #include "JSInspectedObjectWrapper.h"
53 #include "JSInspectorCallbackWrapper.h"
56 #include "JavaScriptProfile.h"
59 #include "ResourceRequest.h"
60 #include "ResourceResponse.h"
62 #include "SharedBuffer.h"
63 #include "SystemTime.h"
64 #include "TextEncoding.h"
65 #include "TextIterator.h"
66 #include "ScriptController.h"
67 #include <JavaScriptCore/APICast.h>
68 #include <JavaScriptCore/JSRetainPtr.h>
69 #include <JavaScriptCore/JSStringRef.h>
70 #include <JavaScriptCore/OpaqueJSString.h>
71 #include <runtime/JSLock.h>
72 #include <kjs/ustring.h>
73 #include <runtime/CollectorHeapIterator.h>
74 #include <profiler/Profile.h>
75 #include <profiler/Profiler.h>
76 #include <wtf/RefCounted.h>
80 #include "JSDatabase.h"
83 #if ENABLE(JAVASCRIPT_DEBUGGER)
84 #include "JavaScriptCallFrame.h"
85 #include "JavaScriptDebugServer.h"
86 #include "JSJavaScriptCallFrame.h"
94 static const char* const UserInitiatedProfileName
= "org.webkit.profiles.user-initiated";
96 static JSRetainPtr
<JSStringRef
> jsStringRef(const char* str
)
98 return JSRetainPtr
<JSStringRef
>(Adopt
, JSStringCreateWithUTF8CString(str
));
101 static JSRetainPtr
<JSStringRef
> jsStringRef(const SourceCode
& str
)
103 return JSRetainPtr
<JSStringRef
>(Adopt
, JSStringCreateWithCharacters(str
.data(), str
.length()));
106 static JSRetainPtr
<JSStringRef
> jsStringRef(const String
& str
)
108 return JSRetainPtr
<JSStringRef
>(Adopt
, JSStringCreateWithCharacters(str
.characters(), str
.length()));
111 static JSRetainPtr
<JSStringRef
> jsStringRef(const UString
& str
)
113 return JSRetainPtr
<JSStringRef
>(Adopt
, OpaqueJSString::create(str
).releaseRef());
116 static String
toString(JSContextRef context
, JSValueRef value
, JSValueRef
* exception
)
118 ASSERT_ARG(value
, value
);
121 JSRetainPtr
<JSStringRef
> scriptString(Adopt
, JSValueToStringCopy(context
, value
, exception
));
122 if (exception
&& *exception
)
124 return String(JSStringGetCharactersPtr(scriptString
.get()), JSStringGetLength(scriptString
.get()));
127 #define HANDLE_EXCEPTION(context, exception) handleException((context), (exception), __LINE__)
129 JSValueRef
InspectorController::callSimpleFunction(JSContextRef context
, JSObjectRef thisObject
, const char* functionName
) const
131 JSValueRef exception
= 0;
132 return callFunction(context
, thisObject
, functionName
, 0, 0, exception
);
135 JSValueRef
InspectorController::callFunction(JSContextRef context
, JSObjectRef thisObject
, const char* functionName
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
& exception
) const
137 ASSERT_ARG(context
, context
);
138 ASSERT_ARG(thisObject
, thisObject
);
141 return JSValueMakeUndefined(context
);
143 JSValueRef functionProperty
= JSObjectGetProperty(context
, thisObject
, jsStringRef(functionName
).get(), &exception
);
144 if (HANDLE_EXCEPTION(context
, exception
))
145 return JSValueMakeUndefined(context
);
147 JSObjectRef function
= JSValueToObject(context
, functionProperty
, &exception
);
148 if (HANDLE_EXCEPTION(context
, exception
))
149 return JSValueMakeUndefined(context
);
151 JSValueRef result
= JSObjectCallAsFunction(context
, function
, thisObject
, argumentCount
, arguments
, &exception
);
152 if (HANDLE_EXCEPTION(context
, exception
))
153 return JSValueMakeUndefined(context
);
158 // ConsoleMessage Struct
160 struct ConsoleMessage
{
161 ConsoleMessage(MessageSource s
, MessageLevel l
, const String
& m
, unsigned li
, const String
& u
, unsigned g
)
172 ConsoleMessage(MessageSource s
, MessageLevel l
, ExecState
* exec
, const ArgList
& args
, unsigned li
, const String
& u
, unsigned g
)
175 , wrappedArguments(args
.size())
182 for (unsigned i
= 0; i
< args
.size(); ++i
)
183 wrappedArguments
[i
] = JSInspectedObjectWrapper::wrap(exec
, args
.at(exec
, i
));
186 bool isEqual(ExecState
* exec
, ConsoleMessage
* msg
) const
188 if (msg
->wrappedArguments
.size() != this->wrappedArguments
.size() ||
189 (!exec
&& msg
->wrappedArguments
.size()))
192 for (size_t i
= 0; i
< msg
->wrappedArguments
.size(); ++i
) {
193 ASSERT_ARG(exec
, exec
);
194 if (!JSValueIsEqual(toRef(exec
), toRef(msg
->wrappedArguments
[i
].get()), toRef(this->wrappedArguments
[i
].get()), 0))
198 return msg
->source
== this->source
199 && msg
->level
== this->level
200 && msg
->message
== this->message
201 && msg
->line
== this->line
202 && msg
->url
== this->url
203 && msg
->groupLevel
== this->groupLevel
;
206 MessageSource source
;
209 Vector
<ProtectedPtr
<JSValue
> > wrappedArguments
;
213 unsigned repeatCount
;
216 // XMLHttpRequestResource Class
218 struct XMLHttpRequestResource
{
219 XMLHttpRequestResource(JSC::UString
& sourceString
)
221 JSC::JSLock
lock(false);
222 this->sourceString
= sourceString
.rep();
225 ~XMLHttpRequestResource()
227 JSC::JSLock
lock(false);
228 sourceString
.clear();
231 RefPtr
<JSC::UString::Rep
> sourceString
;
234 // InspectorResource Struct
236 struct InspectorResource
: public RefCounted
<InspectorResource
> {
237 // Keep these in sync with WebInspector.Resource.Type
249 static PassRefPtr
<InspectorResource
> create(long long identifier
, DocumentLoader
* documentLoader
, Frame
* frame
)
251 return adoptRef(new InspectorResource(identifier
, documentLoader
, frame
));
256 setScriptObject(0, 0);
261 if (xmlHttpRequestResource
)
264 if (requestURL
== loader
->requestURL())
267 if (loader
->frameLoader() && requestURL
== loader
->frameLoader()->iconURL())
270 CachedResource
* cachedResource
= frame
->document()->docLoader()->cachedResource(requestURL
.string());
274 switch (cachedResource
->type()) {
275 case CachedResource::ImageResource
:
277 case CachedResource::FontResource
:
279 case CachedResource::CSSStyleSheet
:
281 case CachedResource::XSLStyleSheet
:
284 case CachedResource::Script
:
291 void setScriptObject(JSContextRef context
, JSObjectRef newScriptObject
)
293 if (scriptContext
&& scriptObject
)
294 JSValueUnprotect(scriptContext
, scriptObject
);
296 scriptObject
= newScriptObject
;
297 scriptContext
= context
;
299 ASSERT((context
&& newScriptObject
) || (!context
&& !newScriptObject
));
300 if (context
&& newScriptObject
)
301 JSValueProtect(context
, newScriptObject
);
304 void setXMLHttpRequestProperties(JSC::UString
& data
)
306 xmlHttpRequestResource
.set(new XMLHttpRequestResource(data
));
309 String
sourceString() const
311 if (xmlHttpRequestResource
)
312 return JSC::UString(xmlHttpRequestResource
->sourceString
);
314 RefPtr
<SharedBuffer
> buffer
;
315 String textEncodingName
;
317 if (requestURL
== loader
->requestURL()) {
318 buffer
= loader
->mainResourceData();
319 textEncodingName
= frame
->document()->inputEncoding();
321 CachedResource
* cachedResource
= frame
->document()->docLoader()->cachedResource(requestURL
.string());
325 buffer
= cachedResource
->data();
326 textEncodingName
= cachedResource
->encoding();
332 TextEncoding
encoding(textEncodingName
);
333 if (!encoding
.isValid())
334 encoding
= WindowsLatin1Encoding();
335 return encoding
.decode(buffer
->data(), buffer
->size());
338 long long identifier
;
339 RefPtr
<DocumentLoader
> loader
;
341 OwnPtr
<XMLHttpRequestResource
> xmlHttpRequestResource
;
343 HTTPHeaderMap requestHeaderFields
;
344 HTTPHeaderMap responseHeaderFields
;
346 String suggestedFilename
;
347 JSContextRef scriptContext
;
348 JSObjectRef scriptObject
;
349 long long expectedContentLength
;
354 int responseStatusCode
;
356 double responseReceivedTime
;
360 InspectorResource(long long identifier
, DocumentLoader
* documentLoader
, Frame
* frame
)
361 : identifier(identifier
)
362 , loader(documentLoader
)
364 , xmlHttpRequestResource(0)
367 , expectedContentLength(0)
372 , responseStatusCode(0)
374 , responseReceivedTime(-1.0)
380 // InspectorDatabaseResource Struct
383 struct InspectorDatabaseResource
: public RefCounted
<InspectorDatabaseResource
> {
384 static PassRefPtr
<InspectorDatabaseResource
> create(Database
* database
, const String
& domain
, const String
& name
, const String
& version
)
386 return adoptRef(new InspectorDatabaseResource(database
, domain
, name
, version
));
389 void setScriptObject(JSContextRef context
, JSObjectRef newScriptObject
)
391 if (scriptContext
&& scriptObject
)
392 JSValueUnprotect(scriptContext
, scriptObject
);
394 scriptObject
= newScriptObject
;
395 scriptContext
= context
;
397 ASSERT((context
&& newScriptObject
) || (!context
&& !newScriptObject
));
398 if (context
&& newScriptObject
)
399 JSValueProtect(context
, newScriptObject
);
402 RefPtr
<Database
> database
;
406 JSContextRef scriptContext
;
407 JSObjectRef scriptObject
;
410 InspectorDatabaseResource(Database
* database
, const String
& domain
, const String
& name
, const String
& version
)
422 // JavaScript Callbacks
424 #define SIMPLE_INSPECTOR_CALLBACK(jsFunction, inspectorControllerMethod) \
425 static JSValueRef jsFunction(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef*) \
427 if (InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject))) \
428 controller->inspectorControllerMethod(); \
429 return JSValueMakeUndefined(ctx); \
432 SIMPLE_INSPECTOR_CALLBACK(hideDOMNodeHighlight
, hideHighlight
);
433 SIMPLE_INSPECTOR_CALLBACK(loaded
, scriptObjectReady
);
434 SIMPLE_INSPECTOR_CALLBACK(unloading
, close
);
435 SIMPLE_INSPECTOR_CALLBACK(attach
, attachWindow
);
436 SIMPLE_INSPECTOR_CALLBACK(detach
, detachWindow
);
437 #if ENABLE(JAVASCRIPT_DEBUGGER)
438 SIMPLE_INSPECTOR_CALLBACK(enableDebugger
, enableDebugger
);
439 SIMPLE_INSPECTOR_CALLBACK(disableDebugger
, disableDebugger
);
440 SIMPLE_INSPECTOR_CALLBACK(pauseInDebugger
, pauseInDebugger
);
441 SIMPLE_INSPECTOR_CALLBACK(resumeDebugger
, resumeDebugger
);
442 SIMPLE_INSPECTOR_CALLBACK(stepOverStatementInDebugger
, stepOverStatementInDebugger
);
443 SIMPLE_INSPECTOR_CALLBACK(stepIntoStatementInDebugger
, stepIntoStatementInDebugger
);
444 SIMPLE_INSPECTOR_CALLBACK(stepOutOfFunctionInDebugger
, stepOutOfFunctionInDebugger
);
446 SIMPLE_INSPECTOR_CALLBACK(closeWindow
, closeWindow
);
447 SIMPLE_INSPECTOR_CALLBACK(clearMessages
, clearConsoleMessages
);
448 SIMPLE_INSPECTOR_CALLBACK(startProfiling
, startUserInitiatedProfilingSoon
);
449 SIMPLE_INSPECTOR_CALLBACK(stopProfiling
, stopUserInitiatedProfiling
);
450 SIMPLE_INSPECTOR_CALLBACK(enableProfiler
, enableProfiler
);
451 SIMPLE_INSPECTOR_CALLBACK(disableProfiler
, disableProfiler
);
452 SIMPLE_INSPECTOR_CALLBACK(toggleNodeSearch
, toggleSearchForNodeInPage
);
454 #define BOOL_INSPECTOR_CALLBACK(jsFunction, inspectorControllerMethod) \
455 static JSValueRef jsFunction(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef*) \
457 if (InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject))) \
458 return JSValueMakeBoolean(ctx, controller->inspectorControllerMethod()); \
459 return JSValueMakeUndefined(ctx); \
462 #if ENABLE(JAVASCRIPT_DEBUGGER)
463 BOOL_INSPECTOR_CALLBACK(debuggerEnabled
, debuggerEnabled
);
464 BOOL_INSPECTOR_CALLBACK(pauseOnExceptions
, pauseOnExceptions
);
466 BOOL_INSPECTOR_CALLBACK(profilerEnabled
, profilerEnabled
);
467 BOOL_INSPECTOR_CALLBACK(isWindowVisible
, windowVisible
);
468 BOOL_INSPECTOR_CALLBACK(searchingForNode
, searchingForNodeInPage
);
470 static bool addSourceToFrame(const String
& mimeType
, const String
& source
, Node
* frameNode
)
472 ASSERT_ARG(frameNode
, frameNode
);
477 if (!frameNode
->attached()) {
478 ASSERT_NOT_REACHED();
482 ASSERT(frameNode
->isElementNode());
483 if (!frameNode
->isElementNode())
486 Element
* element
= static_cast<Element
*>(frameNode
);
487 ASSERT(element
->isFrameOwnerElement());
488 if (!element
->isFrameOwnerElement())
491 HTMLFrameOwnerElement
* frameOwner
= static_cast<HTMLFrameOwnerElement
*>(element
);
492 ASSERT(frameOwner
->contentFrame());
493 if (!frameOwner
->contentFrame())
496 FrameLoader
* loader
= frameOwner
->contentFrame()->loader();
498 loader
->setResponseMIMEType(mimeType
);
500 loader
->write(source
);
506 static JSValueRef
addResourceSourceToFrame(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
508 JSValueRef undefined
= JSValueMakeUndefined(ctx
);
510 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
511 if (argumentCount
< 2 || !controller
)
514 JSValueRef identifierValue
= arguments
[0];
515 if (!JSValueIsNumber(ctx
, identifierValue
))
518 long long identifier
= static_cast<long long>(JSValueToNumber(ctx
, identifierValue
, exception
));
519 if (exception
&& *exception
)
522 RefPtr
<InspectorResource
> resource
= controller
->resources().get(identifier
);
527 String sourceString
= resource
->sourceString();
528 if (sourceString
.isEmpty())
531 bool successfullyAddedSource
= addSourceToFrame(resource
->mimeType
, sourceString
, toNode(toJS(arguments
[1])));
532 return JSValueMakeBoolean(ctx
, successfullyAddedSource
);
535 static JSValueRef
addSourceToFrame(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
537 JSValueRef undefined
= JSValueMakeUndefined(ctx
);
539 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
540 if (argumentCount
< 3 || !controller
)
543 JSValueRef mimeTypeValue
= arguments
[0];
544 if (!JSValueIsString(ctx
, mimeTypeValue
))
547 JSValueRef sourceValue
= arguments
[1];
548 if (!JSValueIsString(ctx
, sourceValue
))
551 String mimeType
= toString(ctx
, mimeTypeValue
, exception
);
552 if (mimeType
.isEmpty())
555 String source
= toString(ctx
, sourceValue
, exception
);
556 if (source
.isEmpty())
559 bool successfullyAddedSource
= addSourceToFrame(mimeType
, source
, toNode(toJS(arguments
[2])));
560 return JSValueMakeBoolean(ctx
, successfullyAddedSource
);
563 static JSValueRef
getResourceDocumentNode(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
565 JSValueRef undefined
= JSValueMakeUndefined(ctx
);
567 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
568 if (!argumentCount
|| argumentCount
> 1 || !controller
)
571 JSValueRef identifierValue
= arguments
[0];
572 if (!JSValueIsNumber(ctx
, identifierValue
))
575 long long identifier
= static_cast<long long>(JSValueToNumber(ctx
, identifierValue
, exception
));
576 if (exception
&& *exception
)
579 RefPtr
<InspectorResource
> resource
= controller
->resources().get(identifier
);
584 Frame
* frame
= resource
->frame
.get();
586 Document
* document
= frame
->document();
590 if (document
->isPluginDocument() || document
->isImageDocument() || document
->isMediaDocument())
593 ExecState
* exec
= toJSDOMWindowShell(resource
->frame
.get())->window()->globalExec();
595 JSC::JSLock
lock(false);
596 JSValueRef documentValue
= toRef(JSInspectedObjectWrapper::wrap(exec
, toJS(exec
, document
)));
597 return documentValue
;
600 static JSValueRef
highlightDOMNode(JSContextRef context
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* /*exception*/)
602 JSValueRef undefined
= JSValueMakeUndefined(context
);
604 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
605 if (argumentCount
< 1 || !controller
)
608 JSQuarantinedObjectWrapper
* wrapper
= JSQuarantinedObjectWrapper::asWrapper(toJS(arguments
[0]));
611 Node
* node
= toNode(wrapper
->unwrappedObject());
615 controller
->highlight(node
);
620 static JSValueRef
search(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
622 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
624 return JSValueMakeUndefined(ctx
);
626 if (argumentCount
< 2 || !JSValueIsString(ctx
, arguments
[1]))
627 return JSValueMakeUndefined(ctx
);
629 Node
* node
= toNode(toJS(arguments
[0]));
631 return JSValueMakeUndefined(ctx
);
633 String target
= toString(ctx
, arguments
[1], exception
);
635 JSObjectRef global
= JSContextGetGlobalObject(ctx
);
637 JSValueRef arrayProperty
= JSObjectGetProperty(ctx
, global
, jsStringRef("Array").get(), exception
);
638 if (exception
&& *exception
)
639 return JSValueMakeUndefined(ctx
);
641 JSObjectRef arrayConstructor
= JSValueToObject(ctx
, arrayProperty
, exception
);
642 if (exception
&& *exception
)
643 return JSValueMakeUndefined(ctx
);
645 JSObjectRef result
= JSObjectCallAsConstructor(ctx
, arrayConstructor
, 0, 0, exception
);
646 if (exception
&& *exception
)
647 return JSValueMakeUndefined(ctx
);
649 JSValueRef pushProperty
= JSObjectGetProperty(ctx
, result
, jsStringRef("push").get(), exception
);
650 if (exception
&& *exception
)
651 return JSValueMakeUndefined(ctx
);
653 JSObjectRef pushFunction
= JSValueToObject(ctx
, pushProperty
, exception
);
654 if (exception
&& *exception
)
655 return JSValueMakeUndefined(ctx
);
657 RefPtr
<Range
> searchRange(rangeOfContents(node
));
659 ExceptionCode ec
= 0;
661 RefPtr
<Range
> resultRange(findPlainText(searchRange
.get(), target
, true, false));
662 if (resultRange
->collapsed(ec
))
665 // A non-collapsed result range can in some funky whitespace cases still not
666 // advance the range's start position (4509328). Break to avoid infinite loop.
667 VisiblePosition newStart
= endVisiblePosition(resultRange
.get(), DOWNSTREAM
);
668 if (newStart
== startVisiblePosition(searchRange
.get(), DOWNSTREAM
))
671 JSC::JSLock
lock(false);
672 JSValueRef arg0
= toRef(toJS(toJS(ctx
), resultRange
.get()));
673 JSObjectCallAsFunction(ctx
, pushFunction
, result
, 1, &arg0
, exception
);
674 if (exception
&& *exception
)
675 return JSValueMakeUndefined(ctx
);
677 setStart(searchRange
.get(), newStart
);
684 static JSValueRef
databaseTableNames(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
686 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
688 return JSValueMakeUndefined(ctx
);
690 if (argumentCount
< 1)
691 return JSValueMakeUndefined(ctx
);
693 JSQuarantinedObjectWrapper
* wrapper
= JSQuarantinedObjectWrapper::asWrapper(toJS(arguments
[0]));
695 return JSValueMakeUndefined(ctx
);
697 Database
* database
= toDatabase(wrapper
->unwrappedObject());
699 return JSValueMakeUndefined(ctx
);
701 JSObjectRef global
= JSContextGetGlobalObject(ctx
);
703 JSValueRef arrayProperty
= JSObjectGetProperty(ctx
, global
, jsStringRef("Array").get(), exception
);
704 if (exception
&& *exception
)
705 return JSValueMakeUndefined(ctx
);
707 JSObjectRef arrayConstructor
= JSValueToObject(ctx
, arrayProperty
, exception
);
708 if (exception
&& *exception
)
709 return JSValueMakeUndefined(ctx
);
711 JSObjectRef result
= JSObjectCallAsConstructor(ctx
, arrayConstructor
, 0, 0, exception
);
712 if (exception
&& *exception
)
713 return JSValueMakeUndefined(ctx
);
715 JSValueRef pushProperty
= JSObjectGetProperty(ctx
, result
, jsStringRef("push").get(), exception
);
716 if (exception
&& *exception
)
717 return JSValueMakeUndefined(ctx
);
719 JSObjectRef pushFunction
= JSValueToObject(ctx
, pushProperty
, exception
);
720 if (exception
&& *exception
)
721 return JSValueMakeUndefined(ctx
);
723 Vector
<String
> tableNames
= database
->tableNames();
724 unsigned length
= tableNames
.size();
725 for (unsigned i
= 0; i
< length
; ++i
) {
726 String tableName
= tableNames
[i
];
727 JSValueRef tableNameValue
= JSValueMakeString(ctx
, jsStringRef(tableName
).get());
729 JSValueRef pushArguments
[] = { tableNameValue
};
730 JSObjectCallAsFunction(ctx
, pushFunction
, result
, 1, pushArguments
, exception
);
731 if (exception
&& *exception
)
732 return JSValueMakeUndefined(ctx
);
739 static JSValueRef
inspectedWindow(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t /*argumentCount*/, const JSValueRef
[] /*arguments[]*/, JSValueRef
* /*exception*/)
741 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
743 return JSValueMakeUndefined(ctx
);
745 JSDOMWindow
* inspectedWindow
= toJSDOMWindow(controller
->inspectedPage()->mainFrame());
747 return toRef(JSInspectedObjectWrapper::wrap(inspectedWindow
->globalExec(), inspectedWindow
));
750 static JSValueRef
setting(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t /*argumentCount*/, const JSValueRef arguments
[], JSValueRef
* exception
)
752 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
754 return JSValueMakeUndefined(ctx
);
756 JSValueRef keyValue
= arguments
[0];
757 if (!JSValueIsString(ctx
, keyValue
))
758 return JSValueMakeUndefined(ctx
);
760 const InspectorController::Setting
& setting
= controller
->setting(toString(ctx
, keyValue
, exception
));
762 switch (setting
.type()) {
764 case InspectorController::Setting::NoType
:
765 return JSValueMakeUndefined(ctx
);
766 case InspectorController::Setting::StringType
:
767 return JSValueMakeString(ctx
, jsStringRef(setting
.string()).get());
768 case InspectorController::Setting::DoubleType
:
769 return JSValueMakeNumber(ctx
, setting
.doubleValue());
770 case InspectorController::Setting::IntegerType
:
771 return JSValueMakeNumber(ctx
, setting
.integerValue());
772 case InspectorController::Setting::BooleanType
:
773 return JSValueMakeBoolean(ctx
, setting
.booleanValue());
774 case InspectorController::Setting::StringVectorType
: {
775 Vector
<JSValueRef
> stringValues
;
776 const Vector
<String
>& strings
= setting
.stringVector();
777 const unsigned length
= strings
.size();
778 for (unsigned i
= 0; i
< length
; ++i
)
779 stringValues
.append(JSValueMakeString(ctx
, jsStringRef(strings
[i
]).get()));
781 JSObjectRef stringsArray
= JSObjectMakeArray(ctx
, stringValues
.size(), stringValues
.data(), exception
);
782 if (exception
&& *exception
)
783 return JSValueMakeUndefined(ctx
);
789 static JSValueRef
setSetting(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t /*argumentCount*/, const JSValueRef arguments
[], JSValueRef
* exception
)
791 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
793 return JSValueMakeUndefined(ctx
);
795 JSValueRef keyValue
= arguments
[0];
796 if (!JSValueIsString(ctx
, keyValue
))
797 return JSValueMakeUndefined(ctx
);
799 InspectorController::Setting setting
;
801 JSValueRef value
= arguments
[1];
802 switch (JSValueGetType(ctx
, value
)) {
804 case kJSTypeUndefined
:
806 // Do nothing. The setting is already NoType.
807 ASSERT(setting
.type() == InspectorController::Setting::NoType
);
810 setting
.set(toString(ctx
, value
, exception
));
813 setting
.set(JSValueToNumber(ctx
, value
, exception
));
816 setting
.set(JSValueToBoolean(ctx
, value
));
818 case kJSTypeObject
: {
819 JSObjectRef object
= JSValueToObject(ctx
, value
, 0);
820 JSValueRef lengthValue
= JSObjectGetProperty(ctx
, object
, jsStringRef("length").get(), exception
);
821 if (exception
&& *exception
)
822 return JSValueMakeUndefined(ctx
);
824 Vector
<String
> strings
;
825 const unsigned length
= static_cast<unsigned>(JSValueToNumber(ctx
, lengthValue
, 0));
826 for (unsigned i
= 0; i
< length
; ++i
) {
827 JSValueRef itemValue
= JSObjectGetPropertyAtIndex(ctx
, object
, i
, exception
);
828 if (exception
&& *exception
)
829 return JSValueMakeUndefined(ctx
);
830 strings
.append(toString(ctx
, itemValue
, exception
));
831 if (exception
&& *exception
)
832 return JSValueMakeUndefined(ctx
);
835 setting
.set(strings
);
840 if (exception
&& *exception
)
841 return JSValueMakeUndefined(ctx
);
843 controller
->setSetting(toString(ctx
, keyValue
, exception
), setting
);
845 return JSValueMakeUndefined(ctx
);
848 static JSValueRef
localizedStrings(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t /*argumentCount*/, const JSValueRef
[] /*arguments[]*/, JSValueRef
* /*exception*/)
850 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
852 return JSValueMakeUndefined(ctx
);
854 String url
= controller
->localizedStringsURL();
856 return JSValueMakeNull(ctx
);
858 return JSValueMakeString(ctx
, jsStringRef(url
).get());
861 static JSValueRef
platform(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t /*argumentCount*/, const JSValueRef
[] /*arguments[]*/, JSValueRef
* /*exception*/)
864 #ifdef BUILDING_ON_TIGER
865 static const String platform
= "mac-tiger";
867 static const String platform
= "mac-leopard";
869 #elif PLATFORM(WIN_OS)
870 static const String platform
= "windows";
872 static const String platform
= "qt";
874 static const String platform
= "gtk";
876 static const String platform
= "wx";
878 static const String platform
= "unknown";
881 JSValueRef platformValue
= JSValueMakeString(ctx
, jsStringRef(platform
).get());
883 return platformValue
;
886 static JSValueRef
moveByUnrestricted(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
888 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
890 return JSValueMakeUndefined(ctx
);
892 if (argumentCount
< 2)
893 return JSValueMakeUndefined(ctx
);
895 double x
= JSValueToNumber(ctx
, arguments
[0], exception
);
896 if (exception
&& *exception
)
897 return JSValueMakeUndefined(ctx
);
899 double y
= JSValueToNumber(ctx
, arguments
[1], exception
);
900 if (exception
&& *exception
)
901 return JSValueMakeUndefined(ctx
);
903 controller
->moveWindowBy(narrowPrecisionToFloat(x
), narrowPrecisionToFloat(y
));
905 return JSValueMakeUndefined(ctx
);
908 static JSValueRef
setAttachedWindowHeight(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
910 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
912 return JSValueMakeUndefined(ctx
);
914 if (argumentCount
< 1)
915 return JSValueMakeUndefined(ctx
);
917 unsigned height
= static_cast<unsigned>(JSValueToNumber(ctx
, arguments
[0], exception
));
918 if (exception
&& *exception
)
919 return JSValueMakeUndefined(ctx
);
921 controller
->setAttachedWindowHeight(height
);
923 return JSValueMakeUndefined(ctx
);
926 static JSValueRef
wrapCallback(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
928 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
930 return JSValueMakeUndefined(ctx
);
932 if (argumentCount
< 1)
933 return JSValueMakeUndefined(ctx
);
936 return toRef(JSInspectorCallbackWrapper::wrap(toJS(ctx
), toJS(arguments
[0])));
939 #if ENABLE(JAVASCRIPT_DEBUGGER)
940 static JSValueRef
currentCallFrame(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t /*argumentCount*/, const JSValueRef
[] /*arguments*/, JSValueRef
* /*exception*/)
942 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
944 return JSValueMakeUndefined(ctx
);
946 JavaScriptCallFrame
* callFrame
= controller
->currentCallFrame();
947 if (!callFrame
|| !callFrame
->isValid())
948 return JSValueMakeNull(ctx
);
950 ExecState
* globalExec
= callFrame
->scopeChain()->globalObject()->globalExec();
953 return toRef(JSInspectedObjectWrapper::wrap(globalExec
, toJS(toJS(ctx
), callFrame
)));
956 static JSValueRef
setPauseOnExceptions(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* /*exception*/)
958 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
960 return JSValueMakeUndefined(ctx
);
962 if (argumentCount
< 1)
963 return JSValueMakeUndefined(ctx
);
965 controller
->setPauseOnExceptions(JSValueToBoolean(ctx
, arguments
[0]));
967 return JSValueMakeUndefined(ctx
);
970 static JSValueRef
addBreakpoint(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
972 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
974 return JSValueMakeUndefined(ctx
);
976 if (argumentCount
< 2)
977 return JSValueMakeUndefined(ctx
);
979 double sourceID
= JSValueToNumber(ctx
, arguments
[0], exception
);
980 if (exception
&& *exception
)
981 return JSValueMakeUndefined(ctx
);
983 double lineNumber
= JSValueToNumber(ctx
, arguments
[1], exception
);
984 if (exception
&& *exception
)
985 return JSValueMakeUndefined(ctx
);
987 controller
->addBreakpoint(static_cast<int>(sourceID
), static_cast<unsigned>(lineNumber
));
989 return JSValueMakeUndefined(ctx
);
992 static JSValueRef
removeBreakpoint(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
994 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
996 return JSValueMakeUndefined(ctx
);
998 if (argumentCount
< 2)
999 return JSValueMakeUndefined(ctx
);
1001 double sourceID
= JSValueToNumber(ctx
, arguments
[0], exception
);
1002 if (exception
&& *exception
)
1003 return JSValueMakeUndefined(ctx
);
1005 double lineNumber
= JSValueToNumber(ctx
, arguments
[1], exception
);
1006 if (exception
&& *exception
)
1007 return JSValueMakeUndefined(ctx
);
1009 controller
->removeBreakpoint(static_cast<int>(sourceID
), static_cast<unsigned>(lineNumber
));
1011 return JSValueMakeUndefined(ctx
);
1015 static JSValueRef
profiles(JSContextRef ctx
, JSObjectRef
/*function*/, JSObjectRef thisObject
, size_t /*argumentCount*/, const JSValueRef
[] /*arguments*/, JSValueRef
* exception
)
1017 InspectorController
* controller
= reinterpret_cast<InspectorController
*>(JSObjectGetPrivate(thisObject
));
1019 return JSValueMakeUndefined(ctx
);
1023 const Vector
<RefPtr
<Profile
> >& profiles
= controller
->profiles();
1025 JSObjectRef global
= JSContextGetGlobalObject(ctx
);
1027 JSValueRef arrayProperty
= JSObjectGetProperty(ctx
, global
, jsStringRef("Array").get(), exception
);
1028 if (exception
&& *exception
)
1029 return JSValueMakeUndefined(ctx
);
1031 JSObjectRef arrayConstructor
= JSValueToObject(ctx
, arrayProperty
, exception
);
1032 if (exception
&& *exception
)
1033 return JSValueMakeUndefined(ctx
);
1035 JSObjectRef result
= JSObjectCallAsConstructor(ctx
, arrayConstructor
, 0, 0, exception
);
1036 if (exception
&& *exception
)
1037 return JSValueMakeUndefined(ctx
);
1039 JSValueRef pushProperty
= JSObjectGetProperty(ctx
, result
, jsStringRef("push").get(), exception
);
1040 if (exception
&& *exception
)
1041 return JSValueMakeUndefined(ctx
);
1043 JSObjectRef pushFunction
= JSValueToObject(ctx
, pushProperty
, exception
);
1044 if (exception
&& *exception
)
1045 return JSValueMakeUndefined(ctx
);
1047 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
1048 JSValueRef arg0
= toRef(toJS(toJS(ctx
), profiles
[i
].get()));
1049 JSObjectCallAsFunction(ctx
, pushFunction
, result
, 1, &arg0
, exception
);
1050 if (exception
&& *exception
)
1051 return JSValueMakeUndefined(ctx
);
1057 // InspectorController Class
1059 static unsigned s_inspectorControllerCount
;
1060 static HashMap
<String
, InspectorController::Setting
*>* s_settingCache
;
1062 InspectorController::InspectorController(Page
* page
, InspectorClient
* client
)
1063 : m_inspectedPage(page
)
1067 , m_controllerScriptObject(0)
1068 , m_scriptContext(0)
1069 , m_windowVisible(false)
1070 #if ENABLE(JAVASCRIPT_DEBUGGER)
1071 , m_debuggerEnabled(false)
1072 , m_attachDebuggerWhenShown(false)
1074 , m_profilerEnabled(false)
1075 , m_recordingUserInitiatedProfile(false)
1076 , m_showAfterVisible(ElementsPanel
)
1077 , m_nextIdentifier(-2)
1079 , m_searchingForNode(false)
1080 , m_currentUserInitiatedProfileNumber(-1)
1081 , m_nextUserInitiatedProfileNumber(1)
1082 , m_previousMessage(0)
1083 , m_startProfiling(this, &InspectorController::startUserInitiatedProfiling
)
1085 ASSERT_ARG(page
, page
);
1086 ASSERT_ARG(client
, client
);
1087 ++s_inspectorControllerCount
;
1090 InspectorController::~InspectorController()
1092 m_client
->inspectorDestroyed();
1094 if (m_scriptContext
) {
1095 JSValueRef exception
= 0;
1097 JSObjectRef global
= JSContextGetGlobalObject(m_scriptContext
);
1098 JSValueRef controllerProperty
= JSObjectGetProperty(m_scriptContext
, global
, jsStringRef("InspectorController").get(), &exception
);
1099 if (!HANDLE_EXCEPTION(m_scriptContext
, exception
)) {
1100 if (JSObjectRef controller
= JSValueToObject(m_scriptContext
, controllerProperty
, &exception
)) {
1101 if (!HANDLE_EXCEPTION(m_scriptContext
, exception
))
1102 JSObjectSetPrivate(controller
, 0);
1108 m_page
->setParentInspectorController(0);
1110 // m_inspectedPage should have been cleared in inspectedPageDestroyed().
1111 ASSERT(!m_inspectedPage
);
1113 deleteAllValues(m_frameResources
);
1114 deleteAllValues(m_consoleMessages
);
1116 ASSERT(s_inspectorControllerCount
);
1117 --s_inspectorControllerCount
;
1119 if (!s_inspectorControllerCount
&& s_settingCache
) {
1120 deleteAllValues(*s_settingCache
);
1121 delete s_settingCache
;
1126 void InspectorController::inspectedPageDestroyed()
1130 ASSERT(m_inspectedPage
);
1131 m_inspectedPage
= 0;
1134 bool InspectorController::enabled() const
1136 if (!m_inspectedPage
)
1138 return m_inspectedPage
->settings()->developerExtrasEnabled();
1141 const InspectorController::Setting
& InspectorController::setting(const String
& key
) const
1143 if (!s_settingCache
)
1144 s_settingCache
= new HashMap
<String
, Setting
*>;
1146 if (Setting
* cachedSetting
= s_settingCache
->get(key
))
1147 return *cachedSetting
;
1149 Setting
* newSetting
= new Setting
;
1150 s_settingCache
->set(key
, newSetting
);
1152 m_client
->populateSetting(key
, *newSetting
);
1157 void InspectorController::setSetting(const String
& key
, const Setting
& setting
)
1159 if (setting
.type() == Setting::NoType
) {
1160 if (s_settingCache
) {
1161 Setting
* cachedSetting
= s_settingCache
->get(key
);
1162 if (cachedSetting
) {
1163 s_settingCache
->remove(key
);
1164 delete cachedSetting
;
1168 m_client
->removeSetting(key
);
1172 if (!s_settingCache
)
1173 s_settingCache
= new HashMap
<String
, Setting
*>;
1175 if (Setting
* cachedSetting
= s_settingCache
->get(key
))
1176 *cachedSetting
= setting
;
1178 s_settingCache
->set(key
, new Setting(setting
));
1180 m_client
->storeSetting(key
, setting
);
1183 String
InspectorController::localizedStringsURL()
1187 return m_client
->localizedStringsURL();
1190 // Trying to inspect something in a frame with JavaScript disabled would later lead to
1191 // crashes trying to create JavaScript wrappers. Some day we could fix this issue, but
1192 // for now prevent crashes here by never targeting a node in such a frame.
1193 static bool canPassNodeToJavaScript(Node
* node
)
1197 Frame
* frame
= node
->document()->frame();
1198 return frame
&& frame
->script()->isEnabled();
1201 void InspectorController::inspect(Node
* node
)
1203 if (!canPassNodeToJavaScript(node
) || !enabled())
1208 if (node
->nodeType() != Node::ELEMENT_NODE
&& node
->nodeType() != Node::DOCUMENT_NODE
)
1209 node
= node
->parentNode();
1210 m_nodeToFocus
= node
;
1212 if (!m_scriptObject
) {
1213 m_showAfterVisible
= ElementsPanel
;
1217 if (windowVisible())
1221 void InspectorController::focusNode()
1226 ASSERT(m_scriptContext
);
1227 ASSERT(m_scriptObject
);
1228 ASSERT(m_nodeToFocus
);
1230 Frame
* frame
= m_nodeToFocus
->document()->frame();
1234 ExecState
* exec
= toJSDOMWindow(frame
)->globalExec();
1239 JSC::JSLock
lock(false);
1240 arg0
= toRef(JSInspectedObjectWrapper::wrap(exec
, toJS(exec
, m_nodeToFocus
.get())));
1245 JSValueRef exception
= 0;
1246 callFunction(m_scriptContext
, m_scriptObject
, "updateFocusedNode", 1, &arg0
, exception
);
1249 void InspectorController::highlight(Node
* node
)
1253 ASSERT_ARG(node
, node
);
1254 m_highlightedNode
= node
;
1255 m_client
->highlight(node
);
1258 void InspectorController::hideHighlight()
1262 m_client
->hideHighlight();
1265 bool InspectorController::windowVisible()
1267 return m_windowVisible
;
1270 void InspectorController::setWindowVisible(bool visible
, bool attached
)
1272 if (visible
== m_windowVisible
)
1275 m_windowVisible
= visible
;
1277 if (!m_scriptContext
|| !m_scriptObject
)
1280 if (m_windowVisible
) {
1281 setAttachedWindow(attached
);
1282 populateScriptObjects();
1285 #if ENABLE(JAVASCRIPT_DEBUGGER)
1286 if (m_attachDebuggerWhenShown
)
1289 if (m_showAfterVisible
!= CurrentPanel
)
1290 showPanel(m_showAfterVisible
);
1292 #if ENABLE(JAVASCRIPT_DEBUGGER)
1295 resetScriptObjects();
1298 m_showAfterVisible
= CurrentPanel
;
1301 void InspectorController::addMessageToConsole(MessageSource source
, MessageLevel level
, ExecState
* exec
, const ArgList
& arguments
, unsigned lineNumber
, const String
& sourceURL
)
1306 addConsoleMessage(exec
, new ConsoleMessage(source
, level
, exec
, arguments
, lineNumber
, sourceURL
, m_groupLevel
));
1309 void InspectorController::addMessageToConsole(MessageSource source
, MessageLevel level
, const String
& message
, unsigned lineNumber
, const String
& sourceID
)
1314 addConsoleMessage(0, new ConsoleMessage(source
, level
, message
, lineNumber
, sourceID
, m_groupLevel
));
1317 void InspectorController::addConsoleMessage(ExecState
* exec
, ConsoleMessage
* consoleMessage
)
1320 ASSERT_ARG(consoleMessage
, consoleMessage
);
1322 if (m_previousMessage
&& m_previousMessage
->isEqual(exec
, consoleMessage
)) {
1323 ++m_previousMessage
->repeatCount
;
1324 delete consoleMessage
;
1326 m_previousMessage
= consoleMessage
;
1327 m_consoleMessages
.append(consoleMessage
);
1330 if (windowVisible())
1331 addScriptConsoleMessage(m_previousMessage
);
1334 void InspectorController::clearConsoleMessages()
1336 deleteAllValues(m_consoleMessages
);
1337 m_consoleMessages
.clear();
1338 m_previousMessage
= 0;
1342 void InspectorController::toggleRecordButton(bool isProfiling
)
1344 if (!m_scriptContext
)
1347 JSValueRef exception
= 0;
1348 JSValueRef isProvingValue
= JSValueMakeBoolean(m_scriptContext
, isProfiling
);
1349 callFunction(m_scriptContext
, m_scriptObject
, "setRecordingProfile", 1, &isProvingValue
, exception
);
1352 void InspectorController::startGroup(MessageSource source
, ExecState
* exec
, const ArgList
& arguments
, unsigned lineNumber
, const String
& sourceURL
)
1356 addConsoleMessage(exec
, new ConsoleMessage(source
, StartGroupMessageLevel
, exec
, arguments
, lineNumber
, sourceURL
, m_groupLevel
));
1359 void InspectorController::endGroup(MessageSource source
, unsigned lineNumber
, const String
& sourceURL
)
1361 if (m_groupLevel
== 0)
1366 addConsoleMessage(0, new ConsoleMessage(source
, EndGroupMessageLevel
, String(), lineNumber
, sourceURL
, m_groupLevel
));
1369 void InspectorController::addProfile(PassRefPtr
<Profile
> prpProfile
, unsigned lineNumber
, const UString
& sourceURL
)
1374 RefPtr
<Profile
> profile
= prpProfile
;
1375 m_profiles
.append(profile
);
1377 if (windowVisible())
1378 addScriptProfile(profile
.get());
1380 addProfileMessageToConsole(profile
, lineNumber
, sourceURL
);
1383 void InspectorController::addProfileMessageToConsole(PassRefPtr
<Profile
> prpProfile
, unsigned lineNumber
, const UString
& sourceURL
)
1385 RefPtr
<Profile
> profile
= prpProfile
;
1387 UString message
= "Profile \"webkit-profile://";
1388 message
+= encodeWithURLEscapeSequences(profile
->title());
1390 message
+= UString::from(profile
->uid());
1391 message
+= "\" finished.";
1392 addMessageToConsole(JSMessageSource
, LogMessageLevel
, message
, lineNumber
, sourceURL
);
1395 void InspectorController::attachWindow()
1399 m_client
->attachWindow();
1402 void InspectorController::detachWindow()
1406 m_client
->detachWindow();
1409 void InspectorController::setAttachedWindow(bool attached
)
1411 if (!enabled() || !m_scriptContext
|| !m_scriptObject
)
1414 JSValueRef attachedValue
= JSValueMakeBoolean(m_scriptContext
, attached
);
1416 JSValueRef exception
= 0;
1417 callFunction(m_scriptContext
, m_scriptObject
, "setAttachedWindow", 1, &attachedValue
, exception
);
1420 void InspectorController::setAttachedWindowHeight(unsigned height
)
1424 m_client
->setAttachedWindowHeight(height
);
1427 void InspectorController::toggleSearchForNodeInPage()
1432 m_searchingForNode
= !m_searchingForNode
;
1433 if (!m_searchingForNode
)
1437 void InspectorController::mouseDidMoveOverElement(const HitTestResult
& result
, unsigned modifierFlags
)
1439 if (!enabled() || !m_searchingForNode
)
1442 Node
* node
= result
.innerNode();
1447 void InspectorController::handleMousePressOnNode(Node
* node
)
1452 ASSERT(m_searchingForNode
);
1457 // inspect() will implicitly call ElementsPanel's focusedNodeChanged() and the hover feedback will be stopped there.
1461 void InspectorController::inspectedWindowScriptObjectCleared(Frame
* frame
)
1463 if (!enabled() || !m_scriptContext
|| !m_scriptObject
)
1466 JSDOMWindow
* win
= toJSDOMWindow(frame
);
1467 ExecState
* exec
= win
->globalExec();
1472 JSC::JSLock
lock(false);
1473 arg0
= toRef(JSInspectedObjectWrapper::wrap(exec
, win
));
1476 JSValueRef exception
= 0;
1477 callFunction(m_scriptContext
, m_scriptObject
, "inspectedWindowCleared", 1, &arg0
, exception
);
1480 void InspectorController::windowScriptObjectAvailable()
1482 if (!m_page
|| !enabled())
1485 m_scriptContext
= toRef(m_page
->mainFrame()->script()->globalObject()->globalExec());
1487 JSObjectRef global
= JSContextGetGlobalObject(m_scriptContext
);
1490 static JSStaticFunction staticFunctions
[] = {
1491 // SIMPLE_INSPECTOR_CALLBACK
1492 { "hideDOMNodeHighlight", WebCore::hideDOMNodeHighlight
, kJSPropertyAttributeNone
},
1493 { "loaded", WebCore::loaded
, kJSPropertyAttributeNone
},
1494 { "windowUnloading", WebCore::unloading
, kJSPropertyAttributeNone
},
1495 { "attach", WebCore::attach
, kJSPropertyAttributeNone
},
1496 { "detach", WebCore::detach
, kJSPropertyAttributeNone
},
1497 #if ENABLE(JAVASCRIPT_DEBUGGER)
1498 { "enableDebugger", WebCore::enableDebugger
, kJSPropertyAttributeNone
},
1499 { "disableDebugger", WebCore::disableDebugger
, kJSPropertyAttributeNone
},
1500 { "pauseInDebugger", WebCore::pauseInDebugger
, kJSPropertyAttributeNone
},
1501 { "resumeDebugger", WebCore::resumeDebugger
, kJSPropertyAttributeNone
},
1502 { "stepOverStatementInDebugger", WebCore::stepOverStatementInDebugger
, kJSPropertyAttributeNone
},
1503 { "stepIntoStatementInDebugger", WebCore::stepIntoStatementInDebugger
, kJSPropertyAttributeNone
},
1504 { "stepOutOfFunctionInDebugger", WebCore::stepOutOfFunctionInDebugger
, kJSPropertyAttributeNone
},
1506 { "closeWindow", WebCore::closeWindow
, kJSPropertyAttributeNone
},
1507 { "clearMessages", WebCore::clearMessages
, kJSPropertyAttributeNone
},
1508 { "startProfiling", WebCore::startProfiling
, kJSPropertyAttributeNone
},
1509 { "stopProfiling", WebCore::stopProfiling
, kJSPropertyAttributeNone
},
1510 { "enableProfiler", WebCore::enableProfiler
, kJSPropertyAttributeNone
},
1511 { "disableProfiler", WebCore::disableProfiler
, kJSPropertyAttributeNone
},
1512 { "toggleNodeSearch", WebCore::toggleNodeSearch
, kJSPropertyAttributeNone
},
1514 // BOOL_INSPECTOR_CALLBACK
1515 #if ENABLE(JAVASCRIPT_DEBUGGER)
1516 { "debuggerEnabled", WebCore::debuggerEnabled
, kJSPropertyAttributeNone
},
1517 { "pauseOnExceptions", WebCore::pauseOnExceptions
, kJSPropertyAttributeNone
},
1519 { "profilerEnabled", WebCore::profilerEnabled
, kJSPropertyAttributeNone
},
1520 { "isWindowVisible", WebCore::isWindowVisible
, kJSPropertyAttributeNone
},
1521 { "searchingForNode", WebCore::searchingForNode
, kJSPropertyAttributeNone
},
1524 { "addResourceSourceToFrame", WebCore::addResourceSourceToFrame
, kJSPropertyAttributeNone
},
1525 { "addSourceToFrame", WebCore::addSourceToFrame
, kJSPropertyAttributeNone
},
1526 { "getResourceDocumentNode", WebCore::getResourceDocumentNode
, kJSPropertyAttributeNone
},
1527 { "highlightDOMNode", WebCore::highlightDOMNode
, kJSPropertyAttributeNone
},
1528 { "search", WebCore::search
, kJSPropertyAttributeNone
},
1529 #if ENABLE(DATABASE)
1530 { "databaseTableNames", WebCore::databaseTableNames
, kJSPropertyAttributeNone
},
1532 { "setting", WebCore::setting
, kJSPropertyAttributeNone
},
1533 { "setSetting", WebCore::setSetting
, kJSPropertyAttributeNone
},
1534 { "inspectedWindow", WebCore::inspectedWindow
, kJSPropertyAttributeNone
},
1535 { "localizedStringsURL", WebCore::localizedStrings
, kJSPropertyAttributeNone
},
1536 { "platform", WebCore::platform
, kJSPropertyAttributeNone
},
1537 { "moveByUnrestricted", WebCore::moveByUnrestricted
, kJSPropertyAttributeNone
},
1538 { "setAttachedWindowHeight", WebCore::setAttachedWindowHeight
, kJSPropertyAttributeNone
},
1539 { "wrapCallback", WebCore::wrapCallback
, kJSPropertyAttributeNone
},
1540 #if ENABLE(JAVASCRIPT_DEBUGGER)
1541 { "currentCallFrame", WebCore::currentCallFrame
, kJSPropertyAttributeNone
},
1542 { "setPauseOnExceptions", WebCore::setPauseOnExceptions
, kJSPropertyAttributeNone
},
1543 { "addBreakpoint", WebCore::addBreakpoint
, kJSPropertyAttributeNone
},
1544 { "removeBreakpoint", WebCore::removeBreakpoint
, kJSPropertyAttributeNone
},
1546 { "profiles", WebCore::profiles
, kJSPropertyAttributeNone
},
1550 JSClassDefinition inspectorControllerDefinition
= {
1551 0, kJSClassAttributeNone
, "InspectorController", 0, 0, staticFunctions
,
1552 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1555 JSClassRef controllerClass
= JSClassCreate(&inspectorControllerDefinition
);
1556 ASSERT(controllerClass
);
1558 m_controllerScriptObject
= JSObjectMake(m_scriptContext
, controllerClass
, reinterpret_cast<void*>(this));
1559 ASSERT(m_controllerScriptObject
);
1561 JSObjectSetProperty(m_scriptContext
, global
, jsStringRef("InspectorController").get(), m_controllerScriptObject
, kJSPropertyAttributeNone
, 0);
1564 void InspectorController::scriptObjectReady()
1566 ASSERT(m_scriptContext
);
1567 if (!m_scriptContext
)
1570 JSObjectRef global
= JSContextGetGlobalObject(m_scriptContext
);
1573 JSValueRef exception
= 0;
1575 JSValueRef inspectorValue
= JSObjectGetProperty(m_scriptContext
, global
, jsStringRef("WebInspector").get(), &exception
);
1576 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1579 ASSERT(inspectorValue
);
1580 if (!inspectorValue
)
1583 m_scriptObject
= JSValueToObject(m_scriptContext
, inspectorValue
, &exception
);
1584 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1587 ASSERT(m_scriptObject
);
1589 JSValueProtect(m_scriptContext
, m_scriptObject
);
1591 // Make sure our window is visible now that the page loaded
1595 void InspectorController::show()
1601 m_page
= m_client
->createPage();
1604 m_page
->setParentInspectorController(this);
1606 // showWindow() will be called after the page loads in scriptObjectReady()
1613 void InspectorController::showPanel(SpecialPanels panel
)
1620 if (!m_scriptObject
) {
1621 m_showAfterVisible
= panel
;
1625 if (panel
== CurrentPanel
)
1628 const char* showFunctionName
;
1631 showFunctionName
= "showConsole";
1633 case DatabasesPanel
:
1634 showFunctionName
= "showDatabasesPanel";
1637 showFunctionName
= "showElementsPanel";
1640 showFunctionName
= "showProfilesPanel";
1642 case ResourcesPanel
:
1643 showFunctionName
= "showResourcesPanel";
1646 showFunctionName
= "showScriptsPanel";
1649 ASSERT_NOT_REACHED();
1650 showFunctionName
= 0;
1653 if (showFunctionName
)
1654 callSimpleFunction(m_scriptContext
, m_scriptObject
, showFunctionName
);
1657 void InspectorController::close()
1662 stopUserInitiatedProfiling();
1663 #if ENABLE(JAVASCRIPT_DEBUGGER)
1668 if (m_scriptContext
&& m_scriptObject
)
1669 JSValueUnprotect(m_scriptContext
, m_scriptObject
);
1672 m_scriptContext
= 0;
1675 void InspectorController::showWindow()
1678 m_client
->showWindow();
1681 void InspectorController::closeWindow()
1683 m_client
->closeWindow();
1686 void InspectorController::startUserInitiatedProfilingSoon()
1688 m_startProfiling
.startOneShot(0);
1691 void InspectorController::startUserInitiatedProfiling(Timer
<InspectorController
>*)
1696 if (!profilerEnabled()) {
1697 enableProfiler(true);
1698 JavaScriptDebugServer::shared().recompileAllJSFunctions();
1701 m_recordingUserInitiatedProfile
= true;
1702 m_currentUserInitiatedProfileNumber
= m_nextUserInitiatedProfileNumber
++;
1704 UString title
= UserInitiatedProfileName
;
1706 title
+= UString::from(m_currentUserInitiatedProfileNumber
);
1708 ExecState
* exec
= toJSDOMWindow(m_inspectedPage
->mainFrame())->globalExec();
1709 Profiler::profiler()->startProfiling(exec
, title
);
1711 toggleRecordButton(true);
1714 void InspectorController::stopUserInitiatedProfiling()
1719 m_recordingUserInitiatedProfile
= false;
1721 UString title
= UserInitiatedProfileName
;
1723 title
+= UString::from(m_currentUserInitiatedProfileNumber
);
1725 ExecState
* exec
= toJSDOMWindow(m_inspectedPage
->mainFrame())->globalExec();
1726 RefPtr
<Profile
> profile
= Profiler::profiler()->stopProfiling(exec
, title
);
1728 addProfile(profile
, 0, UString());
1730 toggleRecordButton(false);
1733 void InspectorController::enableProfiler(bool skipRecompile
)
1735 if (m_profilerEnabled
)
1738 m_profilerEnabled
= true;
1741 JavaScriptDebugServer::shared().recompileAllJSFunctionsSoon();
1743 if (m_scriptContext
&& m_scriptObject
)
1744 callSimpleFunction(m_scriptContext
, m_scriptObject
, "profilerWasEnabled");
1747 void InspectorController::disableProfiler()
1749 if (!m_profilerEnabled
)
1752 m_profilerEnabled
= false;
1754 JavaScriptDebugServer::shared().recompileAllJSFunctionsSoon();
1756 if (m_scriptContext
&& m_scriptObject
)
1757 callSimpleFunction(m_scriptContext
, m_scriptObject
, "profilerWasDisabled");
1760 static void addHeaders(JSContextRef context
, JSObjectRef object
, const HTTPHeaderMap
& headers
, JSValueRef
* exception
)
1762 ASSERT_ARG(context
, context
);
1763 ASSERT_ARG(object
, object
);
1765 HTTPHeaderMap::const_iterator end
= headers
.end();
1766 for (HTTPHeaderMap::const_iterator it
= headers
.begin(); it
!= end
; ++it
) {
1767 JSValueRef value
= JSValueMakeString(context
, jsStringRef(it
->second
).get());
1768 JSObjectSetProperty(context
, object
, jsStringRef(it
->first
).get(), value
, kJSPropertyAttributeNone
, exception
);
1769 if (exception
&& *exception
)
1774 static JSObjectRef
scriptObjectForRequest(JSContextRef context
, const InspectorResource
* resource
, JSValueRef
* exception
)
1776 ASSERT_ARG(context
, context
);
1778 JSObjectRef object
= JSObjectMake(context
, 0, 0);
1779 addHeaders(context
, object
, resource
->requestHeaderFields
, exception
);
1784 static JSObjectRef
scriptObjectForResponse(JSContextRef context
, const InspectorResource
* resource
, JSValueRef
* exception
)
1786 ASSERT_ARG(context
, context
);
1788 JSObjectRef object
= JSObjectMake(context
, 0, 0);
1789 addHeaders(context
, object
, resource
->responseHeaderFields
, exception
);
1794 JSObjectRef
InspectorController::addScriptResource(InspectorResource
* resource
)
1796 ASSERT_ARG(resource
, resource
);
1798 ASSERT(m_scriptContext
);
1799 ASSERT(m_scriptObject
);
1800 if (!m_scriptContext
|| !m_scriptObject
)
1803 if (!resource
->scriptObject
) {
1804 JSValueRef exception
= 0;
1806 JSValueRef resourceProperty
= JSObjectGetProperty(m_scriptContext
, m_scriptObject
, jsStringRef("Resource").get(), &exception
);
1807 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1810 JSObjectRef resourceConstructor
= JSValueToObject(m_scriptContext
, resourceProperty
, &exception
);
1811 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1814 JSValueRef urlValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->requestURL
.string()).get());
1815 JSValueRef domainValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->requestURL
.host()).get());
1816 JSValueRef pathValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->requestURL
.path()).get());
1817 JSValueRef lastPathComponentValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->requestURL
.lastPathComponent()).get());
1819 JSValueRef identifier
= JSValueMakeNumber(m_scriptContext
, resource
->identifier
);
1820 JSValueRef mainResource
= JSValueMakeBoolean(m_scriptContext
, m_mainResource
== resource
);
1821 JSValueRef cached
= JSValueMakeBoolean(m_scriptContext
, resource
->cached
);
1823 JSObjectRef scriptObject
= scriptObjectForRequest(m_scriptContext
, resource
, &exception
);
1824 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1827 JSValueRef arguments
[] = { scriptObject
, urlValue
, domainValue
, pathValue
, lastPathComponentValue
, identifier
, mainResource
, cached
};
1828 JSObjectRef result
= JSObjectCallAsConstructor(m_scriptContext
, resourceConstructor
, 8, arguments
, &exception
);
1829 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1834 resource
->setScriptObject(m_scriptContext
, result
);
1837 JSValueRef exception
= 0;
1838 callFunction(m_scriptContext
, m_scriptObject
, "addResource", 1, &resource
->scriptObject
, exception
);
1843 return resource
->scriptObject
;
1846 JSObjectRef
InspectorController::addAndUpdateScriptResource(InspectorResource
* resource
)
1848 ASSERT_ARG(resource
, resource
);
1850 JSObjectRef scriptResource
= addScriptResource(resource
);
1851 if (!scriptResource
)
1854 updateScriptResourceResponse(resource
);
1855 updateScriptResource(resource
, resource
->length
);
1856 updateScriptResource(resource
, resource
->startTime
, resource
->responseReceivedTime
, resource
->endTime
);
1857 updateScriptResource(resource
, resource
->finished
, resource
->failed
);
1858 return scriptResource
;
1861 void InspectorController::removeScriptResource(InspectorResource
* resource
)
1863 ASSERT(m_scriptContext
);
1864 ASSERT(m_scriptObject
);
1865 if (!m_scriptContext
|| !m_scriptObject
)
1869 ASSERT(resource
->scriptObject
);
1870 if (!resource
|| !resource
->scriptObject
)
1873 JSObjectRef scriptObject
= resource
->scriptObject
;
1874 resource
->setScriptObject(0, 0);
1876 JSValueRef exception
= 0;
1877 callFunction(m_scriptContext
, m_scriptObject
, "removeResource", 1, &scriptObject
, exception
);
1880 static void updateResourceRequest(InspectorResource
* resource
, const ResourceRequest
& request
)
1882 resource
->requestHeaderFields
= request
.httpHeaderFields();
1883 resource
->requestURL
= request
.url();
1886 static void updateResourceResponse(InspectorResource
* resource
, const ResourceResponse
& response
)
1888 resource
->expectedContentLength
= response
.expectedContentLength();
1889 resource
->mimeType
= response
.mimeType();
1890 resource
->responseHeaderFields
= response
.httpHeaderFields();
1891 resource
->responseStatusCode
= response
.httpStatusCode();
1892 resource
->suggestedFilename
= response
.suggestedFilename();
1895 void InspectorController::updateScriptResourceRequest(InspectorResource
* resource
)
1897 ASSERT(resource
->scriptObject
);
1898 ASSERT(m_scriptContext
);
1899 if (!resource
->scriptObject
|| !m_scriptContext
)
1902 JSValueRef urlValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->requestURL
.string()).get());
1903 JSValueRef domainValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->requestURL
.host()).get());
1904 JSValueRef pathValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->requestURL
.path()).get());
1905 JSValueRef lastPathComponentValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->requestURL
.lastPathComponent()).get());
1907 JSValueRef mainResourceValue
= JSValueMakeBoolean(m_scriptContext
, m_mainResource
== resource
);
1909 JSValueRef exception
= 0;
1911 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("url").get(), urlValue
, kJSPropertyAttributeNone
, &exception
);
1912 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1915 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("domain").get(), domainValue
, kJSPropertyAttributeNone
, &exception
);
1916 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1919 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("path").get(), pathValue
, kJSPropertyAttributeNone
, &exception
);
1920 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1923 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("lastPathComponent").get(), lastPathComponentValue
, kJSPropertyAttributeNone
, &exception
);
1924 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1927 JSObjectRef scriptObject
= scriptObjectForRequest(m_scriptContext
, resource
, &exception
);
1928 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1931 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("requestHeaders").get(), scriptObject
, kJSPropertyAttributeNone
, &exception
);
1932 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1935 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("mainResource").get(), mainResourceValue
, kJSPropertyAttributeNone
, &exception
);
1936 HANDLE_EXCEPTION(m_scriptContext
, exception
);
1939 void InspectorController::updateScriptResourceResponse(InspectorResource
* resource
)
1941 ASSERT(resource
->scriptObject
);
1942 ASSERT(m_scriptContext
);
1943 if (!resource
->scriptObject
|| !m_scriptContext
)
1946 JSValueRef mimeTypeValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->mimeType
).get());
1948 JSValueRef suggestedFilenameValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->suggestedFilename
).get());
1950 JSValueRef expectedContentLengthValue
= JSValueMakeNumber(m_scriptContext
, static_cast<double>(resource
->expectedContentLength
));
1951 JSValueRef statusCodeValue
= JSValueMakeNumber(m_scriptContext
, resource
->responseStatusCode
);
1953 JSValueRef exception
= 0;
1955 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("mimeType").get(), mimeTypeValue
, kJSPropertyAttributeNone
, &exception
);
1956 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1959 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("suggestedFilename").get(), suggestedFilenameValue
, kJSPropertyAttributeNone
, &exception
);
1960 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1963 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("expectedContentLength").get(), expectedContentLengthValue
, kJSPropertyAttributeNone
, &exception
);
1964 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1967 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("statusCode").get(), statusCodeValue
, kJSPropertyAttributeNone
, &exception
);
1968 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1971 JSObjectRef scriptObject
= scriptObjectForResponse(m_scriptContext
, resource
, &exception
);
1972 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1975 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("responseHeaders").get(), scriptObject
, kJSPropertyAttributeNone
, &exception
);
1976 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
1979 updateScriptResourceType(resource
);
1982 void InspectorController::updateScriptResourceType(InspectorResource
* resource
)
1984 ASSERT(resource
->scriptObject
);
1985 ASSERT(m_scriptContext
);
1986 if (!resource
->scriptObject
|| !m_scriptContext
)
1989 JSValueRef exception
= 0;
1991 JSValueRef typeValue
= JSValueMakeNumber(m_scriptContext
, resource
->type());
1992 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("type").get(), typeValue
, kJSPropertyAttributeNone
, &exception
);
1993 HANDLE_EXCEPTION(m_scriptContext
, exception
);
1996 void InspectorController::updateScriptResource(InspectorResource
* resource
, int length
)
1998 ASSERT(resource
->scriptObject
);
1999 ASSERT(m_scriptContext
);
2000 if (!resource
->scriptObject
|| !m_scriptContext
)
2003 JSValueRef lengthValue
= JSValueMakeNumber(m_scriptContext
, length
);
2005 JSValueRef exception
= 0;
2007 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("contentLength").get(), lengthValue
, kJSPropertyAttributeNone
, &exception
);
2008 HANDLE_EXCEPTION(m_scriptContext
, exception
);
2011 void InspectorController::updateScriptResource(InspectorResource
* resource
, bool finished
, bool failed
)
2013 ASSERT(resource
->scriptObject
);
2014 ASSERT(m_scriptContext
);
2015 if (!resource
->scriptObject
|| !m_scriptContext
)
2018 JSValueRef failedValue
= JSValueMakeBoolean(m_scriptContext
, failed
);
2019 JSValueRef finishedValue
= JSValueMakeBoolean(m_scriptContext
, finished
);
2021 JSValueRef exception
= 0;
2023 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("failed").get(), failedValue
, kJSPropertyAttributeNone
, &exception
);
2024 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2027 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("finished").get(), finishedValue
, kJSPropertyAttributeNone
, &exception
);
2028 HANDLE_EXCEPTION(m_scriptContext
, exception
);
2031 void InspectorController::updateScriptResource(InspectorResource
* resource
, double startTime
, double responseReceivedTime
, double endTime
)
2033 ASSERT(resource
->scriptObject
);
2034 ASSERT(m_scriptContext
);
2035 if (!resource
->scriptObject
|| !m_scriptContext
)
2038 JSValueRef startTimeValue
= JSValueMakeNumber(m_scriptContext
, startTime
);
2039 JSValueRef responseReceivedTimeValue
= JSValueMakeNumber(m_scriptContext
, responseReceivedTime
);
2040 JSValueRef endTimeValue
= JSValueMakeNumber(m_scriptContext
, endTime
);
2042 JSValueRef exception
= 0;
2044 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("startTime").get(), startTimeValue
, kJSPropertyAttributeNone
, &exception
);
2045 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2048 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("responseReceivedTime").get(), responseReceivedTimeValue
, kJSPropertyAttributeNone
, &exception
);
2049 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2052 JSObjectSetProperty(m_scriptContext
, resource
->scriptObject
, jsStringRef("endTime").get(), endTimeValue
, kJSPropertyAttributeNone
, &exception
);
2053 HANDLE_EXCEPTION(m_scriptContext
, exception
);
2056 void InspectorController::populateScriptObjects()
2058 ASSERT(m_scriptContext
);
2059 if (!m_scriptContext
)
2062 ResourcesMap::iterator resourcesEnd
= m_resources
.end();
2063 for (ResourcesMap::iterator it
= m_resources
.begin(); it
!= resourcesEnd
; ++it
)
2064 addAndUpdateScriptResource(it
->second
.get());
2066 unsigned messageCount
= m_consoleMessages
.size();
2067 for (unsigned i
= 0; i
< messageCount
; ++i
)
2068 addScriptConsoleMessage(m_consoleMessages
[i
]);
2070 #if ENABLE(DATABASE)
2071 DatabaseResourcesSet::iterator databasesEnd
= m_databaseResources
.end();
2072 for (DatabaseResourcesSet::iterator it
= m_databaseResources
.begin(); it
!= databasesEnd
; ++it
)
2073 addDatabaseScriptResource((*it
).get());
2076 callSimpleFunction(m_scriptContext
, m_scriptObject
, "populateInterface");
2079 #if ENABLE(DATABASE)
2080 JSObjectRef
InspectorController::addDatabaseScriptResource(InspectorDatabaseResource
* resource
)
2082 ASSERT_ARG(resource
, resource
);
2084 if (resource
->scriptObject
)
2085 return resource
->scriptObject
;
2087 ASSERT(m_scriptContext
);
2088 ASSERT(m_scriptObject
);
2089 if (!m_scriptContext
|| !m_scriptObject
)
2092 Frame
* frame
= resource
->database
->document()->frame();
2096 JSValueRef exception
= 0;
2098 JSValueRef databaseProperty
= JSObjectGetProperty(m_scriptContext
, m_scriptObject
, jsStringRef("Database").get(), &exception
);
2099 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2102 JSObjectRef databaseConstructor
= JSValueToObject(m_scriptContext
, databaseProperty
, &exception
);
2103 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2106 ExecState
* exec
= toJSDOMWindow(frame
)->globalExec();
2108 JSValueRef database
;
2111 JSC::JSLock
lock(false);
2112 database
= toRef(JSInspectedObjectWrapper::wrap(exec
, toJS(exec
, resource
->database
.get())));
2115 JSValueRef domainValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->domain
).get());
2116 JSValueRef nameValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->name
).get());
2117 JSValueRef versionValue
= JSValueMakeString(m_scriptContext
, jsStringRef(resource
->version
).get());
2119 JSValueRef arguments
[] = { database
, domainValue
, nameValue
, versionValue
};
2120 JSObjectRef result
= JSObjectCallAsConstructor(m_scriptContext
, databaseConstructor
, 4, arguments
, &exception
);
2121 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2126 callFunction(m_scriptContext
, m_scriptObject
, "addDatabase", 1, &result
, exception
);
2131 resource
->setScriptObject(m_scriptContext
, result
);
2136 void InspectorController::removeDatabaseScriptResource(InspectorDatabaseResource
* resource
)
2138 ASSERT(m_scriptContext
);
2139 ASSERT(m_scriptObject
);
2140 if (!m_scriptContext
|| !m_scriptObject
)
2144 ASSERT(resource
->scriptObject
);
2145 if (!resource
|| !resource
->scriptObject
)
2148 JSObjectRef scriptObject
= resource
->scriptObject
;
2149 resource
->setScriptObject(0, 0);
2151 JSValueRef exception
= 0;
2152 callFunction(m_scriptContext
, m_scriptObject
, "removeDatabase", 1, &scriptObject
, exception
);
2156 void InspectorController::addScriptConsoleMessage(const ConsoleMessage
* message
)
2158 ASSERT_ARG(message
, message
);
2160 JSValueRef exception
= 0;
2162 JSValueRef messageConstructorProperty
= JSObjectGetProperty(m_scriptContext
, m_scriptObject
, jsStringRef("ConsoleMessage").get(), &exception
);
2163 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2166 JSObjectRef messageConstructor
= JSValueToObject(m_scriptContext
, messageConstructorProperty
, &exception
);
2167 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2170 JSValueRef sourceValue
= JSValueMakeNumber(m_scriptContext
, message
->source
);
2171 JSValueRef levelValue
= JSValueMakeNumber(m_scriptContext
, message
->level
);
2172 JSValueRef lineValue
= JSValueMakeNumber(m_scriptContext
, message
->line
);
2173 JSValueRef urlValue
= JSValueMakeString(m_scriptContext
, jsStringRef(message
->url
).get());
2174 JSValueRef groupLevelValue
= JSValueMakeNumber(m_scriptContext
, message
->groupLevel
);
2175 JSValueRef repeatCountValue
= JSValueMakeNumber(m_scriptContext
, message
->repeatCount
);
2177 static const unsigned maximumMessageArguments
= 256;
2178 JSValueRef arguments
[maximumMessageArguments
];
2179 unsigned argumentCount
= 0;
2180 arguments
[argumentCount
++] = sourceValue
;
2181 arguments
[argumentCount
++] = levelValue
;
2182 arguments
[argumentCount
++] = lineValue
;
2183 arguments
[argumentCount
++] = urlValue
;
2184 arguments
[argumentCount
++] = groupLevelValue
;
2185 arguments
[argumentCount
++] = repeatCountValue
;
2187 if (!message
->wrappedArguments
.isEmpty()) {
2188 unsigned remainingSpaceInArguments
= maximumMessageArguments
- argumentCount
;
2189 unsigned argumentsToAdd
= min(remainingSpaceInArguments
, static_cast<unsigned>(message
->wrappedArguments
.size()));
2190 for (unsigned i
= 0; i
< argumentsToAdd
; ++i
)
2191 arguments
[argumentCount
++] = toRef(message
->wrappedArguments
[i
]);
2193 JSValueRef messageValue
= JSValueMakeString(m_scriptContext
, jsStringRef(message
->message
).get());
2194 arguments
[argumentCount
++] = messageValue
;
2197 JSObjectRef messageObject
= JSObjectCallAsConstructor(m_scriptContext
, messageConstructor
, argumentCount
, arguments
, &exception
);
2198 if (HANDLE_EXCEPTION(m_scriptContext
, exception
))
2201 callFunction(m_scriptContext
, m_scriptObject
, "addMessageToConsole", 1, &messageObject
, exception
);
2204 void InspectorController::addScriptProfile(Profile
* profile
)
2207 JSValueRef exception
= 0;
2208 JSValueRef profileObject
= toRef(toJS(toJS(m_scriptContext
), profile
));
2209 callFunction(m_scriptContext
, m_scriptObject
, "addProfile", 1, &profileObject
, exception
);
2212 void InspectorController::resetScriptObjects()
2214 if (!m_scriptContext
|| !m_scriptObject
)
2217 ResourcesMap::iterator resourcesEnd
= m_resources
.end();
2218 for (ResourcesMap::iterator it
= m_resources
.begin(); it
!= resourcesEnd
; ++it
) {
2219 InspectorResource
* resource
= it
->second
.get();
2220 resource
->setScriptObject(0, 0);
2223 #if ENABLE(DATABASE)
2224 DatabaseResourcesSet::iterator databasesEnd
= m_databaseResources
.end();
2225 for (DatabaseResourcesSet::iterator it
= m_databaseResources
.begin(); it
!= databasesEnd
; ++it
) {
2226 InspectorDatabaseResource
* resource
= (*it
).get();
2227 resource
->setScriptObject(0, 0);
2231 callSimpleFunction(m_scriptContext
, m_scriptObject
, "reset");
2234 void InspectorController::pruneResources(ResourcesMap
* resourceMap
, DocumentLoader
* loaderToKeep
)
2236 ASSERT_ARG(resourceMap
, resourceMap
);
2238 ResourcesMap
mapCopy(*resourceMap
);
2239 ResourcesMap::iterator end
= mapCopy
.end();
2240 for (ResourcesMap::iterator it
= mapCopy
.begin(); it
!= end
; ++it
) {
2241 InspectorResource
* resource
= (*it
).second
.get();
2242 if (resource
== m_mainResource
)
2245 if (!loaderToKeep
|| resource
->loader
!= loaderToKeep
) {
2246 removeResource(resource
);
2247 if (windowVisible() && resource
->scriptObject
)
2248 removeScriptResource(resource
);
2253 void InspectorController::didCommitLoad(DocumentLoader
* loader
)
2258 ASSERT(m_inspectedPage
);
2260 if (loader
->frame() == m_inspectedPage
->mainFrame()) {
2261 m_client
->inspectedURLChanged(loader
->url().string());
2263 clearConsoleMessages();
2269 #if ENABLE(DATABASE)
2270 m_databaseResources
.clear();
2273 if (windowVisible()) {
2274 resetScriptObjects();
2276 if (!loader
->isLoadingFromCachedPage()) {
2277 ASSERT(m_mainResource
&& m_mainResource
->loader
== loader
);
2278 // We don't add the main resource until its load is committed. This is
2279 // needed to keep the load for a user-entered URL from showing up in the
2280 // list of resources for the page they are navigating away from.
2281 addAndUpdateScriptResource(m_mainResource
.get());
2283 // Pages loaded from the page cache are committed before
2284 // m_mainResource is the right resource for this load, so we
2285 // clear it here. It will be re-assigned in
2286 // identifierForInitialRequest.
2292 for (Frame
* frame
= loader
->frame(); frame
; frame
= frame
->tree()->traverseNext(loader
->frame()))
2293 if (ResourcesMap
* resourceMap
= m_frameResources
.get(frame
))
2294 pruneResources(resourceMap
, loader
);
2297 void InspectorController::frameDetachedFromParent(Frame
* frame
)
2301 if (ResourcesMap
* resourceMap
= m_frameResources
.get(frame
))
2302 removeAllResources(resourceMap
);
2305 void InspectorController::addResource(InspectorResource
* resource
)
2307 m_resources
.set(resource
->identifier
, resource
);
2308 m_knownResources
.add(resource
->requestURL
.string());
2310 Frame
* frame
= resource
->frame
.get();
2311 ResourcesMap
* resourceMap
= m_frameResources
.get(frame
);
2313 resourceMap
->set(resource
->identifier
, resource
);
2315 resourceMap
= new ResourcesMap
;
2316 resourceMap
->set(resource
->identifier
, resource
);
2317 m_frameResources
.set(frame
, resourceMap
);
2321 void InspectorController::removeResource(InspectorResource
* resource
)
2323 m_resources
.remove(resource
->identifier
);
2324 m_knownResources
.remove(resource
->requestURL
.string());
2326 Frame
* frame
= resource
->frame
.get();
2327 ResourcesMap
* resourceMap
= m_frameResources
.get(frame
);
2329 ASSERT_NOT_REACHED();
2333 resourceMap
->remove(resource
->identifier
);
2334 if (resourceMap
->isEmpty()) {
2335 m_frameResources
.remove(frame
);
2340 void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader
* loader
, const ResourceRequest
& request
, const ResourceResponse
& response
, int length
)
2345 // If the resource URL is already known, we don't need to add it again since this is just a cached load.
2346 if (m_knownResources
.contains(request
.url().string()))
2349 RefPtr
<InspectorResource
> resource
= InspectorResource::create(m_nextIdentifier
--, loader
, loader
->frame());
2350 resource
->finished
= true;
2352 updateResourceRequest(resource
.get(), request
);
2353 updateResourceResponse(resource
.get(), response
);
2355 resource
->length
= length
;
2356 resource
->cached
= true;
2357 resource
->startTime
= currentTime();
2358 resource
->responseReceivedTime
= resource
->startTime
;
2359 resource
->endTime
= resource
->startTime
;
2361 ASSERT(m_inspectedPage
);
2363 if (loader
->frame() == m_inspectedPage
->mainFrame() && request
.url() == loader
->requestURL())
2364 m_mainResource
= resource
;
2366 addResource(resource
.get());
2368 if (windowVisible())
2369 addAndUpdateScriptResource(resource
.get());
2372 void InspectorController::identifierForInitialRequest(unsigned long identifier
, DocumentLoader
* loader
, const ResourceRequest
& request
)
2377 RefPtr
<InspectorResource
> resource
= InspectorResource::create(identifier
, loader
, loader
->frame());
2379 updateResourceRequest(resource
.get(), request
);
2381 ASSERT(m_inspectedPage
);
2383 if (loader
->frame() == m_inspectedPage
->mainFrame() && request
.url() == loader
->requestURL())
2384 m_mainResource
= resource
;
2386 addResource(resource
.get());
2388 if (windowVisible() && loader
->isLoadingFromCachedPage() && resource
== m_mainResource
)
2389 addAndUpdateScriptResource(resource
.get());
2392 void InspectorController::willSendRequest(DocumentLoader
* loader
, unsigned long identifier
, ResourceRequest
& request
, const ResourceResponse
& redirectResponse
)
2397 InspectorResource
* resource
= m_resources
.get(identifier
).get();
2401 resource
->startTime
= currentTime();
2403 if (!redirectResponse
.isNull()) {
2404 updateResourceRequest(resource
, request
);
2405 updateResourceResponse(resource
, redirectResponse
);
2408 if (resource
!= m_mainResource
&& windowVisible()) {
2409 if (!resource
->scriptObject
)
2410 addScriptResource(resource
);
2412 updateScriptResourceRequest(resource
);
2414 updateScriptResource(resource
, resource
->startTime
, resource
->responseReceivedTime
, resource
->endTime
);
2416 if (!redirectResponse
.isNull())
2417 updateScriptResourceResponse(resource
);
2421 void InspectorController::didReceiveResponse(DocumentLoader
*, unsigned long identifier
, const ResourceResponse
& response
)
2426 InspectorResource
* resource
= m_resources
.get(identifier
).get();
2430 updateResourceResponse(resource
, response
);
2432 resource
->responseReceivedTime
= currentTime();
2434 if (windowVisible() && resource
->scriptObject
) {
2435 updateScriptResourceResponse(resource
);
2436 updateScriptResource(resource
, resource
->startTime
, resource
->responseReceivedTime
, resource
->endTime
);
2440 void InspectorController::didReceiveContentLength(DocumentLoader
*, unsigned long identifier
, int lengthReceived
)
2445 InspectorResource
* resource
= m_resources
.get(identifier
).get();
2449 resource
->length
+= lengthReceived
;
2451 if (windowVisible() && resource
->scriptObject
)
2452 updateScriptResource(resource
, resource
->length
);
2455 void InspectorController::didFinishLoading(DocumentLoader
* loader
, unsigned long identifier
)
2460 RefPtr
<InspectorResource
> resource
= m_resources
.get(identifier
);
2464 removeResource(resource
.get());
2466 resource
->finished
= true;
2467 resource
->endTime
= currentTime();
2469 addResource(resource
.get());
2471 if (windowVisible() && resource
->scriptObject
) {
2472 updateScriptResource(resource
.get(), resource
->startTime
, resource
->responseReceivedTime
, resource
->endTime
);
2473 updateScriptResource(resource
.get(), resource
->finished
);
2477 void InspectorController::didFailLoading(DocumentLoader
* loader
, unsigned long identifier
, const ResourceError
& /*error*/)
2482 RefPtr
<InspectorResource
> resource
= m_resources
.get(identifier
);
2486 removeResource(resource
.get());
2488 resource
->finished
= true;
2489 resource
->failed
= true;
2490 resource
->endTime
= currentTime();
2492 addResource(resource
.get());
2494 if (windowVisible() && resource
->scriptObject
) {
2495 updateScriptResource(resource
.get(), resource
->startTime
, resource
->responseReceivedTime
, resource
->endTime
);
2496 updateScriptResource(resource
.get(), resource
->finished
, resource
->failed
);
2500 void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier
, JSC::UString
& sourceString
)
2505 InspectorResource
* resource
= m_resources
.get(identifier
).get();
2509 resource
->setXMLHttpRequestProperties(sourceString
);
2511 if (windowVisible() && resource
->scriptObject
)
2512 updateScriptResourceType(resource
);
2516 #if ENABLE(DATABASE)
2517 void InspectorController::didOpenDatabase(Database
* database
, const String
& domain
, const String
& name
, const String
& version
)
2522 RefPtr
<InspectorDatabaseResource
> resource
= InspectorDatabaseResource::create(database
, domain
, name
, version
);
2524 m_databaseResources
.add(resource
);
2526 if (windowVisible())
2527 addDatabaseScriptResource(resource
.get());
2531 void InspectorController::moveWindowBy(float x
, float y
) const
2533 if (!m_page
|| !enabled())
2536 FloatRect frameRect
= m_page
->chrome()->windowRect();
2537 frameRect
.move(x
, y
);
2538 m_page
->chrome()->setWindowRect(frameRect
);
2541 #if ENABLE(JAVASCRIPT_DEBUGGER)
2542 void InspectorController::enableDebugger()
2547 if (!m_scriptContext
|| !m_scriptObject
) {
2548 m_attachDebuggerWhenShown
= true;
2552 ASSERT(m_inspectedPage
);
2554 JavaScriptDebugServer::shared().addListener(this, m_inspectedPage
);
2555 JavaScriptDebugServer::shared().clearBreakpoints();
2557 m_debuggerEnabled
= true;
2558 m_attachDebuggerWhenShown
= false;
2560 callSimpleFunction(m_scriptContext
, m_scriptObject
, "debuggerWasEnabled");
2563 void InspectorController::disableDebugger()
2568 ASSERT(m_inspectedPage
);
2570 JavaScriptDebugServer::shared().removeListener(this, m_inspectedPage
);
2572 m_debuggerEnabled
= false;
2573 m_attachDebuggerWhenShown
= false;
2575 if (m_scriptContext
&& m_scriptObject
)
2576 callSimpleFunction(m_scriptContext
, m_scriptObject
, "debuggerWasDisabled");
2579 JavaScriptCallFrame
* InspectorController::currentCallFrame() const
2581 return JavaScriptDebugServer::shared().currentCallFrame();
2584 bool InspectorController::pauseOnExceptions()
2586 return JavaScriptDebugServer::shared().pauseOnExceptions();
2589 void InspectorController::setPauseOnExceptions(bool pause
)
2591 JavaScriptDebugServer::shared().setPauseOnExceptions(pause
);
2594 void InspectorController::pauseInDebugger()
2596 if (!m_debuggerEnabled
)
2598 JavaScriptDebugServer::shared().pauseProgram();
2601 void InspectorController::resumeDebugger()
2603 if (!m_debuggerEnabled
)
2605 JavaScriptDebugServer::shared().continueProgram();
2608 void InspectorController::stepOverStatementInDebugger()
2610 if (!m_debuggerEnabled
)
2612 JavaScriptDebugServer::shared().stepOverStatement();
2615 void InspectorController::stepIntoStatementInDebugger()
2617 if (!m_debuggerEnabled
)
2619 JavaScriptDebugServer::shared().stepIntoStatement();
2622 void InspectorController::stepOutOfFunctionInDebugger()
2624 if (!m_debuggerEnabled
)
2626 JavaScriptDebugServer::shared().stepOutOfFunction();
2629 void InspectorController::addBreakpoint(intptr_t sourceID
, unsigned lineNumber
)
2631 JavaScriptDebugServer::shared().addBreakpoint(sourceID
, lineNumber
);
2634 void InspectorController::removeBreakpoint(intptr_t sourceID
, unsigned lineNumber
)
2636 JavaScriptDebugServer::shared().removeBreakpoint(sourceID
, lineNumber
);
2640 static void drawOutlinedRect(GraphicsContext
& context
, const IntRect
& rect
, const Color
& fillColor
)
2642 static const int outlineThickness
= 1;
2643 static const Color
outlineColor(62, 86, 180, 228);
2645 IntRect outline
= rect
;
2646 outline
.inflate(outlineThickness
);
2648 context
.clearRect(outline
);
2651 context
.clipOut(rect
);
2652 context
.fillRect(outline
, outlineColor
);
2655 context
.fillRect(rect
, fillColor
);
2658 static void drawHighlightForBoxes(GraphicsContext
& context
, const Vector
<IntRect
>& lineBoxRects
, const IntRect
& contentBox
, const IntRect
& paddingBox
, const IntRect
& borderBox
, const IntRect
& marginBox
)
2660 static const Color
contentBoxColor(125, 173, 217, 128);
2661 static const Color
paddingBoxColor(125, 173, 217, 160);
2662 static const Color
borderBoxColor(125, 173, 217, 192);
2663 static const Color
marginBoxColor(125, 173, 217, 228);
2665 if (!lineBoxRects
.isEmpty()) {
2666 for (size_t i
= 0; i
< lineBoxRects
.size(); ++i
)
2667 drawOutlinedRect(context
, lineBoxRects
[i
], contentBoxColor
);
2671 if (marginBox
!= borderBox
)
2672 drawOutlinedRect(context
, marginBox
, marginBoxColor
);
2673 if (borderBox
!= paddingBox
)
2674 drawOutlinedRect(context
, borderBox
, borderBoxColor
);
2675 if (paddingBox
!= contentBox
)
2676 drawOutlinedRect(context
, paddingBox
, paddingBoxColor
);
2677 drawOutlinedRect(context
, contentBox
, contentBoxColor
);
2680 static inline void convertFromFrameToMainFrame(Frame
* frame
, IntRect
& rect
)
2682 rect
= frame
->page()->mainFrame()->view()->windowToContents(frame
->view()->contentsToWindow(rect
));
2685 void InspectorController::drawNodeHighlight(GraphicsContext
& context
) const
2687 if (!m_highlightedNode
)
2690 RenderObject
* renderer
= m_highlightedNode
->renderer();
2691 Frame
* containingFrame
= m_highlightedNode
->document()->frame();
2692 if (!renderer
|| !containingFrame
)
2695 IntRect contentBox
= renderer
->absoluteContentBox();
2696 IntRect boundingBox
= renderer
->absoluteBoundingBoxRect();
2698 // FIXME: Should we add methods to RenderObject to obtain these rects?
2699 IntRect
paddingBox(contentBox
.x() - renderer
->paddingLeft(), contentBox
.y() - renderer
->paddingTop(), contentBox
.width() + renderer
->paddingLeft() + renderer
->paddingRight(), contentBox
.height() + renderer
->paddingTop() + renderer
->paddingBottom());
2700 IntRect
borderBox(paddingBox
.x() - renderer
->borderLeft(), paddingBox
.y() - renderer
->borderTop(), paddingBox
.width() + renderer
->borderLeft() + renderer
->borderRight(), paddingBox
.height() + renderer
->borderTop() + renderer
->borderBottom());
2701 IntRect
marginBox(borderBox
.x() - renderer
->marginLeft(), borderBox
.y() - renderer
->marginTop(), borderBox
.width() + renderer
->marginLeft() + renderer
->marginRight(), borderBox
.height() + renderer
->marginTop() + renderer
->marginBottom());
2703 convertFromFrameToMainFrame(containingFrame
, contentBox
);
2704 convertFromFrameToMainFrame(containingFrame
, paddingBox
);
2705 convertFromFrameToMainFrame(containingFrame
, borderBox
);
2706 convertFromFrameToMainFrame(containingFrame
, marginBox
);
2707 convertFromFrameToMainFrame(containingFrame
, boundingBox
);
2709 Vector
<IntRect
> lineBoxRects
;
2710 if (renderer
->isInline() || (renderer
->isText() && !m_highlightedNode
->isSVGElement())) {
2711 // FIXME: We should show margins/padding/border for inlines.
2712 renderer
->addLineBoxRects(lineBoxRects
);
2715 for (unsigned i
= 0; i
< lineBoxRects
.size(); ++i
)
2716 convertFromFrameToMainFrame(containingFrame
, lineBoxRects
[i
]);
2718 if (lineBoxRects
.isEmpty() && contentBox
.isEmpty()) {
2719 // If we have no line boxes and our content box is empty, we'll just draw our bounding box.
2720 // This can happen, e.g., with an <a> enclosing an <img style="float:right">.
2721 // FIXME: Can we make this better/more accurate? The <a> in the above case has no
2722 // width/height but the highlight makes it appear to be the size of the <img>.
2723 lineBoxRects
.append(boundingBox
);
2726 ASSERT(m_inspectedPage
);
2728 FrameView
* view
= m_inspectedPage
->mainFrame()->view();
2729 FloatRect overlayRect
= view
->visibleContentRect();
2731 if (!overlayRect
.contains(boundingBox
) && !boundingBox
.contains(enclosingIntRect(overlayRect
))) {
2733 if (m_highlightedNode
->isElementNode())
2734 element
= static_cast<Element
*>(m_highlightedNode
.get());
2736 element
= static_cast<Element
*>(m_highlightedNode
->parent());
2737 overlayRect
= view
->visibleContentRect();
2740 context
.translate(-overlayRect
.x(), -overlayRect
.y());
2742 drawHighlightForBoxes(context
, lineBoxRects
, contentBox
, paddingBox
, borderBox
, marginBox
);
2745 void InspectorController::count(const UString
& title
, unsigned lineNumber
, const String
& sourceID
)
2747 String identifier
= String(title
) + String::format("@%s:%d", sourceID
.utf8().data(), lineNumber
);
2748 HashMap
<String
, unsigned>::iterator it
= m_counts
.find(identifier
);
2750 if (it
== m_counts
.end())
2753 count
= it
->second
+ 1;
2754 m_counts
.remove(it
);
2757 m_counts
.add(identifier
, count
);
2759 String message
= String::format("%s: %d", title
.UTF8String().c_str(), count
);
2760 addMessageToConsole(JSMessageSource
, LogMessageLevel
, message
, lineNumber
, sourceID
);
2763 void InspectorController::startTiming(const UString
& title
)
2765 m_times
.add(title
, currentTime() * 1000);
2768 bool InspectorController::stopTiming(const UString
& title
, double& elapsed
)
2770 HashMap
<String
, double>::iterator it
= m_times
.find(title
);
2771 if (it
== m_times
.end())
2774 double startTime
= it
->second
;
2777 elapsed
= currentTime() * 1000 - startTime
;
2781 bool InspectorController::handleException(JSContextRef context
, JSValueRef exception
, unsigned lineNumber
) const
2789 String message
= toString(context
, exception
, 0);
2790 String
file(__FILE__
);
2792 if (JSObjectRef exceptionObject
= JSValueToObject(context
, exception
, 0)) {
2793 JSValueRef lineValue
= JSObjectGetProperty(context
, exceptionObject
, jsStringRef("line").get(), NULL
);
2795 lineNumber
= static_cast<unsigned>(JSValueToNumber(context
, lineValue
, 0));
2797 JSValueRef fileValue
= JSObjectGetProperty(context
, exceptionObject
, jsStringRef("sourceURL").get(), NULL
);
2799 file
= toString(context
, fileValue
, 0);
2802 m_page
->mainFrame()->domWindow()->console()->addMessage(JSMessageSource
, ErrorMessageLevel
, message
, lineNumber
, file
);
2806 #if ENABLE(JAVASCRIPT_DEBUGGER)
2807 // JavaScriptDebugListener functions
2809 void InspectorController::didParseSource(ExecState
* exec
, const SourceCode
& source
)
2811 JSValueRef sourceIDValue
= JSValueMakeNumber(m_scriptContext
, source
.provider()->asID());
2812 JSValueRef sourceURLValue
= JSValueMakeString(m_scriptContext
, jsStringRef(source
.provider()->url()).get());
2813 JSValueRef sourceValue
= JSValueMakeString(m_scriptContext
, jsStringRef(source
).get());
2814 JSValueRef firstLineValue
= JSValueMakeNumber(m_scriptContext
, source
.firstLine());
2816 JSValueRef exception
= 0;
2817 JSValueRef arguments
[] = { sourceIDValue
, sourceURLValue
, sourceValue
, firstLineValue
};
2818 callFunction(m_scriptContext
, m_scriptObject
, "parsedScriptSource", 4, arguments
, exception
);
2821 void InspectorController::failedToParseSource(ExecState
* exec
, const SourceCode
& source
, int errorLine
, const UString
& errorMessage
)
2823 JSValueRef sourceURLValue
= JSValueMakeString(m_scriptContext
, jsStringRef(source
.provider()->url()).get());
2824 JSValueRef sourceValue
= JSValueMakeString(m_scriptContext
, jsStringRef(source
.data()).get());
2825 JSValueRef firstLineValue
= JSValueMakeNumber(m_scriptContext
, source
.firstLine());
2826 JSValueRef errorLineValue
= JSValueMakeNumber(m_scriptContext
, errorLine
);
2827 JSValueRef errorMessageValue
= JSValueMakeString(m_scriptContext
, jsStringRef(errorMessage
).get());
2829 JSValueRef exception
= 0;
2830 JSValueRef arguments
[] = { sourceURLValue
, sourceValue
, firstLineValue
, errorLineValue
, errorMessageValue
};
2831 callFunction(m_scriptContext
, m_scriptObject
, "failedToParseScriptSource", 5, arguments
, exception
);
2834 void InspectorController::didPause()
2836 JSValueRef exception
= 0;
2837 callFunction(m_scriptContext
, m_scriptObject
, "pausedScript", 0, 0, exception
);
2841 } // namespace WebCore