Changeset 144522 in webkit


Ignore:
Timestamp:
Mar 1, 2013 6:35:53 PM (11 years ago)
Author:
commit-queue@webkit.org
Message:

Don't leak Documents when using MutationObserver from extensions
https://bugs.webkit.org/show_bug.cgi?id=111234

Patch by Elliott Sprehn <Elliott Sprehn> on 2013-03-01
Reviewed by Adam Barth.

.:

  • ManualTests/leak-observer-nonmain-world.html: Added.

Source/WebCore:

MutationObserverCallback holds a WorldContextHandle which secretly isn't
a handle to anything when it's for the main world. When it's for a non-main
world though, like those used in extensions, it becomes a strong reference
to the v8::Context which results in leaks by creating cycles:

MutationObserver -> Callback -> World -> Document -> Node -> MutationObserver.

Instead we should keep a RefPtr to a DOMWrapperWorld in the callback and then
get the v8::Context from that inside handleEvent.

Tests: ManualTests/leak-observer-nonmain-world.html

  • bindings/v8/V8Binding.cpp:

(WebCore::toV8Context): Added overload that takes a DOMWrapperWorld.

  • bindings/v8/V8Binding.h:
  • bindings/v8/V8MutationCallback.cpp:

(WebCore::V8MutationCallback::V8MutationCallback):
(WebCore::V8MutationCallback::handleEvent):

  • bindings/v8/V8MutationCallback.h:

(V8MutationCallback):

Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r144222 r144522  
     12013-03-01  Elliott Sprehn  <esprehn@gmail.com>
     2
     3        Don't leak Documents when using MutationObserver from extensions
     4        https://bugs.webkit.org/show_bug.cgi?id=111234
     5
     6        Reviewed by Adam Barth.
     7
     8        * ManualTests/leak-observer-nonmain-world.html: Added.
     9
    1102013-02-27  Zan Dobersek  <zdobersek@igalia.com>
    211
  • trunk/Source/WebCore/ChangeLog

    r144520 r144522  
     12013-03-01  Elliott Sprehn  <esprehn@gmail.com>
     2
     3        Don't leak Documents when using MutationObserver from extensions
     4        https://bugs.webkit.org/show_bug.cgi?id=111234
     5
     6        Reviewed by Adam Barth.
     7
     8        MutationObserverCallback holds a WorldContextHandle which secretly isn't
     9        a handle to anything when it's for the main world. When it's for a non-main
     10        world though, like those used in extensions, it becomes a strong reference
     11        to the v8::Context which results in leaks by creating cycles:
     12
     13        MutationObserver -> Callback -> World -> Document -> Node -> MutationObserver.
     14
     15        Instead we should keep a RefPtr to a DOMWrapperWorld in the callback and then
     16        get the v8::Context from that inside handleEvent.
     17
     18        Tests: ManualTests/leak-observer-nonmain-world.html
     19
     20        * bindings/v8/V8Binding.cpp:
     21        (WebCore::toV8Context): Added overload that takes a DOMWrapperWorld.
     22        * bindings/v8/V8Binding.h:
     23        * bindings/v8/V8MutationCallback.cpp:
     24        (WebCore::V8MutationCallback::V8MutationCallback):
     25        (WebCore::V8MutationCallback::handleEvent):
     26        * bindings/v8/V8MutationCallback.h:
     27        (V8MutationCallback):
     28
    1292013-03-01  Bear Travis  <betravis@adobe.com>
    230
  • trunk/Source/WebCore/bindings/v8/V8Binding.cpp

    r142810 r144522  
    267267}
    268268
     269v8::Local<v8::Context> toV8Context(ScriptExecutionContext* context, DOMWrapperWorld* world)
     270{
     271    if (context->isDocument()) {
     272        if (Frame* frame = static_cast<Document*>(context)->frame()) {
     273            // FIXME: Store the DOMWrapperWorld for the main world in the v8::Context so callers
     274            // that are looking up their world with DOMWrapperWorld::getWorld(v8::Context::GetCurrent())
     275            // won't end up passing null here when later trying to get their v8::Context back.
     276            if (!world)
     277                return frame->script()->mainWorldContext();
     278            return v8::Local<v8::Context>::New(frame->script()->windowShell(world)->context());
     279        }
     280#if ENABLE(WORKERS)
     281    } else if (context->isWorkerContext()) {
     282        if (WorkerScriptController* script = static_cast<WorkerContext*>(context)->script())
     283            return script->context();
     284#endif
     285    }
     286    return v8::Local<v8::Context>();
     287}
     288
    269289bool handleOutOfMemory()
    270290{
  • trunk/Source/WebCore/bindings/v8/V8Binding.h

    r144381 r144522  
    446446    // Returns the context associated with a ScriptExecutionContext.
    447447    v8::Local<v8::Context> toV8Context(ScriptExecutionContext*, const WorldContextHandle&);
     448    v8::Local<v8::Context> toV8Context(ScriptExecutionContext*, DOMWrapperWorld*);
    448449
    449450    // Returns the frame object of the window object associated with
  • trunk/Source/WebCore/bindings/v8/V8MutationCallback.cpp

    r141771 r144522  
    3939    : ActiveDOMCallback(context)
    4040    , m_callback(callback)
    41     , m_worldContext(UseCurrentWorld)
     41    , m_world(DOMWrapperWorld::getWorld(v8::Context::GetCurrent()))
    4242{
    4343    owner->SetHiddenValue(V8HiddenPropertyName::callback(), callback);
     
    5656    v8::HandleScope handleScope;
    5757
    58     v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);
     58    v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_world.get());
    5959    if (v8Context.IsEmpty())
    6060        return true;
  • trunk/Source/WebCore/bindings/v8/V8MutationCallback.h

    r141771 r144522  
    2828
    2929#include "ActiveDOMCallback.h"
     30#include "DOMWrapperWorld.h"
    3031#include "MutationCallback.h"
    3132#include "ScopedPersistent.h"
    32 #include "WorldContextHandle.h"
    3333#include <v8.h>
     34#include <wtf/RefPtr.h>
    3435
    3536namespace WebCore {
     
    5960
    6061    ScopedPersistent<v8::Object> m_callback;
    61     WorldContextHandle m_worldContext;
     62    RefPtr<DOMWrapperWorld> m_world;
    6263};
    6364
Note: See TracChangeset for help on using the changeset viewer.