Cherry-pick WebKit change 54972 to merge DOMWindow and WorkerContext object wrapping in V8 bindings

The motivation for this change is to disable workers on Android, because V8 on
Android does not have the required locking.

The current version of WebKit in Android (54731) uses workers features without
ENABLE(WORKERS) guards in the V8 bindings. In particular,
V8DOMWrapper::instantiateV8ObjectInWorkerContext is used from generated code
without guards.

Fixing the code generator would be difficult and would be wasted effort as
V8DOMWrapper::instantiateV8ObjectInWorkerContext no longer exists in tip-of-tree
WebKit. Instead, we cherry-pick the WebKit change which removes this method.

See http://trac.webkit.org/changeset/54972

Change-Id: Ie6365073d7a4d92aa7c1553d87a7e1c1ed514118
diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm
index 2b89b54..ee51ec3 100644
--- a/WebCore/bindings/scripts/CodeGeneratorV8.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm
@@ -1949,12 +1949,8 @@
 
 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput}) {
   v8::Handle<v8::Object> wrapper;
-END
-    if (!MayBeInWorkerContext($dataNode, $interfaceName)) {
-        push(@implContent, <<END);
   V8Proxy* proxy = 0;
 END
-    }
 
     if (IsNodeSubType($dataNode)) {
         push(@implContent, <<END);
@@ -1993,15 +1989,9 @@
 END
     }
 
-    if (MayBeInWorkerContext($dataNode, $interfaceName)) {
-        push(@implContent, <<END);
-  wrapper = V8DOMWrapper::instantiateV8ObjectInWorkerContext(${wrapperType}, impl);
-END
-    } else {
-        push(@implContent, <<END);
+    push(@implContent, <<END);
   wrapper = V8DOMWrapper::instantiateV8Object(proxy, ${wrapperType}, impl);
 END
-    }
 
     if (IsNodeSubType($dataNode)) {
         push(@implContent, <<END);
@@ -2049,35 +2039,6 @@
     }
 }
 
-sub MayBeInWorkerContext {
-    # These objects can be constructed under WorkerContextExecutionProxy. They need special
-    # handling, since if we call V8Proxy::retrieve(), we will crash.
-    # FIXME: websocket?
-    my $dataNode = shift;
-    my $interfaceName = shift;
-    # FIXME: Doing the extra work to handle the WorkerContext case for all Event
-    # types is sad. We can probably be cleverer and only do the extra work for certain types.
-    return 1 if IsEventSubType($dataNode);
-    return 1 if $interfaceName eq "DOMCoreException";
-    return 1 if $interfaceName eq "EventException";
-    return 1 if $interfaceName eq "RangeException";
-    return 1 if $interfaceName eq "XMLHttpRequestException";
-    return 1 if $interfaceName eq "MessagePort";
-    return 1 if $interfaceName eq "DedicatedWorkerContext";
-    return 1 if $interfaceName eq "WorkerContext";
-    return 1 if $interfaceName eq "SharedWorkerContext";
-    return 1 if $interfaceName eq "WorkerLocation";
-    return 1 if $interfaceName eq "WorkerNavigator";
-    return 1 if $interfaceName eq "Notification";
-    return 1 if $interfaceName eq "NotificationCenter";
-    return 1 if $interfaceName eq "XMLHttpRequest";
-    return 1 if $interfaceName eq "WebSocket";
-    return 1 if $interfaceName eq "Worker";
-    return 1 if $interfaceName eq "SharedWorker";
-    return 1 if $interfaceName eq "EventSource";
-    return 0;
-}
-
 sub HasCustomToV8Implementation {
     # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)?
     $dataNode = shift;
diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp
index 1605417..184c643 100644
--- a/WebCore/bindings/v8/V8DOMWrapper.cpp
+++ b/WebCore/bindings/v8/V8DOMWrapper.cpp
@@ -61,6 +61,7 @@
 #include "V8Proxy.h"
 #include "V8SVGElementInstance.h"
 #include "V8SharedWorker.h"
+#include "V8SharedWorkerContext.h"
 #include "V8StyleSheet.h"
 #include "V8WebSocket.h"
 #include "V8Worker.h"
@@ -267,36 +268,49 @@
     return NodeFilter::create(condition);
 }
 
-v8::Local<v8::Object> V8DOMWrapper::instantiateV8ObjectInWorkerContext(V8ClassIndex::V8WrapperType type, void* impl)
+static bool globalObjectPrototypeIsDOMWindow(v8::Handle<v8::Object> objectPrototype)
 {
-    WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
-    if (!workerContextProxy)
-        return instantiateV8Object(0, type, impl);
-    v8::Local<v8::Object> instance = SafeAllocation::newInstance(getConstructor(type, workerContextProxy->workerContext()));
-    if (!instance.IsEmpty()) {
-        // Avoid setting the DOM wrapper for failed allocations.
-        setDOMWrapper(instance, V8ClassIndex::ToInt(type), impl);
-    }
-    return instance;
+    // We can identify what type of context the global object is wrapping by looking at the
+    // internal field count of its prototype. This assumes WorkerContexts and DOMWindows have different numbers
+    // of internal fields, so a COMPILE_ASSERT is included to warn if this ever changes. DOMWindow has
+    // traditionally had far more internal fields than any other class.
+    COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8WorkerContext::internalFieldCount && V8DOMWindow::internalFieldCount != V8SharedWorkerContext::internalFieldCount,
+        DOMWindowAndWorkerContextHaveUnequalFieldCounts);
+    return objectPrototype->InternalFieldCount() == V8DOMWindow::internalFieldCount;
 }
 
 v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType type, void* impl)
 {
+    WorkerContext* workerContext = 0;
     if (V8IsolatedContext::getEntered()) {
         // This effectively disables the wrapper cache for isolated worlds.
         proxy = 0;
         // FIXME: Do we need a wrapper cache for the isolated world?  We should
         //        see if the performance gains are worth while.
         // We'll get one once we give the isolated context a proper window shell.
-    } else if (!proxy)
-        proxy = V8Proxy::retrieve();
+    } else if (!proxy) {
+        v8::Handle<v8::Context> context = v8::Context::GetCurrent();
+        if (!context.IsEmpty()) {
+            v8::Handle<v8::Object> globalPrototype = v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype());
+            if (globalObjectPrototypeIsDOMWindow(globalPrototype))
+                proxy = V8Proxy::retrieve(V8DOMWindow::toNative(globalPrototype)->frame());
+            else
+                workerContext = V8WorkerContext::toNative(globalPrototype);
+        }
+    }
 
     v8::Local<v8::Object> instance;
     if (proxy)
         // FIXME: Fix this to work properly with isolated worlds (see above).
         instance = proxy->windowShell()->createWrapperFromCache(type);
-    else
-        instance = SafeAllocation::newInstance(V8ClassIndex::getTemplate(type)->GetFunction());
+    else {
+        v8::Local<v8::Function> function;
+        if (workerContext)
+            function = getConstructor(type, workerContext);
+        else
+            function = V8ClassIndex::getTemplate(type)->GetFunction();
+        instance = SafeAllocation::newInstance(function);
+    }
     if (!instance.IsEmpty()) {
         // Avoid setting the DOM wrapper for failed allocations.
         setDOMWrapper(instance, V8ClassIndex::ToInt(type), impl);
diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h
index 78e9ae2..afac577 100644
--- a/WebCore/bindings/v8/V8DOMWrapper.h
+++ b/WebCore/bindings/v8/V8DOMWrapper.h
@@ -192,7 +192,6 @@
         static void setHiddenWindowReference(Frame*, const int internalIndex, v8::Handle<v8::Object>);
 
         static v8::Local<v8::Object> instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType type, void* impl);
-        static v8::Local<v8::Object> instantiateV8ObjectInWorkerContext(V8ClassIndex::V8WrapperType type, void* impl);
 
         static v8::Handle<v8::Object> getWrapper(Node*);
     };