Changeset 56708 in webkit


Ignore:
Timestamp:
Mar 29, 2010 12:34:38 AM (14 years ago)
Author:
yurys@chromium.org
Message:

2010-03-29 Yury Semikhatsky <yurys@chromium.org>

Reviewed by Pavel Feldman.

Protect global object from being GC'ed if there are messages written to console from the iframe with that global object.

Whent serializing objects in the injected script check that global object properties are still defined before using them as arguments. The may become undefined if owning frame navigated to a different domain.

https://bugs.webkit.org/show_bug.cgi?id=36612

Test: http/tests/inspector-enabled/console-log-before-frame-navigation.html

  • bindings/js/ScriptState.h: (WebCore::ScriptStateProtectedPtr::ScriptStateProtectedPtr): (WebCore::ScriptStateProtectedPtr::get):
  • bindings/v8/ScriptState.h: (WebCore::ScriptStateProtectedPtr::ScriptStateProtectedPtr): (WebCore::ScriptStateProtectedPtr::~ScriptStateProtectedPtr): (WebCore::ScriptStateProtectedPtr::get):
  • inspector/ConsoleMessage.cpp: (WebCore::ConsoleMessage::addToFrontend):
  • inspector/ConsoleMessage.h:
  • inspector/front-end/InjectedScript.js: (injectedScriptConstructor): (injectedScriptConstructor.):

2010-03-29 Yury Semikhatsky <yurys@chromium.org>

Reviewed by Pavel Feldman.

Web Inspector: don't crash when there are messages in console from previous iframe content.

https://bugs.webkit.org/show_bug.cgi?id=36612

  • http/tests/inspector-enabled/console-log-before-frame-navigation-expected.txt: Added.
  • http/tests/inspector-enabled/console-log-before-frame-navigation.html: Added.
  • http/tests/inspector-enabled/resources/console-log-before-frame-navigation.js: Added. (doit.callback): (doit): (receiveMessage): (frontend_dumpConsoleMessages):
  • http/tests/inspector-enabled/resources/console-log-frame-after-navigation.html: Added.
  • http/tests/inspector-enabled/resources/console-log-frame-before-navigation.html: Added.
Location:
trunk
Files:
7 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r56703 r56708  
     12010-03-29  Yury Semikhatsky  <yurys@chromium.org>
     2
     3        Reviewed by Pavel Feldman.
     4
     5        Web Inspector: don't crash when there are messages in console from previous iframe content.
     6
     7        https://bugs.webkit.org/show_bug.cgi?id=36612
     8
     9        * http/tests/inspector-enabled/console-log-before-frame-navigation-expected.txt: Added.
     10        * http/tests/inspector-enabled/console-log-before-frame-navigation.html: Added.
     11        * http/tests/inspector-enabled/resources/console-log-before-frame-navigation.js: Added.
     12        (doit.callback):
     13        (doit):
     14        (receiveMessage):
     15        (frontend_dumpConsoleMessages):
     16        * http/tests/inspector-enabled/resources/console-log-frame-after-navigation.html: Added.
     17        * http/tests/inspector-enabled/resources/console-log-frame-before-navigation.html: Added.
     18
    1192010-03-28  Gustavo Noronha Silva  <gns@gnome.org>
    220
  • trunk/WebCore/ChangeLog

    r56707 r56708  
     12010-03-29  Yury Semikhatsky  <yurys@chromium.org>
     2
     3        Reviewed by Pavel Feldman.
     4
     5        Protect global object from being GC'ed if there are messages written to console from the iframe with that global object.
     6
     7        Whent serializing objects in the injected script check that global object properties are still defined before using them as arguments. The may become undefined if owning frame navigated to a different domain.
     8
     9        https://bugs.webkit.org/show_bug.cgi?id=36612
     10
     11        Test: http/tests/inspector-enabled/console-log-before-frame-navigation.html
     12
     13        * bindings/js/ScriptState.h:
     14        (WebCore::ScriptStateProtectedPtr::ScriptStateProtectedPtr):
     15        (WebCore::ScriptStateProtectedPtr::get):
     16        * bindings/v8/ScriptState.h:
     17        (WebCore::ScriptStateProtectedPtr::ScriptStateProtectedPtr):
     18        (WebCore::ScriptStateProtectedPtr::~ScriptStateProtectedPtr):
     19        (WebCore::ScriptStateProtectedPtr::get):
     20        * inspector/ConsoleMessage.cpp:
     21        (WebCore::ConsoleMessage::addToFrontend):
     22        * inspector/ConsoleMessage.h:
     23        * inspector/front-end/InjectedScript.js:
     24        (injectedScriptConstructor):
     25        (injectedScriptConstructor.):
     26
    1272010-03-26  Philippe Normand  <pnormand@igalia.com>
    228
  • trunk/WebCore/bindings/js/ScriptState.h

    r54051 r56708  
    3434
    3535#include "JSDOMBinding.h"
     36#include <runtime/Protect.h>
     37#include <wtf/Noncopyable.h>
    3638
    3739namespace WebCore {
    38     class DOMWrapperWorld;
    39     class Frame;
    40     class Node;
    41     class Page;
     40class DOMWrapperWorld;
     41class Frame;
     42class Node;
     43class Page;
    4244
    43     // The idea is to expose "state-like" methods (hadException, and any other
    44     // methods where ExecState just dips into globalData) of JSC::ExecState as a
    45     // separate abstraction.
    46     // For now, the separation is purely by convention.
    47     typedef JSC::ExecState ScriptState;
     45// The idea is to expose "state-like" methods (hadException, and any other
     46// methods where ExecState just dips into globalData) of JSC::ExecState as a
     47// separate abstraction.
     48// For now, the separation is purely by convention.
     49typedef JSC::ExecState ScriptState;
    4850
    49     ScriptState* mainWorldScriptState(Frame*);
     51class ScriptStateProtectedPtr : public Noncopyable {
     52public:
     53    ScriptStateProtectedPtr() { }
     54    ScriptStateProtectedPtr(ScriptState* scriptState) : m_globalObject(scriptState->lexicalGlobalObject()) { }
     55    ScriptState* get()
     56    {
     57        if (m_globalObject)
     58            return m_globalObject->globalExec();
     59        return 0;
     60    }
     61private:
     62    JSC::ProtectedPtr<JSC::JSGlobalObject> m_globalObject;
     63};
    5064
    51     ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*);
    52     ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*);
     65ScriptState* mainWorldScriptState(Frame*);
     66
     67ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*);
     68ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*);
    5369
    5470} // namespace WebCore
  • trunk/WebCore/bindings/v8/ScriptState.h

    r54421 r56708  
    3838
    3939namespace WebCore {
    40     class DOMWrapperWorld;
    41     class Frame;
    42     class Node;
    43     class Page;
     40class DOMWrapperWorld;
     41class Frame;
     42class Node;
     43class Page;
    4444
    45     class ScriptState : public Noncopyable {
    46     public:
    47         bool hadException() { return !m_exception.IsEmpty(); }
    48         void setException(v8::Local<v8::Value> exception)
    49         {
    50             m_exception = exception;
     45class ScriptState : public Noncopyable {
     46public:
     47    bool hadException() { return !m_exception.IsEmpty(); }
     48    void setException(v8::Local<v8::Value> exception)
     49    {
     50        m_exception = exception;
     51    }
     52    v8::Local<v8::Value> exception() { return m_exception; }
     53
     54    v8::Local<v8::Context> context() const
     55    {
     56        return v8::Local<v8::Context>::New(m_context);
     57    }
     58
     59    static ScriptState* forContext(v8::Local<v8::Context>);
     60    static ScriptState* current();
     61
     62protected:
     63    ScriptState() { }
     64    ~ScriptState();
     65
     66private:
     67    friend ScriptState* mainWorldScriptState(Frame*);
     68    explicit ScriptState(v8::Handle<v8::Context>);
     69
     70    static void weakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter);
     71
     72    v8::Local<v8::Value> m_exception;
     73    v8::Persistent<v8::Context> m_context;
     74};
     75
     76class EmptyScriptState : public ScriptState {
     77public:
     78    EmptyScriptState() : ScriptState() { }
     79    ~EmptyScriptState() { }
     80};
     81
     82class ScriptStateProtectedPtr : public Noncopyable {
     83public:
     84    ScriptStateProtectedPtr() : m_scriptState(0) { }
     85    ScriptStateProtectedPtr(ScriptState* scriptState) : m_scriptState(scriptState)
     86    {
     87        v8::HandleScope handleScope;
     88        // Keep the context from being GC'ed. ScriptState is guaranteed to be live while the context is live.
     89        m_context = v8::Persistent<v8::Context>::New(scriptState->context());
     90    }
     91    ~ScriptStateProtectedPtr()
     92    {
     93        if (!m_context.IsEmpty()) {
     94            m_context.Dispose();
     95            m_context.Clear();
    5196        }
    52         v8::Local<v8::Value> exception() { return m_exception; }
     97    }
     98    ScriptState* get() { return m_scriptState; }
     99private:
     100    ScriptState* m_scriptState;
     101    v8::Persistent<v8::Context> m_context;
     102};
    53103
    54         v8::Local<v8::Context> context() const
    55         {
    56             return v8::Local<v8::Context>::New(m_context);
    57         }
     104ScriptState* mainWorldScriptState(Frame*);
    58105
    59         static ScriptState* forContext(v8::Local<v8::Context>);
    60         static ScriptState* current();
     106ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*);
     107ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*);
    61108
    62     protected:
    63         ScriptState() { }
    64         ~ScriptState();
    65 
    66     private:
    67         friend ScriptState* mainWorldScriptState(Frame*);
    68         explicit ScriptState(v8::Handle<v8::Context>);
    69 
    70         static void weakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter);
    71 
    72         v8::Local<v8::Value> m_exception;
    73         v8::Persistent<v8::Context> m_context;
    74     };
    75 
    76     class EmptyScriptState : public ScriptState {
    77     public:
    78         EmptyScriptState() : ScriptState() { }
    79         ~EmptyScriptState() { }
    80     };
    81 
    82     ScriptState* mainWorldScriptState(Frame*);
    83 
    84     ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*);
    85     ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*);
    86 
    87     inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); }
    88     inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); }
     109inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); }
     110inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); }
    89111
    90112}
  • trunk/WebCore/inspector/ConsoleMessage.cpp

    r56051 r56708  
    9696    Vector<RefPtr<SerializedScriptValue> > arguments;
    9797    if (!m_arguments.isEmpty()) {
    98         InjectedScript injectedScript = injectedScriptHost->injectedScriptFor(m_scriptState);
     98        InjectedScript injectedScript = injectedScriptHost->injectedScriptFor(m_scriptState.get());
    9999        for (unsigned i = 0; i < m_arguments.size(); ++i) {
    100100            RefPtr<SerializedScriptValue> serializedValue = injectedScript.wrapForConsole(m_arguments[i]);
  • trunk/WebCore/inspector/ConsoleMessage.h

    r56051 r56708  
    6666#if ENABLE(INSPECTOR)
    6767    Vector<ScriptValue> m_arguments;
    68     ScriptState* m_scriptState;
     68    ScriptStateProtectedPtr m_scriptState;
    6969#endif
    7070    Vector<ScriptString> m_frames;
  • trunk/WebCore/inspector/front-end/InjectedScript.js

    r56676 r56708  
    8686    var result = InjectedScript[methodName].apply(InjectedScript, argsArray);
    8787    if (typeof result === "undefined") {
    88         InjectedScript._window().console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName);
     88        inspectedWindow.console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName);
    8989        result = null;
    9090    }
     
    167167        // not call frame while on a breakpoint.
    168168        // TODO: bring evaluation against call frame back.
    169         var result = InjectedScript._window().eval("(" + expression + ")");
     169        var result = inspectedWindow.eval("(" + expression + ")");
    170170        // Store the result in the property.
    171171        object[propertyName] = result;
     
    173173    } catch(e) {
    174174        try {
    175             var result = InjectedScript._window().eval("\"" + InjectedScript._escapeCharacters(expression, "\"") + "\"");
     175            var result = inspectedWindow.eval("\"" + InjectedScript._escapeCharacters(expression, "\"") + "\"");
    176176            object[propertyName] = result;
    177177            return true;
     
    245245            if (!expression)
    246246                expression = "this";
    247             expressionResult = InjectedScript._evaluateOn(InjectedScript._window().eval, InjectedScript._window(), expression);
     247            expressionResult = InjectedScript._evaluateOn(inspectedWindow.eval, inspectedWindow, expression);
    248248        }
    249249        if (typeof expressionResult == "object")
    250250            InjectedScript._populatePropertyNames(expressionResult, props);
    251251        if (includeInspectorCommandLineAPI)
    252             for (var prop in InjectedScript._window().console._inspectorCommandLineAPI)
     252            for (var prop in inspectedWindow.console._inspectorCommandLineAPI)
    253253                if (prop.charAt(0) !== '_')
    254254                    props[prop] = true;
     
    260260InjectedScript.evaluate = function(expression, objectGroup)
    261261{
    262     return InjectedScript._evaluateAndWrap(InjectedScript._window().eval, InjectedScript._window(), expression, objectGroup);
     262    return InjectedScript._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup);
    263263}
    264264
     
    304304        return false;
    305305
    306     InjectedScript._ensureCommandLineAPIInstalled(InjectedScript._window().eval, InjectedScript._window());
    307     var inspectedNodes = InjectedScript._window().console._inspectorCommandLineAPI._inspectedNodes;
     306    InjectedScript._ensureCommandLineAPIInstalled(inspectedWindow.eval, inspectedWindow);
     307    var inspectedNodes = inspectedWindow.console._inspectorCommandLineAPI._inspectedNodes;
    308308    inspectedNodes.unshift(node);
    309309    if (inspectedNodes.length >= 5)
     
    466466    }
    467467
    468     const mainFrameDocument = InjectedScript._window().document;
     468    const mainFrameDocument = inspectedWindow.document;
    469469    const searchDocuments = [mainFrameDocument];
    470470    var searchFunctions;
     
    562562    // Don't call window.open on wrapper - popup blocker mutes it.
    563563    // URIs should have no double quotes.
    564     InjectedScript._window().eval("window.open(\"" + url + "\")");
     564    inspectedWindow.eval("window.open(\"" + url + "\")");
    565565    return true;
    566566}
     
    724724}
    725725
    726 InjectedScript._window = function()
    727 {
    728     // TODO: replace with 'return window;' once this script is injected into
    729     // the page's context.
    730     return inspectedWindow;
    731 }
    732 
    733726InjectedScript._nodeForId = function(nodeId)
    734727{
     
    827820                foundLocalScope = true;
    828821                scopeObjectProxy.isLocal = true;
    829             } else if (foundLocalScope && scopeObject instanceof InjectedScript._window().Element)
     822            } else if (foundLocalScope && scopeObject instanceof inspectedWindow.Element)
    830823                scopeObjectProxy.isElement = true;
    831             else if (foundLocalScope && scopeObject instanceof InjectedScript._window().Document)
     824            else if (foundLocalScope && scopeObject instanceof inspectedWindow.Document)
    832825                scopeObjectProxy.isDocument = true;
    833826            else if (!foundLocalScope)
     
    894887        return "null";
    895888
    896     // FIXME(33716): typeof document.all is always 'undefined'.
    897     if (InjectedScript._isHTMLAllCollection(obj))
     889    var type = typeof obj;
     890    if (type !== "object" && type !== "function") {
     891        // FIXME(33716): typeof document.all is always 'undefined'.
     892        if (InjectedScript._isHTMLAllCollection(obj))
     893            return "array";
     894        return type;
     895    }
     896
     897    // If owning frame has navigated to somewhere else window properties will be undefined.
     898    // In this case just return result of the typeof.
     899    if (!inspectedWindow.document)
     900        return type;
     901
     902    if (obj instanceof inspectedWindow.Node)
     903        return (obj.nodeType === undefined ? type : "node");
     904    if (obj instanceof inspectedWindow.String)
     905        return "string";
     906    if (obj instanceof inspectedWindow.Array)
    898907        return "array";
    899 
    900     var type = typeof obj;
    901     if (type !== "object" && type !== "function")
    902         return type;
    903 
    904     var win = InjectedScript._window();
    905 
    906     if (obj instanceof win.Node)
    907         return (obj.nodeType === undefined ? type : "node");
    908     if (obj instanceof win.String)
    909         return "string";
    910     if (obj instanceof win.Array)
     908    if (obj instanceof inspectedWindow.Boolean)
     909        return "boolean";
     910    if (obj instanceof inspectedWindow.Number)
     911        return "number";
     912    if (obj instanceof inspectedWindow.Date)
     913        return "date";
     914    if (obj instanceof inspectedWindow.RegExp)
     915        return "regexp";
     916    if (obj instanceof inspectedWindow.NodeList)
    911917        return "array";
    912     if (obj instanceof win.Boolean)
    913         return "boolean";
    914     if (obj instanceof win.Number)
    915         return "number";
    916     if (obj instanceof win.Date)
    917         return "date";
    918     if (obj instanceof win.RegExp)
    919         return "regexp";
    920     if (obj instanceof win.NodeList)
     918    if (obj instanceof inspectedWindow.HTMLCollection)
    921919        return "array";
    922     if (obj instanceof win.HTMLCollection)
    923         return "array";
    924     if (obj instanceof win.Error)
     920    if (obj instanceof inspectedWindow.Error)
    925921        return "error";
    926922    return type;
     
    944940        return "\"" + obj + "\"";
    945941    case "function":
    946         var objectText = String(obj);
     942        var objectText = InjectedScript._toString(obj);
    947943        if (!/^function /.test(objectText))
    948944            objectText = (type2 == "object") ? type1 : type2;
     
    951947        return objectText;
    952948    default:
    953         return String(obj);
    954     }
     949        return InjectedScript._toString(obj);
     950    }
     951}
     952
     953InjectedScript._toString = function(obj)
     954{
     955    // We don't use String(obj) because inspectedWindow.String is undefined if owning frame navigated to another page.
     956    return "" + obj;
    955957}
    956958
    957959InjectedScript._className = function(obj)
    958960{
    959     return Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1")
     961    var str = inspectedWindow.Object ? inspectedWindow.Object.prototype.toString.call(obj) : InjectedScript._toString(obj);
     962    return str.replace(/^\[object (.*)\]$/i, "$1");
    960963}
    961964
Note: See TracChangeset for help on using the changeset viewer.