Skip to content
Permalink
Browse files
WKWebView evaluateJavaScript:completionHandler: should reuse its JSCo…
…ntext instance.

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

Reviewed by Anders Carlsson.

The core issue here is that we need to be able to deserialized an
API::SerializedScriptValue instance into an ObjC object graph.  We'll solve this
by introducing a API::SerializedScriptValue::deserialize() functions that does
the job.  The deserialize() function will will use a SharedJSContext to provide
the needed JSContext for doing this work.

Also updated ScriptMessageHandlerDelegate::didPostMessage() to use this new
deserialize() function.

* Shared/API/APISerializedScriptValue.h:
(API::SerializedScriptValue::deserialize):
(API::SerializedScriptValue::internalRepresentation):
- Changed to return a WebCore::SerializedScriptValue*.  This makes it friendlier
  to use in the 2 places that need it.

* UIProcess/API/Cocoa/APISerializedScriptValueCocoa.mm: Added.
(API::SharedJSContext::SharedJSContext):
(API::SharedJSContext::ensureContext):
(API::SharedJSContext::releaseContext):
(API::SerializedScriptValue::deserialize):
* UIProcess/API/Cocoa/WKUserContentController.mm:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView evaluateJavaScript:completionHandler:]):
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewRunJavaScriptCallback):
- Removed a now unnecessary cast.
* WebKit2.xcodeproj/project.pbxproj:



Canonical link: https://commits.webkit.org/164641@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@186229 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Mark Lam committed Jul 2, 2015
1 parent 0b26df5 commit 4b4311a71be9330c8944d704de68482083f9ccbe
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 20 deletions.
@@ -1,3 +1,38 @@
2015-07-02 Mark Lam <mark.lam@apple.com>

WKWebView evaluateJavaScript:completionHandler: should reuse its JSContext instance.
https://bugs.webkit.org/show_bug.cgi?id=146416

Reviewed by Anders Carlsson.

The core issue here is that we need to be able to deserialized an
API::SerializedScriptValue instance into an ObjC object graph. We'll solve this
by introducing a API::SerializedScriptValue::deserialize() functions that does
the job. The deserialize() function will will use a SharedJSContext to provide
the needed JSContext for doing this work.

Also updated ScriptMessageHandlerDelegate::didPostMessage() to use this new
deserialize() function.

* Shared/API/APISerializedScriptValue.h:
(API::SerializedScriptValue::deserialize):
(API::SerializedScriptValue::internalRepresentation):
- Changed to return a WebCore::SerializedScriptValue*. This makes it friendlier
to use in the 2 places that need it.

* UIProcess/API/Cocoa/APISerializedScriptValueCocoa.mm: Added.
(API::SharedJSContext::SharedJSContext):
(API::SharedJSContext::ensureContext):
(API::SharedJSContext::releaseContext):
(API::SerializedScriptValue::deserialize):
* UIProcess/API/Cocoa/WKUserContentController.mm:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView evaluateJavaScript:completionHandler:]):
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewRunJavaScriptCallback):
- Removed a now unnecessary cast.
* WebKit2.xcodeproj/project.pbxproj:

2015-07-02 Dan Bernstein <mitz@apple.com>

<rdar://problem/21429613> [iOS] Stop making symlinks from PrivateFrameworks to Frameworks
@@ -58,10 +58,14 @@ class SerializedScriptValue : public API::ObjectImpl<API::Object::Type::Serializ
{
return m_serializedScriptValue->deserialize(context, exception);
}

#if PLATFORM(COCOA) && defined(__OBJC__)
static id deserialize(WebCore::SerializedScriptValue&, JSValueRef* exception);
#endif

IPC::DataReference dataReference() const { return m_serializedScriptValue->data(); }

void* internalRepresentation() { return m_serializedScriptValue.get(); }
WebCore::SerializedScriptValue* internalRepresentation() { return m_serializedScriptValue.get(); }

private:
explicit SerializedScriptValue(PassRefPtr<WebCore::SerializedScriptValue> serializedScriptValue)
@@ -0,0 +1,76 @@
/*
* Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "config.h"
#include "APISerializedScriptValue.h"

#import <JavaScriptCore/JSContext.h>
#import <JavaScriptCore/JSValue.h>
#import <wtf/NeverDestroyed.h>
#import <wtf/RunLoop.h>

namespace API {

class SharedJSContext {
public:
SharedJSContext()
: m_timer(RunLoop::main(), this, &SharedJSContext::releaseContext)
{
}

JSContext* ensureContext()
{
if (!m_context) {
m_context = adoptNS([[JSContext alloc] init]);
m_timer.startOneShot(1);
}
return m_context.get();
}

void releaseContext()
{
m_context.clear();
}

private:
RetainPtr<JSContext> m_context;
RunLoop::Timer<SharedJSContext> m_timer;
};

id SerializedScriptValue::deserialize(WebCore::SerializedScriptValue& serializedScriptValue, JSValueRef* exception)
{
ASSERT(RunLoop::isMain());
static NeverDestroyed<SharedJSContext> sharedContext;
JSContext* context = sharedContext.get().ensureContext();

JSValueRef valueRef = serializedScriptValue.deserialize([context JSGlobalContextRef], exception);
if (!valueRef)
return nil;

JSValue *value = [JSValue valueWithJSValueRef:valueRef inContext:context];
return value.toObject;
}

} // API
@@ -28,6 +28,7 @@

#if WK_API_ENABLED

#import "APISerializedScriptValue.h"
#import "SecurityOriginData.h"
#import "WKFrameInfoInternal.h"
#import "WKNSArray.h"
@@ -38,10 +39,7 @@
#import "WebScriptMessageHandler.h"
#import "WebUserContentControllerProxy.h"
#import "_WKUserContentFilterInternal.h"
#import <JavaScriptCore/JSContext.h>
#import <JavaScriptCore/JSValue.h>
#import <WebCore/SerializedScriptValue.h>
#import <wtf/MainThread.h>

@implementation WKUserContentController

@@ -90,14 +88,7 @@ virtual void didPostMessage(WebKit::WebPageProxy& page, WebKit::WebFrameProxy& f
{
@autoreleasepool {
RetainPtr<WKFrameInfo> frameInfo = wrapper(API::FrameInfo::create(frame, securityOriginData.securityOrigin()));

ASSERT(isUIThread());
static JSContext* context = [[JSContext alloc] init];

JSValueRef valueRef = serializedScriptValue.deserialize([context JSGlobalContextRef], 0);
JSValue *value = [JSValue valueWithJSValueRef:valueRef inContext:context];
id body = value.toObject;

id body = API::SerializedScriptValue::deserialize(serializedScriptValue, 0);
auto message = adoptNS([[WKScriptMessage alloc] _initWithBody:body webView:fromWebPageProxy(page) frameInfo:frameInfo.get() name:m_name.get()]);

[m_handler userContentController:m_controller.get() didReceiveScriptMessage:message.get()];
@@ -76,8 +76,6 @@
#import "_WKRemoteObjectRegistryInternal.h"
#import "_WKSessionStateInternal.h"
#import "_WKVisitedLinkProviderInternal.h"
#import <JavaScriptCore/JSContext.h>
#import <JavaScriptCore/JSValue.h>
#import <WebCore/IOSurface.h>
#import <wtf/HashMap.h>
#import <wtf/MathExtras.h>
@@ -637,11 +635,8 @@ - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void
return;
}

auto context = adoptNS([[JSContext alloc] init]);
JSValueRef valueRef = serializedScriptValue->deserialize([context JSGlobalContextRef], 0);
JSValue *value = [JSValue valueWithJSValueRef:valueRef inContext:context.get()];

rawHandler([value toObject], nil);
id body = API::SerializedScriptValue::deserialize(*serializedScriptValue->internalRepresentation(), 0);
rawHandler(body, nil);
});
}

@@ -2986,7 +2986,7 @@ static void webkitWebViewRunJavaScriptCallback(API::SerializedScriptValue* wkSer

WebKitWebView* webView = WEBKIT_WEB_VIEW(g_task_get_source_object(task));
g_task_return_pointer(task, webkitJavascriptResultCreate(webView,
*static_cast<WebCore::SerializedScriptValue*>(wkSerializedScriptValue->internalRepresentation())),
*wkSerializedScriptValue->internalRepresentation()),
reinterpret_cast<GDestroyNotify>(webkit_javascript_result_unref));
}

@@ -1790,6 +1790,7 @@
F6A25FDD12ADC6CC00DC40CC /* WebDatabaseManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A25FDB12ADC6CC00DC40CC /* WebDatabaseManager.h */; };
F6A90813133C20510082C3F4 /* WebCookieManagerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6A90811133C1F3D0082C3F4 /* WebCookieManagerMac.mm */; };
F6D632BC133D198200743D77 /* WebCookieManagerProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6D632BA133D181B00743D77 /* WebCookieManagerProxyMac.mm */; };
FED3C1DC1B447EAC00E0EB7F /* APISerializedScriptValueCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = FED3C1DA1B447AE800E0EB7F /* APISerializedScriptValueCocoa.mm */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
@@ -4023,6 +4024,7 @@
F6A25FDB12ADC6CC00DC40CC /* WebDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebDatabaseManager.h; sourceTree = "<group>"; };
F6A90811133C1F3D0082C3F4 /* WebCookieManagerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCookieManagerMac.mm; sourceTree = "<group>"; };
F6D632BA133D181B00743D77 /* WebCookieManagerProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCookieManagerProxyMac.mm; sourceTree = "<group>"; };
FED3C1DA1B447AE800E0EB7F /* APISerializedScriptValueCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = APISerializedScriptValueCocoa.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
@@ -5309,6 +5311,7 @@
1A81B37F18BD66AD0007FDAC /* _WKVisitedLinkProvider.h */,
1A81B37E18BD66AD0007FDAC /* _WKVisitedLinkProvider.mm */,
1A81B38418BD673A0007FDAC /* _WKVisitedLinkProviderInternal.h */,
FED3C1DA1B447AE800E0EB7F /* APISerializedScriptValueCocoa.mm */,
7CEFA9601AC0999300B910FD /* APIUserContentExtensionStoreCocoa.mm */,
1A3635AB1A3145E500ED6197 /* APIWebsiteDataStoreCocoa.mm */,
1AFDE64319510B5500C48FFA /* LegacyBundleForClass.mm */,
@@ -9641,6 +9644,7 @@
296BD85E15019BC30071F424 /* StringUtilities.mm in Sources */,
1ZZ417EF12C00D87002BE67B /* TextCheckerCompletion.cpp in Sources */,
2DA944AD1884E9BA00ED86DB /* TextCheckerIOS.mm in Sources */,
FED3C1DC1B447EAC00E0EB7F /* APISerializedScriptValueCocoa.mm in Sources */,
1AA417EF12C00D87002BE67B /* TextCheckerMac.mm in Sources */,
1AAF263814687C39004A1E8A /* TiledCoreAnimationDrawingArea.mm in Sources */,
1AF05D8614688348008B1E81 /* TiledCoreAnimationDrawingAreaProxy.mm in Sources */,

0 comments on commit 4b4311a

Please sign in to comment.