webengine/osswebengine/WebCore/page/InspectorController.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     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 "DocLoader.h"
       
    35 #include "Document.h"
       
    36 #include "DocumentLoader.h"
       
    37 #include "Element.h"
       
    38 #include "FloatRect.h"
       
    39 #include "Frame.h"
       
    40 #include "FrameLoader.h"
       
    41 #include "FrameTree.h"
       
    42 #include "HTMLFrameOwnerElement.h"
       
    43 #include "InspectorClient.h"
       
    44 #include "JSRange.h"
       
    45 #include "Page.h"
       
    46 #include "Range.h"
       
    47 #include "ResourceRequest.h"
       
    48 #include "ResourceResponse.h"
       
    49 #include "Settings.h"
       
    50 #include "Shared.h"
       
    51 #include "SharedBuffer.h"
       
    52 #include "SystemTime.h"
       
    53 #include "TextEncoding.h"
       
    54 #include "TextIterator.h"
       
    55 #include "kjs_dom.h"
       
    56 #include "kjs_proxy.h"
       
    57 #include "kjs_window.h"
       
    58 #include <JavaScriptCore/APICast.h>
       
    59 #include <JavaScriptCore/JSLock.h>
       
    60 #include <JavaScriptCore/JSStringRef.h>
       
    61 
       
    62 namespace WebCore {
       
    63 
       
    64 struct ConsoleMessage {
       
    65     ConsoleMessage(MessageSource s, MessageLevel l, const String& m, unsigned li, const String& u)
       
    66         : source(s)
       
    67         , level(l)
       
    68         , message(m)
       
    69         , line(li)
       
    70         , url(u)
       
    71     {
       
    72     }
       
    73 
       
    74     MessageSource source;
       
    75     MessageLevel level;
       
    76     String message;
       
    77     unsigned line;
       
    78     String url;
       
    79 };
       
    80 
       
    81 struct InspectorResource : public Shared<InspectorResource> {
       
    82     // Keep these in sync with WebInspector.Resource.Type
       
    83     enum Type {
       
    84         Doc,
       
    85         Stylesheet,
       
    86         Image,
       
    87         Script,
       
    88         Other
       
    89     };
       
    90 
       
    91     InspectorResource(long long identifier, DocumentLoader* documentLoader, Frame* frame)
       
    92         : identifier(identifier)
       
    93         , loader(documentLoader)
       
    94         , frame(frame)
       
    95         , scriptContext(0)
       
    96         , scriptObject(0)
       
    97         , expectedContentLength(0)
       
    98         , cached(false)
       
    99         , finished(false)
       
   100         , failed(false)
       
   101         , length(0)
       
   102         , responseStatusCode(0)
       
   103         , startTime(-1.0)
       
   104         , responseReceivedTime(-1.0)
       
   105         , endTime(-1.0)
       
   106     {
       
   107     }
       
   108 
       
   109     ~InspectorResource()
       
   110     {
       
   111         setScriptObject(0, 0);
       
   112     }
       
   113 
       
   114     Type type() const
       
   115     {
       
   116         if (requestURL == loader->requestURL())
       
   117             return Doc;
       
   118 
       
   119         FrameLoader* frameLoader = loader->frameLoader();
       
   120         if (!frameLoader)
       
   121             return Other;
       
   122 
       
   123         if (requestURL == frameLoader->iconURL())
       
   124             return Image;
       
   125 
       
   126         Document* doc = frameLoader->frame()->document();
       
   127         if (!doc)
       
   128             return Other;
       
   129 
       
   130         CachedResource* cachedResource = doc->docLoader()->cachedResource(requestURL.url());
       
   131         if (!cachedResource)
       
   132             return Other;
       
   133 
       
   134         switch (cachedResource->type()) {
       
   135             case CachedResource::ImageResource:
       
   136                 return Image;
       
   137             case CachedResource::CSSStyleSheet:
       
   138 #if ENABLE(XSLT)
       
   139             case CachedResource::XSLStyleSheet:
       
   140 #endif
       
   141                 return Stylesheet;
       
   142             case CachedResource::Script:
       
   143                 return Script;
       
   144             default:
       
   145                 return Other;
       
   146         }
       
   147     }
       
   148 
       
   149     void setScriptObject(JSContextRef context, JSObjectRef newScriptObject)
       
   150     {
       
   151         if (scriptContext && scriptObject)
       
   152             JSValueUnprotect(scriptContext, scriptObject);
       
   153 
       
   154         scriptObject = newScriptObject;
       
   155         scriptContext = context;
       
   156 
       
   157         ASSERT((context && newScriptObject) || (!context && !newScriptObject));
       
   158         if (context && newScriptObject)
       
   159             JSValueProtect(context, newScriptObject);
       
   160     }
       
   161 
       
   162     long long identifier;
       
   163     RefPtr<DocumentLoader> loader;
       
   164     RefPtr<Frame> frame;
       
   165     KURL requestURL;
       
   166     HTTPHeaderMap requestHeaderFields;
       
   167     HTTPHeaderMap responseHeaderFields;
       
   168     String mimeType;
       
   169     String suggestedFilename;
       
   170     String textEncodingName;
       
   171     JSContextRef scriptContext;
       
   172     JSObjectRef scriptObject;
       
   173     long long expectedContentLength;
       
   174     bool cached;
       
   175     bool finished;
       
   176     bool failed;
       
   177     int length;
       
   178     int responseStatusCode;
       
   179     double startTime;
       
   180     double responseReceivedTime;
       
   181     double endTime;
       
   182 };
       
   183 
       
   184 static JSValueRef addSourceToFrame(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
       
   185 {
       
   186     JSValueRef undefined = JSValueMakeUndefined(ctx);
       
   187 
       
   188     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   189     if (argumentCount < 2 || !controller)
       
   190         return undefined;
       
   191 
       
   192     JSValueRef identifierValue = arguments[0];
       
   193     if (!JSValueIsNumber(ctx, identifierValue))
       
   194         return undefined;
       
   195 
       
   196     unsigned long identifier = static_cast<unsigned long>(JSValueToNumber(ctx, identifierValue, 0));
       
   197     RefPtr<InspectorResource> resource = controller->resources().get(identifier);
       
   198     ASSERT(resource);
       
   199     if (!resource)
       
   200         return undefined;
       
   201 
       
   202     RefPtr<SharedBuffer> buffer;
       
   203     if (resource->requestURL == resource->loader->requestURL())
       
   204         buffer = resource->loader->mainResourceData();
       
   205     else {
       
   206         FrameLoader* frameLoader = resource->loader->frameLoader();
       
   207         if (!frameLoader)
       
   208             return undefined;
       
   209 
       
   210         Document* doc = frameLoader->frame()->document();
       
   211         if (!doc)
       
   212             return undefined;
       
   213 
       
   214         CachedResource* cachedResource = doc->docLoader()->cachedResource(resource->requestURL.url());
       
   215         if (!cachedResource)
       
   216             return undefined;
       
   217 
       
   218         buffer = cachedResource->data();
       
   219     }
       
   220 
       
   221     if (!buffer)
       
   222         return undefined;
       
   223 
       
   224     String textEncodingName = resource->loader->overrideEncoding();
       
   225     if (!textEncodingName)
       
   226         textEncodingName = resource->textEncodingName;
       
   227 
       
   228     TextEncoding encoding(textEncodingName);
       
   229     if (!encoding.isValid())
       
   230         encoding = WindowsLatin1Encoding();
       
   231     String sourceString = encoding.decode(buffer->data(), buffer->size());
       
   232 
       
   233     Node* node = toNode(toJS(arguments[1]));
       
   234     ASSERT(node);
       
   235     if (!node)
       
   236         return undefined;
       
   237 
       
   238     if (!node->attached()) {
       
   239         ASSERT_NOT_REACHED();
       
   240         return undefined;
       
   241     }
       
   242 
       
   243     ASSERT(node->isElementNode());
       
   244     if (!node->isElementNode())
       
   245         return undefined;
       
   246 
       
   247     Element* element = static_cast<Element*>(node);
       
   248     ASSERT(element->isFrameOwnerElement());
       
   249     if (!element->isFrameOwnerElement())
       
   250         return undefined;
       
   251 
       
   252     HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element);
       
   253     ASSERT(frameOwner->contentFrame());
       
   254     if (!frameOwner->contentFrame())
       
   255         return undefined;
       
   256 
       
   257     FrameLoader* loader = frameOwner->contentFrame()->loader();
       
   258 
       
   259     loader->setResponseMIMEType(resource->mimeType);
       
   260     loader->begin();
       
   261     loader->write(sourceString);
       
   262     loader->end();
       
   263 
       
   264     return undefined;
       
   265 }
       
   266 
       
   267 static JSValueRef getResourceDocumentNode(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
       
   268 {
       
   269     JSValueRef undefined = JSValueMakeUndefined(ctx);
       
   270 
       
   271     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   272     if (!argumentCount || argumentCount > 1 || !controller)
       
   273         return undefined;
       
   274 
       
   275     JSValueRef identifierValue = arguments[0];
       
   276     if (!JSValueIsNumber(ctx, identifierValue))
       
   277         return undefined;
       
   278 
       
   279     unsigned long identifier = static_cast<unsigned long>(JSValueToNumber(ctx, identifierValue, 0));
       
   280     RefPtr<InspectorResource> resource = controller->resources().get(identifier);
       
   281     ASSERT(resource);
       
   282     if (!resource)
       
   283         return undefined;
       
   284 
       
   285     FrameLoader* frameLoader = resource->loader->frameLoader();
       
   286     if (!frameLoader)
       
   287         return undefined;
       
   288 
       
   289     Document* document = frameLoader->frame()->document();
       
   290     if (!document)
       
   291         return undefined;
       
   292 
       
   293     if (document->isPluginDocument() || document->isImageDocument())
       
   294         return undefined;
       
   295 
       
   296     KJS::JSLock lock;
       
   297     JSValueRef documentValue = toRef(toJS(toJS(controller->scriptContext()), document));
       
   298     return documentValue;
       
   299 }
       
   300 
       
   301 static JSValueRef highlightDOMNode(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
       
   302 {
       
   303     JSValueRef undefined = JSValueMakeUndefined(context);
       
   304 
       
   305     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   306     if (argumentCount < 1 || !controller)
       
   307         return undefined;
       
   308 
       
   309     Node* node = toNode(toJS(arguments[0]));
       
   310     if (!node)
       
   311         return undefined;
       
   312 
       
   313     controller->highlight(node);
       
   314 
       
   315     return undefined;
       
   316 }
       
   317 
       
   318 static JSValueRef hideDOMNodeHighlight(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
       
   319 {
       
   320     JSValueRef undefined = JSValueMakeUndefined(context);
       
   321 
       
   322     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   323     if (argumentCount || !controller)
       
   324         return undefined;
       
   325 
       
   326     controller->hideHighlight();
       
   327 
       
   328     return undefined;
       
   329 }
       
   330 
       
   331 static JSValueRef loaded(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
       
   332 {
       
   333     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   334     if (!controller)
       
   335         return JSValueMakeUndefined(ctx);
       
   336 
       
   337     controller->scriptObjectReady();
       
   338     return JSValueMakeUndefined(ctx);
       
   339 }
       
   340 
       
   341 static JSValueRef unloading(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
       
   342 {
       
   343     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   344     if (!controller)
       
   345         return JSValueMakeUndefined(ctx);
       
   346 
       
   347     controller->windowUnloading();
       
   348     return JSValueMakeUndefined(ctx);
       
   349 }
       
   350 
       
   351 static JSValueRef attach(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
       
   352 {
       
   353     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   354     if (!controller)
       
   355         return JSValueMakeUndefined(ctx);
       
   356 
       
   357     controller->attachWindow();
       
   358     return JSValueMakeUndefined(ctx);
       
   359 }
       
   360 
       
   361 static JSValueRef detach(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
       
   362 {
       
   363     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   364     if (!controller)
       
   365         return JSValueMakeUndefined(ctx);
       
   366 
       
   367     controller->detachWindow();
       
   368     return JSValueMakeUndefined(ctx);
       
   369 }
       
   370 
       
   371 static JSValueRef log(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
       
   372 {
       
   373     if (argumentCount < 1 || !JSValueIsString(ctx, arguments[0]))
       
   374         return JSValueMakeUndefined(ctx);
       
   375 
       
   376 #ifndef NDEBUG
       
   377     JSStringRef string = JSValueToStringCopy(ctx, arguments[0], 0);
       
   378     String message(JSStringGetCharactersPtr(string), JSStringGetLength(string));
       
   379     JSStringRelease(string);
       
   380 
       
   381     fprintf(stderr, "%s\n", message.latin1().data());
       
   382 #endif
       
   383 
       
   384     return JSValueMakeUndefined(ctx);
       
   385 }
       
   386 
       
   387 static JSValueRef search(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
       
   388 {
       
   389     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   390     if (!controller)
       
   391         return JSValueMakeUndefined(ctx);
       
   392 
       
   393     if (argumentCount < 2 || !JSValueIsString(ctx, arguments[1]))
       
   394         return JSValueMakeUndefined(ctx);
       
   395 
       
   396     Node* node = toNode(toJS(arguments[0]));
       
   397     if (!node)
       
   398         return JSValueMakeUndefined(ctx);
       
   399 
       
   400     JSStringRef string = JSValueToStringCopy(ctx, arguments[1], 0);
       
   401     String target(JSStringGetCharactersPtr(string), JSStringGetLength(string));
       
   402     JSStringRelease(string);
       
   403 
       
   404     JSObjectRef globalObject = JSContextGetGlobalObject(ctx);
       
   405     JSStringRef constructorString = JSStringCreateWithUTF8CString("Array");
       
   406     JSObjectRef arrayConstructor = JSValueToObject(ctx, JSObjectGetProperty(ctx, globalObject, constructorString, 0), 0);
       
   407     JSStringRelease(constructorString);
       
   408     JSObjectRef array = JSObjectCallAsConstructor(ctx, arrayConstructor, 0, 0, 0);
       
   409 
       
   410     JSStringRef pushString = JSStringCreateWithUTF8CString("push");
       
   411     JSValueRef pushValue = JSObjectGetProperty(ctx, array, pushString, 0);
       
   412     JSStringRelease(pushString);
       
   413     JSObjectRef push = JSValueToObject(ctx, pushValue, 0);
       
   414 
       
   415     RefPtr<Range> searchRange(rangeOfContents(node));
       
   416 
       
   417     int exception = 0;
       
   418     do {
       
   419         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false));
       
   420         if (resultRange->collapsed(exception))
       
   421             break;
       
   422 
       
   423         // A non-collapsed result range can in some funky whitespace cases still not
       
   424         // advance the range's start position (4509328). Break to avoid infinite loop.
       
   425         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
       
   426         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
       
   427             break;
       
   428 
       
   429         KJS::JSLock lock;
       
   430         JSValueRef arg0 = toRef(toJS(toJS(ctx), resultRange.get()));
       
   431         JSObjectCallAsFunction(ctx, push, array, 1, &arg0, 0);
       
   432 
       
   433         setStart(searchRange.get(), newStart);
       
   434     } while (true);
       
   435 
       
   436     return array;
       
   437 }
       
   438 
       
   439 static JSValueRef inspectedWindow(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
       
   440 {
       
   441     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
       
   442     if (!controller)
       
   443         return JSValueMakeUndefined(ctx);
       
   444 
       
   445     return toRef(KJS::Window::retrieve(controller->inspectedPage()->mainFrame()));
       
   446 }
       
   447 
       
   448 InspectorController::InspectorController(Page* page, InspectorClient* client)
       
   449     : m_inspectedPage(page)
       
   450     , m_client(client)
       
   451     , m_page(0)
       
   452     , m_scriptObject(0)
       
   453     , m_controllerScriptObject(0)
       
   454     , m_scriptContext(0)
       
   455     , m_windowVisible(false)
       
   456     , m_nextIdentifier(-2)
       
   457 {
       
   458     ASSERT_ARG(page, page);
       
   459     ASSERT_ARG(client, client);
       
   460 }
       
   461 
       
   462 InspectorController::~InspectorController()
       
   463 {
       
   464     if (m_scriptContext) {
       
   465         JSObjectRef global = JSContextGetGlobalObject(m_scriptContext);
       
   466         JSStringRef controllerProperty = JSStringCreateWithUTF8CString("InspectorController");
       
   467         JSObjectRef controller = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, global, controllerProperty, 0), 0);
       
   468         JSStringRelease(controllerProperty);
       
   469         JSObjectSetPrivate(controller, 0);
       
   470     }
       
   471 
       
   472     m_client->closeWindow();
       
   473     m_client->inspectorDestroyed();
       
   474 
       
   475     if (m_page)
       
   476         m_page->setParentInspectorController(0);
       
   477 
       
   478     deleteAllValues(m_frameResources);
       
   479     deleteAllValues(m_consoleMessages);
       
   480 }
       
   481 
       
   482 bool InspectorController::enabled() const
       
   483 {
       
   484     return m_inspectedPage->settings()->developerExtrasEnabled();
       
   485 }
       
   486 
       
   487 void InspectorController::inspect(Node* node)
       
   488 {
       
   489     if (!node || !enabled())
       
   490         return;
       
   491 
       
   492     if (!m_page) {
       
   493         m_page = m_client->createPage();
       
   494         if (!m_page)
       
   495             return;
       
   496 
       
   497         m_page->setParentInspectorController(this);
       
   498     }
       
   499 
       
   500     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
       
   501         node = node->parentNode();
       
   502     m_nodeToFocus = node;
       
   503 
       
   504     if (!m_scriptObject)
       
   505         return;
       
   506 
       
   507     if (windowVisible())
       
   508         focusNode();
       
   509     else
       
   510         m_client->showWindow();
       
   511 }
       
   512 
       
   513 void InspectorController::focusNode()
       
   514 {
       
   515     if (!enabled())
       
   516         return;
       
   517 
       
   518     ASSERT(m_scriptContext);
       
   519     ASSERT(m_scriptObject);
       
   520     ASSERT(m_nodeToFocus);
       
   521 
       
   522     JSValueRef arg0;
       
   523 
       
   524     {
       
   525         KJS::JSLock lock;
       
   526         arg0 = toRef(toJS(toJS(m_scriptContext), m_nodeToFocus.get()));
       
   527     }
       
   528 
       
   529     m_nodeToFocus = 0;
       
   530 
       
   531     JSStringRef functionProperty = JSStringCreateWithUTF8CString("updateFocusedNode");
       
   532     JSObjectRef function = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, functionProperty, 0), 0);
       
   533     JSStringRelease(functionProperty);
       
   534     ASSERT(function);
       
   535 
       
   536     JSObjectCallAsFunction(m_scriptContext, function, m_scriptObject, 1, &arg0, 0);
       
   537 }
       
   538 
       
   539 void InspectorController::highlight(Node* node)
       
   540 {
       
   541     if (!enabled())
       
   542         return;
       
   543     ASSERT_ARG(node, node);
       
   544     m_client->highlight(node);
       
   545 }
       
   546 
       
   547 void InspectorController::hideHighlight()
       
   548 {
       
   549     if (!enabled())
       
   550         return;
       
   551     m_client->hideHighlight();
       
   552 }
       
   553 
       
   554 bool InspectorController::windowVisible()
       
   555 {
       
   556     return m_windowVisible;
       
   557 }
       
   558 
       
   559 void InspectorController::setWindowVisible(bool visible)
       
   560 {
       
   561     if (visible == m_windowVisible)
       
   562         return;
       
   563 
       
   564     m_windowVisible = visible;
       
   565 
       
   566     if (!m_scriptContext || !m_scriptObject)
       
   567         return;
       
   568 
       
   569     if (m_windowVisible) {
       
   570         populateScriptResources();
       
   571         if (m_nodeToFocus)
       
   572             focusNode();
       
   573     } else {
       
   574         clearScriptResources();
       
   575         clearScriptConsoleMessages();
       
   576         clearNetworkTimeline();
       
   577     }
       
   578 }
       
   579 
       
   580 void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID)
       
   581 {
       
   582     if (!enabled())
       
   583         return;
       
   584 
       
   585     ConsoleMessage* consoleMessage = new ConsoleMessage(source, level, message, lineNumber, sourceID);
       
   586     m_consoleMessages.append(consoleMessage);
       
   587 
       
   588     if (windowVisible())
       
   589         addScriptConsoleMessage(consoleMessage);
       
   590 }
       
   591 
       
   592 void InspectorController::attachWindow()
       
   593 {
       
   594     if (!enabled())
       
   595         return;
       
   596     m_client->attachWindow();
       
   597 }
       
   598 
       
   599 void InspectorController::detachWindow()
       
   600 {
       
   601     if (!enabled())
       
   602         return;
       
   603     m_client->detachWindow();
       
   604 }
       
   605 
       
   606 void InspectorController::windowScriptObjectAvailable()
       
   607 {
       
   608     if (!m_page || !enabled())
       
   609         return;
       
   610 
       
   611     m_scriptContext = toRef(m_page->mainFrame()->scriptProxy()->interpreter()->globalExec());
       
   612 
       
   613     JSObjectRef global = JSContextGetGlobalObject(m_scriptContext);
       
   614     ASSERT(global);
       
   615 
       
   616     static JSStaticFunction staticFunctions[] = {
       
   617         { "addSourceToFrame", addSourceToFrame, kJSPropertyAttributeNone },
       
   618         { "getResourceDocumentNode", getResourceDocumentNode, kJSPropertyAttributeNone },
       
   619         { "highlightDOMNode", highlightDOMNode, kJSPropertyAttributeNone },
       
   620         { "hideDOMNodeHighlight", hideDOMNodeHighlight, kJSPropertyAttributeNone },
       
   621         { "loaded", loaded, kJSPropertyAttributeNone },
       
   622         { "windowUnloading", unloading, kJSPropertyAttributeNone },
       
   623         { "attach", attach, kJSPropertyAttributeNone },
       
   624         { "detach", detach, kJSPropertyAttributeNone },
       
   625         { "log", log, kJSPropertyAttributeNone },
       
   626         { "search", search, kJSPropertyAttributeNone },
       
   627         { "inspectedWindow", inspectedWindow, kJSPropertyAttributeNone },
       
   628         { 0, 0, 0 }
       
   629     };
       
   630 
       
   631     JSClassDefinition inspectorControllerDefinition = {
       
   632         0, kJSClassAttributeNone, "InspectorController", 0, 0, staticFunctions,
       
   633         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
   634     };
       
   635 
       
   636     JSClassRef controllerClass = JSClassCreate(&inspectorControllerDefinition);
       
   637     ASSERT(controllerClass);
       
   638 
       
   639     m_controllerScriptObject = JSObjectMake(m_scriptContext, controllerClass, reinterpret_cast<void*>(this));
       
   640     ASSERT(m_controllerScriptObject);
       
   641 
       
   642     JSStringRef controllerObjectString = JSStringCreateWithUTF8CString("InspectorController");
       
   643     JSObjectSetProperty(m_scriptContext, global, controllerObjectString, m_controllerScriptObject, kJSPropertyAttributeNone, 0);
       
   644     JSStringRelease(controllerObjectString);
       
   645 }
       
   646 
       
   647 void InspectorController::scriptObjectReady()
       
   648 {
       
   649     ASSERT(m_scriptContext);
       
   650     if (!m_scriptContext)
       
   651         return;
       
   652 
       
   653     JSObjectRef global = JSContextGetGlobalObject(m_scriptContext);
       
   654     ASSERT(global);
       
   655 
       
   656     JSStringRef inspectorString = JSStringCreateWithUTF8CString("WebInspector");
       
   657     JSValueRef inspectorValue = JSObjectGetProperty(m_scriptContext, global, inspectorString, 0);
       
   658     JSStringRelease(inspectorString);
       
   659 
       
   660     ASSERT(inspectorValue);
       
   661     if (!inspectorValue)
       
   662         return;
       
   663 
       
   664     m_scriptObject = JSValueToObject(m_scriptContext, inspectorValue, 0);
       
   665     ASSERT(m_scriptObject);
       
   666 
       
   667     JSValueProtect(m_scriptContext, m_scriptObject);
       
   668 
       
   669     // Make sure our window is visible now that the page loaded
       
   670     m_client->showWindow();
       
   671 }
       
   672 
       
   673 void InspectorController::windowUnloading()
       
   674 {
       
   675     m_client->closeWindow();
       
   676     if (m_page)
       
   677         m_page->setParentInspectorController(0);
       
   678 
       
   679     ASSERT(m_scriptContext && m_scriptObject);
       
   680     JSValueUnprotect(m_scriptContext, m_scriptObject);
       
   681 
       
   682     m_page = 0;
       
   683     m_scriptObject = 0;
       
   684     m_scriptContext = 0;
       
   685 }
       
   686 
       
   687 static void addHeaders(JSContextRef context, JSObjectRef object, const HTTPHeaderMap& headers)
       
   688 {
       
   689     ASSERT_ARG(context, context);
       
   690     ASSERT_ARG(object, object);
       
   691     
       
   692     HTTPHeaderMap::const_iterator end = headers.end();
       
   693     for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it) {
       
   694         JSStringRef field = JSStringCreateWithCharacters(it->first.characters(), it->first.length());
       
   695         JSStringRef valueString = JSStringCreateWithCharacters(it->second.characters(), it->second.length());
       
   696         JSValueRef value = JSValueMakeString(context, valueString);
       
   697         JSObjectSetProperty(context, object, field, value, kJSPropertyAttributeNone, 0);
       
   698         JSStringRelease(field);
       
   699         JSStringRelease(valueString);
       
   700     }
       
   701 }
       
   702 
       
   703 static JSObjectRef scriptObjectForRequest(JSContextRef context, const InspectorResource* resource)
       
   704 {
       
   705     ASSERT_ARG(context, context);
       
   706 
       
   707     JSObjectRef object = JSObjectMake(context, 0, 0);
       
   708     addHeaders(context, object, resource->requestHeaderFields);
       
   709 
       
   710     return object;
       
   711 }
       
   712 
       
   713 static JSObjectRef scriptObjectForResponse(JSContextRef context, const InspectorResource* resource)
       
   714 {
       
   715     ASSERT_ARG(context, context);
       
   716 
       
   717     JSObjectRef object = JSObjectMake(context, 0, 0);
       
   718     addHeaders(context, object, resource->responseHeaderFields);
       
   719 
       
   720     return object;
       
   721 }
       
   722 
       
   723 JSObjectRef InspectorController::addScriptResource(InspectorResource* resource)
       
   724 {
       
   725     ASSERT_ARG(resource, resource);
       
   726 
       
   727     // This happens for pages loaded from the back/forward cache.
       
   728     if (resource->scriptObject)
       
   729         return resource->scriptObject;
       
   730 
       
   731     ASSERT(m_scriptContext);
       
   732     ASSERT(m_scriptObject);
       
   733     if (!m_scriptContext || !m_scriptObject)
       
   734         return 0;
       
   735 
       
   736     JSStringRef resourceString = JSStringCreateWithUTF8CString("Resource");
       
   737     JSObjectRef resourceConstructor = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, resourceString, 0), 0);
       
   738     JSStringRelease(resourceString);
       
   739 
       
   740     String urlString = resource->requestURL.url();
       
   741     JSStringRef url = JSStringCreateWithCharacters(urlString.characters(), urlString.length());
       
   742     JSValueRef urlValue = JSValueMakeString(m_scriptContext, url);
       
   743     JSStringRelease(url);
       
   744 
       
   745     urlString = resource->requestURL.host();
       
   746     JSStringRef domain = JSStringCreateWithCharacters(urlString.characters(), urlString.length());
       
   747     JSValueRef domainValue = JSValueMakeString(m_scriptContext, domain);
       
   748     JSStringRelease(domain);
       
   749 
       
   750     urlString = resource->requestURL.path();
       
   751     JSStringRef path = JSStringCreateWithCharacters(urlString.characters(), urlString.length());
       
   752     JSValueRef pathValue = JSValueMakeString(m_scriptContext, path);
       
   753     JSStringRelease(path);
       
   754 
       
   755     urlString = resource->requestURL.lastPathComponent();
       
   756     JSStringRef lastPathComponent = JSStringCreateWithCharacters(urlString.characters(), urlString.length());
       
   757     JSValueRef lastPathComponentValue = JSValueMakeString(m_scriptContext, lastPathComponent);
       
   758     JSStringRelease(lastPathComponent);
       
   759 
       
   760     JSValueRef identifier = JSValueMakeNumber(m_scriptContext, resource->identifier);
       
   761     JSValueRef mainResource = JSValueMakeBoolean(m_scriptContext, m_mainResource == resource);
       
   762     JSValueRef cached = JSValueMakeBoolean(m_scriptContext, resource->cached);
       
   763 
       
   764     JSValueRef arguments[] = { scriptObjectForRequest(m_scriptContext, resource), urlValue, domainValue, pathValue, lastPathComponentValue, identifier, mainResource, cached };
       
   765     JSObjectRef result = JSObjectCallAsConstructor(m_scriptContext, resourceConstructor, 8, arguments, 0);
       
   766 
       
   767     resource->setScriptObject(m_scriptContext, result);
       
   768 
       
   769     ASSERT(result);
       
   770 
       
   771     JSStringRef addResourceString = JSStringCreateWithUTF8CString("addResource");
       
   772     JSObjectRef addResourceFunction = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, addResourceString, 0), 0);
       
   773     JSStringRelease(addResourceString);
       
   774 
       
   775     JSValueRef addArguments[] = { result };
       
   776     JSObjectCallAsFunction(m_scriptContext, addResourceFunction, m_scriptObject, 1, addArguments, 0);
       
   777 
       
   778     return result;
       
   779 }
       
   780 
       
   781 JSObjectRef InspectorController::addAndUpdateScriptResource(InspectorResource* resource)
       
   782 {
       
   783     ASSERT_ARG(resource, resource);
       
   784 
       
   785     JSObjectRef scriptResource = addScriptResource(resource);
       
   786     updateScriptResourceResponse(resource);
       
   787     updateScriptResource(resource, resource->length);
       
   788     updateScriptResource(resource, resource->startTime, resource->responseReceivedTime, resource->endTime);
       
   789     updateScriptResource(resource, resource->finished, resource->failed);
       
   790     return scriptResource;
       
   791 }
       
   792 
       
   793 void InspectorController::removeScriptResource(InspectorResource* resource)
       
   794 {
       
   795     ASSERT(m_scriptContext);
       
   796     ASSERT(m_scriptObject);
       
   797     if (!m_scriptContext || !m_scriptObject)
       
   798         return;
       
   799 
       
   800     ASSERT(resource);
       
   801     ASSERT(resource->scriptObject);
       
   802     if (!resource || !resource->scriptObject)
       
   803         return;
       
   804 
       
   805     JSStringRef removeResourceString = JSStringCreateWithUTF8CString("removeResource");
       
   806     JSObjectRef removeResourceFunction = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, removeResourceString, 0), 0);
       
   807     JSStringRelease(removeResourceString);
       
   808 
       
   809     JSValueRef arguments[] = { resource->scriptObject };
       
   810     JSObjectCallAsFunction(m_scriptContext, removeResourceFunction, m_scriptObject, 1, arguments, 0);
       
   811 
       
   812     resource->setScriptObject(0, 0);
       
   813 }
       
   814 
       
   815 static void updateResourceRequest(InspectorResource* resource, const ResourceRequest& request)
       
   816 {
       
   817     resource->requestHeaderFields = request.httpHeaderFields();
       
   818     resource->requestURL = request.url();
       
   819 }
       
   820 
       
   821 static void updateResourceResponse(InspectorResource* resource, const ResourceResponse& response)
       
   822 {
       
   823     resource->expectedContentLength = response.expectedContentLength();
       
   824     resource->mimeType = response.mimeType();
       
   825     resource->responseHeaderFields = response.httpHeaderFields();
       
   826     resource->responseStatusCode = response.httpStatusCode();
       
   827     resource->suggestedFilename = response.suggestedFilename();
       
   828     resource->textEncodingName = response.textEncodingName();
       
   829 }
       
   830 
       
   831 void InspectorController::updateScriptResourceRequest(InspectorResource* resource)
       
   832 {
       
   833     ASSERT(resource->scriptObject);
       
   834     ASSERT(m_scriptContext);
       
   835     if (!resource->scriptObject || !m_scriptContext)
       
   836         return;
       
   837 
       
   838     String urlString = resource->requestURL.url();
       
   839     JSStringRef url = JSStringCreateWithCharacters(urlString.characters(), urlString.length());
       
   840     JSValueRef urlValue = JSValueMakeString(m_scriptContext, url);
       
   841     JSStringRelease(url);
       
   842 
       
   843     urlString = resource->requestURL.host();
       
   844     JSStringRef domain = JSStringCreateWithCharacters(urlString.characters(), urlString.length());
       
   845     JSValueRef domainValue = JSValueMakeString(m_scriptContext, domain);
       
   846     JSStringRelease(domain);
       
   847 
       
   848     urlString = resource->requestURL.path();
       
   849     JSStringRef path = JSStringCreateWithCharacters(urlString.characters(), urlString.length());
       
   850     JSValueRef pathValue = JSValueMakeString(m_scriptContext, path);
       
   851     JSStringRelease(path);
       
   852 
       
   853     urlString = resource->requestURL.lastPathComponent();
       
   854     JSStringRef lastPathComponent = JSStringCreateWithCharacters(urlString.characters(), urlString.length());
       
   855     JSValueRef lastPathComponentValue = JSValueMakeString(m_scriptContext, lastPathComponent);
       
   856     JSStringRelease(lastPathComponent);
       
   857 
       
   858     JSValueRef mainResourceValue = JSValueMakeBoolean(m_scriptContext, m_mainResource == resource);
       
   859 
       
   860     JSStringRef propertyName = JSStringCreateWithUTF8CString("url");
       
   861     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, urlValue, kJSPropertyAttributeNone, 0);
       
   862     JSStringRelease(propertyName);
       
   863 
       
   864     propertyName = JSStringCreateWithUTF8CString("domain");
       
   865     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, domainValue, kJSPropertyAttributeNone, 0);
       
   866     JSStringRelease(propertyName);
       
   867 
       
   868     propertyName = JSStringCreateWithUTF8CString("path");
       
   869     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, pathValue, kJSPropertyAttributeNone, 0);
       
   870     JSStringRelease(propertyName);
       
   871 
       
   872     propertyName = JSStringCreateWithUTF8CString("lastPathComponent");
       
   873     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, lastPathComponentValue, kJSPropertyAttributeNone, 0);
       
   874     JSStringRelease(propertyName);
       
   875 
       
   876     propertyName = JSStringCreateWithUTF8CString("requestHeaders");
       
   877     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, scriptObjectForRequest(m_scriptContext, resource), kJSPropertyAttributeNone, 0);
       
   878     JSStringRelease(propertyName);
       
   879 
       
   880     propertyName = JSStringCreateWithUTF8CString("mainResource");
       
   881     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, mainResourceValue, kJSPropertyAttributeNone, 0);
       
   882     JSStringRelease(propertyName);
       
   883 }
       
   884 
       
   885 void InspectorController::updateScriptResourceResponse(InspectorResource* resource)
       
   886 {
       
   887     ASSERT(resource->scriptObject);
       
   888     ASSERT(m_scriptContext);
       
   889     if (!resource->scriptObject || !m_scriptContext)
       
   890         return;
       
   891 
       
   892     JSStringRef mimeType = JSStringCreateWithCharacters(resource->mimeType.characters(), resource->mimeType.length());
       
   893     JSValueRef mimeTypeValue = JSValueMakeString(m_scriptContext, mimeType);
       
   894     JSStringRelease(mimeType);
       
   895 
       
   896     JSStringRef suggestedFilename = JSStringCreateWithCharacters(resource->suggestedFilename.characters(), resource->suggestedFilename.length());
       
   897     JSValueRef suggestedFilenameValue = JSValueMakeString(m_scriptContext, suggestedFilename);
       
   898     JSStringRelease(suggestedFilename);
       
   899 
       
   900     JSValueRef expectedContentLengthValue = JSValueMakeNumber(m_scriptContext, static_cast<double>(resource->expectedContentLength));
       
   901     JSValueRef statusCodeValue = JSValueMakeNumber(m_scriptContext, resource->responseStatusCode);
       
   902 
       
   903     JSStringRef propertyName = JSStringCreateWithUTF8CString("mimeType");
       
   904     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, mimeTypeValue, kJSPropertyAttributeNone, 0);
       
   905     JSStringRelease(propertyName);
       
   906 
       
   907     propertyName = JSStringCreateWithUTF8CString("suggestedFilename");
       
   908     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, suggestedFilenameValue, kJSPropertyAttributeNone, 0);
       
   909     JSStringRelease(propertyName);
       
   910 
       
   911     propertyName = JSStringCreateWithUTF8CString("expectedContentLength");
       
   912     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, expectedContentLengthValue, kJSPropertyAttributeNone, 0);
       
   913     JSStringRelease(propertyName);
       
   914 
       
   915     propertyName = JSStringCreateWithUTF8CString("statusCode");
       
   916     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, statusCodeValue, kJSPropertyAttributeNone, 0);
       
   917     JSStringRelease(propertyName);
       
   918     
       
   919     propertyName = JSStringCreateWithUTF8CString("responseHeaders");
       
   920     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, scriptObjectForResponse(m_scriptContext, resource), kJSPropertyAttributeNone, 0);
       
   921     JSStringRelease(propertyName);
       
   922 
       
   923     JSValueRef typeValue = JSValueMakeNumber(m_scriptContext, resource->type());
       
   924     propertyName = JSStringCreateWithUTF8CString("type");
       
   925     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, typeValue, kJSPropertyAttributeNone, 0);
       
   926     JSStringRelease(propertyName);
       
   927 }
       
   928 
       
   929 void InspectorController::updateScriptResource(InspectorResource* resource, int length)
       
   930 {
       
   931     ASSERT(resource->scriptObject);
       
   932     ASSERT(m_scriptContext);
       
   933     if (!resource->scriptObject || !m_scriptContext)
       
   934         return;
       
   935 
       
   936     JSValueRef lengthValue = JSValueMakeNumber(m_scriptContext, length);
       
   937 
       
   938     JSStringRef propertyName = JSStringCreateWithUTF8CString("contentLength");
       
   939     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, lengthValue, kJSPropertyAttributeNone, 0);
       
   940     JSStringRelease(propertyName);
       
   941 }
       
   942 
       
   943 void InspectorController::updateScriptResource(InspectorResource* resource, bool finished, bool failed)
       
   944 {
       
   945     ASSERT(resource->scriptObject);
       
   946     ASSERT(m_scriptContext);
       
   947     if (!resource->scriptObject || !m_scriptContext)
       
   948         return;
       
   949 
       
   950     JSValueRef failedValue = JSValueMakeBoolean(m_scriptContext, failed);
       
   951     JSValueRef finishedValue = JSValueMakeBoolean(m_scriptContext, finished);
       
   952 
       
   953     JSStringRef propertyName = JSStringCreateWithUTF8CString("failed");
       
   954     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, failedValue, kJSPropertyAttributeNone, 0);
       
   955     JSStringRelease(propertyName);
       
   956 
       
   957     propertyName = JSStringCreateWithUTF8CString("finished");
       
   958     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, finishedValue, kJSPropertyAttributeNone, 0);
       
   959     JSStringRelease(propertyName);
       
   960 
       
   961 }
       
   962 
       
   963 void InspectorController::updateScriptResource(InspectorResource* resource, double startTime, double responseReceivedTime, double endTime)
       
   964 {
       
   965     ASSERT(resource->scriptObject);
       
   966     ASSERT(m_scriptContext);
       
   967     if (!resource->scriptObject || !m_scriptContext)
       
   968         return;
       
   969 
       
   970     JSValueRef startTimeValue = JSValueMakeNumber(m_scriptContext, startTime);
       
   971     JSValueRef responseReceivedTimeValue = JSValueMakeNumber(m_scriptContext, responseReceivedTime);
       
   972     JSValueRef endTimeValue = JSValueMakeNumber(m_scriptContext, endTime);
       
   973 
       
   974     JSStringRef propertyName = JSStringCreateWithUTF8CString("startTime");
       
   975     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, startTimeValue, kJSPropertyAttributeNone, 0);
       
   976     JSStringRelease(propertyName);
       
   977 
       
   978     propertyName = JSStringCreateWithUTF8CString("responseReceivedTime");
       
   979     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, responseReceivedTimeValue, kJSPropertyAttributeNone, 0);
       
   980     JSStringRelease(propertyName);
       
   981 
       
   982     propertyName = JSStringCreateWithUTF8CString("endTime");
       
   983     JSObjectSetProperty(m_scriptContext, resource->scriptObject, propertyName, endTimeValue, kJSPropertyAttributeNone, 0);
       
   984     JSStringRelease(propertyName);
       
   985 }
       
   986 
       
   987 void InspectorController::populateScriptResources()
       
   988 {
       
   989     ASSERT(m_scriptContext);
       
   990     if (!m_scriptContext)
       
   991         return;
       
   992 
       
   993     clearScriptResources();
       
   994     clearScriptConsoleMessages();
       
   995     clearNetworkTimeline();
       
   996 
       
   997     ResourcesMap::iterator resourcesEnd = m_resources.end();
       
   998     for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it)
       
   999         addAndUpdateScriptResource(it->second.get());
       
  1000 
       
  1001     unsigned messageCount = m_consoleMessages.size();
       
  1002     for (unsigned i = 0; i < messageCount; ++i)
       
  1003         addScriptConsoleMessage(m_consoleMessages[i]);
       
  1004 }
       
  1005 
       
  1006 void InspectorController::addScriptConsoleMessage(const ConsoleMessage* message)
       
  1007 {
       
  1008     ASSERT_ARG(message, message);
       
  1009 
       
  1010     JSStringRef messageConstructorString = JSStringCreateWithUTF8CString("ConsoleMessage");
       
  1011     JSObjectRef messageConstructor = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, messageConstructorString, 0), 0);
       
  1012     JSStringRelease(messageConstructorString);
       
  1013 
       
  1014     JSStringRef addMessageString = JSStringCreateWithUTF8CString("addMessageToConsole");
       
  1015     JSObjectRef addMessage = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, addMessageString, 0), 0);
       
  1016     JSStringRelease(addMessageString);
       
  1017 
       
  1018     JSValueRef sourceValue = JSValueMakeNumber(m_scriptContext, message->source);
       
  1019     JSValueRef levelValue = JSValueMakeNumber(m_scriptContext, message->level);
       
  1020     JSStringRef messageString = JSStringCreateWithCharacters(message->message.characters(), message->message.length());
       
  1021     JSValueRef messageValue = JSValueMakeString(m_scriptContext, messageString);
       
  1022     JSValueRef lineValue = JSValueMakeNumber(m_scriptContext, message->line);
       
  1023     JSStringRef urlString = JSStringCreateWithCharacters(message->url.characters(), message->url.length());
       
  1024     JSValueRef urlValue = JSValueMakeString(m_scriptContext, urlString);
       
  1025 
       
  1026     JSValueRef args[] = { sourceValue, levelValue, messageValue, lineValue, urlValue };
       
  1027     JSObjectRef messageObject = JSObjectCallAsConstructor(m_scriptContext, messageConstructor, 5, args, 0);
       
  1028     JSStringRelease(messageString);
       
  1029     JSStringRelease(urlString);
       
  1030 
       
  1031     JSObjectCallAsFunction(m_scriptContext, addMessage, m_scriptObject, 1, &messageObject, 0);
       
  1032 }
       
  1033 
       
  1034 static void callClearFunction(JSContextRef context, JSObjectRef thisObject, const char* functionName)
       
  1035 {
       
  1036     ASSERT_ARG(context, context);
       
  1037     ASSERT_ARG(thisObject, thisObject);
       
  1038 
       
  1039     JSStringRef string = JSStringCreateWithUTF8CString(functionName);
       
  1040     JSObjectRef function = JSValueToObject(context, JSObjectGetProperty(context, thisObject, string, 0), 0);
       
  1041     JSStringRelease(string);
       
  1042 
       
  1043     JSObjectCallAsFunction(context, function, thisObject, 0, 0, 0);
       
  1044 }
       
  1045 
       
  1046 void InspectorController::clearScriptResources()
       
  1047 {
       
  1048     if (!m_scriptContext || !m_scriptObject)
       
  1049         return;
       
  1050 
       
  1051     ResourcesMap::iterator resourcesEnd = m_resources.end();
       
  1052     for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) {
       
  1053         InspectorResource* resource = it->second.get();
       
  1054         resource->setScriptObject(0, 0);
       
  1055     }
       
  1056 
       
  1057     callClearFunction(m_scriptContext, m_scriptObject, "clearResources");
       
  1058 }
       
  1059 
       
  1060 void InspectorController::clearScriptConsoleMessages()
       
  1061 {
       
  1062     if (!m_scriptContext || !m_scriptObject)
       
  1063         return;
       
  1064 
       
  1065     callClearFunction(m_scriptContext, m_scriptObject, "clearConsoleMessages");
       
  1066 }
       
  1067 
       
  1068 void InspectorController::clearNetworkTimeline()
       
  1069 {
       
  1070     if (!m_scriptContext || !m_scriptObject)
       
  1071         return;
       
  1072 
       
  1073     callClearFunction(m_scriptContext, m_scriptObject, "clearNetworkTimeline");
       
  1074 }
       
  1075 
       
  1076 void InspectorController::pruneResources(ResourcesMap* resourceMap, DocumentLoader* loaderToKeep)
       
  1077 {
       
  1078     ASSERT_ARG(resourceMap, resourceMap);
       
  1079 
       
  1080     ResourcesMap mapCopy(*resourceMap);
       
  1081     ResourcesMap::iterator end = mapCopy.end();
       
  1082     for (ResourcesMap::iterator it = mapCopy.begin(); it != end; ++it) {
       
  1083         InspectorResource* resource = (*it).second.get();
       
  1084         if (resource == m_mainResource)
       
  1085             continue;
       
  1086 
       
  1087         if (!loaderToKeep || resource->loader != loaderToKeep) {
       
  1088             removeResource(resource);
       
  1089             if (windowVisible() && resource->scriptObject)
       
  1090                 removeScriptResource(resource);
       
  1091         }
       
  1092     }
       
  1093 }
       
  1094 
       
  1095 void InspectorController::didCommitLoad(DocumentLoader* loader)
       
  1096 {
       
  1097     if (!enabled())
       
  1098         return;
       
  1099 
       
  1100     if (loader->frame() == m_inspectedPage->mainFrame()) {
       
  1101         ASSERT(m_mainResource);
       
  1102         // FIXME: Should look into asserting that m_mainResource->loader == loader here.
       
  1103 
       
  1104         m_client->inspectedURLChanged(loader->URL().url());
       
  1105         deleteAllValues(m_consoleMessages);
       
  1106         m_consoleMessages.clear();
       
  1107         if (windowVisible()) {
       
  1108             clearScriptConsoleMessages();
       
  1109             clearNetworkTimeline();
       
  1110 
       
  1111             // We don't add the main resource until its load is committed. This
       
  1112             // is needed to keep the load for a user-entered URL from showing
       
  1113             // up in the list of resources for the page they are navigating
       
  1114             // away from.
       
  1115             addAndUpdateScriptResource(m_mainResource.get());
       
  1116         }
       
  1117     }
       
  1118 
       
  1119     for (Frame* frame = loader->frame(); frame; frame = frame->tree()->traverseNext(loader->frame()))
       
  1120         if (ResourcesMap* resourceMap = m_frameResources.get(frame))
       
  1121             pruneResources(resourceMap, loader);
       
  1122 }
       
  1123 
       
  1124 void InspectorController::frameDetachedFromParent(Frame* frame)
       
  1125 {
       
  1126     if (!enabled())
       
  1127         return;
       
  1128     if (ResourcesMap* resourceMap = m_frameResources.get(frame))
       
  1129         removeAllResources(resourceMap);
       
  1130 }
       
  1131 
       
  1132 void InspectorController::addResource(InspectorResource* resource)
       
  1133 {
       
  1134     m_resources.set(resource->identifier, resource);
       
  1135 
       
  1136     Frame* frame = resource->frame.get();
       
  1137     ResourcesMap* resourceMap = m_frameResources.get(frame);
       
  1138     if (resourceMap)
       
  1139         resourceMap->set(resource->identifier, resource);
       
  1140     else {
       
  1141         resourceMap = new ResourcesMap;
       
  1142         resourceMap->set(resource->identifier, resource);
       
  1143         m_frameResources.set(frame, resourceMap);
       
  1144     }
       
  1145 }
       
  1146 
       
  1147 void InspectorController::removeResource(InspectorResource* resource)
       
  1148 {
       
  1149     m_resources.remove(resource->identifier);
       
  1150 
       
  1151     Frame* frame = resource->frame.get();
       
  1152     ResourcesMap* resourceMap = m_frameResources.get(frame);
       
  1153     if (!resourceMap) {
       
  1154         ASSERT_NOT_REACHED();
       
  1155         return;
       
  1156     }
       
  1157 
       
  1158     resourceMap->remove(resource->identifier);
       
  1159     if (resourceMap->isEmpty()) {
       
  1160         m_frameResources.remove(frame);
       
  1161         delete resourceMap;
       
  1162     }
       
  1163 }
       
  1164 
       
  1165 void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
       
  1166 {
       
  1167     if (!enabled())
       
  1168         return;
       
  1169 
       
  1170     InspectorResource* resource = new InspectorResource(m_nextIdentifier--, loader, loader->frame());
       
  1171     resource->finished = true;
       
  1172 
       
  1173     updateResourceRequest(resource, request);
       
  1174     updateResourceResponse(resource, response);
       
  1175 
       
  1176     resource->length = length;
       
  1177     resource->cached = true;
       
  1178     resource->startTime = currentTime();
       
  1179     resource->responseReceivedTime = resource->startTime;
       
  1180     resource->endTime = resource->startTime;
       
  1181 
       
  1182     if (loader->frame() == m_inspectedPage->mainFrame() && request.url() == loader->requestURL())
       
  1183         m_mainResource = resource;
       
  1184 
       
  1185     addResource(resource);
       
  1186 
       
  1187     if (windowVisible())
       
  1188         addAndUpdateScriptResource(resource);
       
  1189 }
       
  1190 
       
  1191 void InspectorController::identifierForInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
       
  1192 {
       
  1193     if (!enabled())
       
  1194         return;
       
  1195 
       
  1196     InspectorResource* resource = new InspectorResource(identifier, loader, loader->frame());
       
  1197 
       
  1198     updateResourceRequest(resource, request);
       
  1199 
       
  1200     if (loader->frame() == m_inspectedPage->mainFrame() && request.url() == loader->requestURL())
       
  1201         m_mainResource = resource;
       
  1202 
       
  1203     addResource(resource);
       
  1204 }
       
  1205 
       
  1206 void InspectorController::willSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
       
  1207 {
       
  1208     if (!enabled())
       
  1209         return;
       
  1210 
       
  1211     InspectorResource* resource = m_resources.get(identifier).get();
       
  1212     if (!resource)
       
  1213         return;
       
  1214 
       
  1215     resource->startTime = currentTime();
       
  1216 
       
  1217     if (!redirectResponse.isNull()) {
       
  1218         updateResourceRequest(resource, request);
       
  1219         updateResourceResponse(resource, redirectResponse);
       
  1220     }
       
  1221 
       
  1222     if (resource != m_mainResource && windowVisible()) {
       
  1223         if (!resource->scriptObject)
       
  1224             addScriptResource(resource);
       
  1225         else
       
  1226             updateScriptResourceRequest(resource);
       
  1227 
       
  1228         updateScriptResource(resource, resource->startTime, resource->responseReceivedTime, resource->endTime);
       
  1229 
       
  1230         if (!redirectResponse.isNull())
       
  1231             updateScriptResourceResponse(resource);
       
  1232     }
       
  1233 }
       
  1234 
       
  1235 void InspectorController::didReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response)
       
  1236 {
       
  1237     if (!enabled())
       
  1238         return;
       
  1239 
       
  1240     InspectorResource* resource = m_resources.get(identifier).get();
       
  1241     if (!resource)
       
  1242         return;
       
  1243 
       
  1244     updateResourceResponse(resource, response);
       
  1245 
       
  1246     resource->responseReceivedTime = currentTime();
       
  1247 
       
  1248     if (windowVisible() && resource->scriptObject) {
       
  1249         updateScriptResourceResponse(resource);
       
  1250         updateScriptResource(resource, resource->startTime, resource->responseReceivedTime, resource->endTime);
       
  1251     }
       
  1252 }
       
  1253 
       
  1254 void InspectorController::didReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived)
       
  1255 {
       
  1256     if (!enabled())
       
  1257         return;
       
  1258 
       
  1259     InspectorResource* resource = m_resources.get(identifier).get();
       
  1260     if (!resource)
       
  1261         return;
       
  1262 
       
  1263     resource->length += lengthReceived;
       
  1264 
       
  1265     if (windowVisible() && resource->scriptObject)
       
  1266         updateScriptResource(resource, resource->length);
       
  1267 }
       
  1268 
       
  1269 void InspectorController::didFinishLoading(DocumentLoader* loader, unsigned long identifier)
       
  1270 {
       
  1271     if (!enabled())
       
  1272         return;
       
  1273 
       
  1274     RefPtr<InspectorResource> resource = m_resources.get(identifier);
       
  1275     if (!resource)
       
  1276         return;
       
  1277 
       
  1278     removeResource(resource.get());
       
  1279 
       
  1280     resource->finished = true;
       
  1281     resource->endTime = currentTime();
       
  1282 
       
  1283     addResource(resource.get());
       
  1284 
       
  1285     if (windowVisible() && resource->scriptObject) {
       
  1286         updateScriptResource(resource.get(), resource->startTime, resource->responseReceivedTime, resource->endTime);
       
  1287         updateScriptResource(resource.get(), resource->finished);
       
  1288     }
       
  1289 }
       
  1290 
       
  1291 void InspectorController::didFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& /*error*/)
       
  1292 {
       
  1293     if (!enabled())
       
  1294         return;
       
  1295 
       
  1296     RefPtr<InspectorResource> resource = m_resources.get(identifier);
       
  1297     if (!resource)
       
  1298         return;
       
  1299 
       
  1300     removeResource(resource.get());
       
  1301 
       
  1302     resource->finished = true;
       
  1303     resource->failed = true;
       
  1304     resource->endTime = currentTime();
       
  1305 
       
  1306     addResource(resource.get());
       
  1307 
       
  1308     if (windowVisible() && resource->scriptObject) {
       
  1309         updateScriptResource(resource.get(), resource->startTime, resource->responseReceivedTime, resource->endTime);
       
  1310         updateScriptResource(resource.get(), resource->finished, resource->failed);
       
  1311     }
       
  1312 }
       
  1313 
       
  1314 } // namespace WebCore