| /* |
| * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``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 ITS 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. |
| */ |
| |
| #import "config.h" |
| #import "PlatformUtilities.h" |
| #import <JavaScriptCore/JSExport.h> |
| #import <JavaScriptCore/JSContext.h> |
| #import <WebKit/WebFrameLoadDelegatePrivate.h> |
| #import <WebKit/WebViewPrivate.h> |
| #import <wtf/RetainPtr.h> |
| |
| #if JSC_OBJC_API_ENABLED |
| |
| @class MyConsole; |
| |
| static bool didFinishLoad = false; |
| static bool didCompleteTestSuccessfully = false; |
| static bool didCallWindowCallback = false; |
| static bool didFindMyCustomProperty = false; |
| static bool didInsertMyCustomProperty = true; |
| static bool didReportException = false; |
| |
| @protocol MyConsole<JSExport> |
| - (void)log:(NSString *)s; |
| - (void)printHelloWorld; |
| - (int)add:(int)a to:(int)b; |
| @end |
| |
| @interface MyConsole : NSObject<MyConsole> |
| @end |
| |
| @implementation MyConsole |
| - (void)log:(NSString *)s |
| { |
| NSLog(@"%@", s); |
| } |
| |
| - (void)printHelloWorld |
| { |
| NSLog(@"Hello, World!"); |
| } |
| |
| - (int)add:(int)a to:(int)b |
| { |
| return a + b; |
| } |
| @end |
| |
| @interface DidCreateJavaScriptContextFrameLoadDelegate : NSObject <WebFrameLoadDelegate> |
| @end |
| |
| @implementation DidCreateJavaScriptContextFrameLoadDelegate |
| |
| - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame |
| { |
| didFinishLoad = true; |
| } |
| |
| - (void)webView:(WebView *)webView didCreateJavaScriptContext:(JSContext *)context forFrame:(WebFrame *)frame |
| { |
| auto myConsole = adoptNS([[MyConsole alloc] init]); |
| context[@"myConsole"] = myConsole.get(); |
| context.exceptionHandler = nil; |
| |
| context[@"windowCallback"] = ^(JSValue *thisObject){ |
| didCallWindowCallback = true; |
| }; |
| |
| context[@"didCompleteTestSuccessfully"] = ^{ |
| didCompleteTestSuccessfully = true; |
| }; |
| |
| context[@"callMeBack"] = ^(JSValue *functionValue) { |
| [functionValue callWithArguments:@[]]; |
| }; |
| |
| context[@"checkForMyCustomProperty"] = ^(JSValue *element) { |
| if ([element hasProperty:@"myCustomProperty"] && [[element valueForProperty:@"myCustomProperty"] toInt32] == 42) |
| didFindMyCustomProperty = true; |
| else |
| NSLog(@"ERROR: Did not find myCustomProperty."); |
| }; |
| |
| context[@"insertMyCustomProperty"] = ^(JSValue *element) { |
| JSValue *fortyTwo = [JSValue valueWithInt32:42 inContext:[JSContext currentContext]]; |
| [element setValue:fortyTwo forProperty:@"myCustomProperty"]; |
| didInsertMyCustomProperty = true; |
| }; |
| |
| context[@"testReportException"] = ^{ |
| JSContext* context = [JSContext currentContext]; |
| [context evaluateScript:@"function doThrow() { throw 'TestError'; }"]; |
| |
| JSGlobalContextRef globalContext = [context JSGlobalContextRef]; |
| JSObjectRef globalObject = JSContextGetGlobalObject(globalContext); |
| |
| JSStringRef jsString = JSStringCreateWithUTF8CString("doThrow"); |
| JSValueRef function = JSObjectGetProperty(globalContext, globalObject, jsString, nullptr); |
| JSStringRelease(jsString); |
| |
| const JSValueRef arguments[] = { }; |
| |
| JSValueRef exception = 0; |
| JSObjectCallAsFunction(globalContext, (JSObjectRef)function, globalObject, 0, arguments, &exception); |
| if (exception) { |
| [WebView _reportException:exception inContext:globalContext]; |
| didReportException = true; |
| } |
| }; |
| } |
| |
| @end |
| |
| namespace TestWebKitAPI { |
| |
| TEST(WebKitLegacy, DidCreateJavaScriptContextSanity1) |
| { |
| didFinishLoad = false; |
| @autoreleasepool { |
| RetainPtr<WebView> webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); |
| RetainPtr<DidCreateJavaScriptContextFrameLoadDelegate> frameLoadDelegate = adoptNS([[DidCreateJavaScriptContextFrameLoadDelegate alloc] init]); |
| |
| webView.get().frameLoadDelegate = frameLoadDelegate.get(); |
| WebFrame *mainFrame = webView.get().mainFrame; |
| |
| NSString *bodyString = |
| @"<body> \ |
| <script> \ |
| myConsole.printHelloWorld(); \ |
| myConsole.log(\"Loaded custom stuff.\"); \ |
| myConsole.log(myConsole.addTo(40, 2)); \ |
| didCompleteTestSuccessfully(); \ |
| </script> \ |
| </body>"; |
| NSURL *aboutBlankURL = [NSURL URLWithString:@"about:blank"]; |
| |
| [mainFrame loadHTMLString:bodyString baseURL:aboutBlankURL]; |
| Util::run(&didCompleteTestSuccessfully); |
| } |
| } |
| |
| TEST(WebKitLegacy, DidCreateJavaScriptContextSanity2) |
| { |
| didCallWindowCallback = false; |
| @autoreleasepool { |
| RetainPtr<WebView> webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); |
| RetainPtr<DidCreateJavaScriptContextFrameLoadDelegate> frameLoadDelegate = adoptNS([[DidCreateJavaScriptContextFrameLoadDelegate alloc] init]); |
| |
| webView.get().frameLoadDelegate = frameLoadDelegate.get(); |
| WebFrame *mainFrame = webView.get().mainFrame; |
| |
| NSString *bodyString = |
| @"<body> \ |
| <script> \ |
| setTimeout(windowCallback, 100); \ |
| </script> \ |
| </body>"; |
| NSURL *aboutBlankURL = [NSURL URLWithString:@"about:blank"]; |
| |
| [mainFrame loadHTMLString:bodyString baseURL:aboutBlankURL]; |
| Util::run(&didCallWindowCallback); |
| } |
| } |
| |
| TEST(WebKitLegacy, DidCreateJavaScriptContextCallJSFunctionFromObjCCallbackTest) |
| { |
| @autoreleasepool { |
| RetainPtr<WebView> webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); |
| RetainPtr<DidCreateJavaScriptContextFrameLoadDelegate> frameLoadDelegate = adoptNS([[DidCreateJavaScriptContextFrameLoadDelegate alloc] init]); |
| |
| webView.get().frameLoadDelegate = frameLoadDelegate.get(); |
| WebFrame *mainFrame = webView.get().mainFrame; |
| |
| NSString *bodyString = |
| @"<body> \ |
| <script> \ |
| callMeBack(function() { \ |
| didCompleteTestSuccessfully(); \ |
| }); \ |
| </script> \ |
| </body>"; |
| NSURL *aboutBlankURL = [NSURL URLWithString:@"about:blank"]; |
| |
| [mainFrame loadHTMLString:bodyString baseURL:aboutBlankURL]; |
| Util::run(&didCompleteTestSuccessfully); |
| } |
| } |
| |
| TEST(WebKitLegacy, DidCreateJavaScriptContextAddCustomPropertiesFromJSTest) |
| { |
| didFindMyCustomProperty = false; |
| @autoreleasepool { |
| RetainPtr<WebView> webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); |
| RetainPtr<DidCreateJavaScriptContextFrameLoadDelegate> frameLoadDelegate = adoptNS([[DidCreateJavaScriptContextFrameLoadDelegate alloc] init]); |
| |
| webView.get().frameLoadDelegate = frameLoadDelegate.get(); |
| WebFrame *mainFrame = webView.get().mainFrame; |
| |
| NSString *bodyString = |
| @"<body> \ |
| <div id=\"test-div\"></div> \ |
| <script> \ |
| var testDiv = document.getElementById(\"test-div\"); \ |
| testDiv.myCustomProperty = 42; \ |
| checkForMyCustomProperty(testDiv); \ |
| </script> \ |
| </body>"; |
| NSURL *aboutBlankURL = [NSURL URLWithString:@"about:blank"]; |
| |
| [mainFrame loadHTMLString:bodyString baseURL:aboutBlankURL]; |
| Util::run(&didFindMyCustomProperty); |
| } |
| } |
| |
| TEST(WebKitLegacy, DidCreateJavaScriptContextAddCustomPropertiesFromObjCTest) |
| { |
| didFindMyCustomProperty = false; |
| @autoreleasepool { |
| RetainPtr<WebView> webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); |
| RetainPtr<DidCreateJavaScriptContextFrameLoadDelegate> frameLoadDelegate = adoptNS([[DidCreateJavaScriptContextFrameLoadDelegate alloc] init]); |
| |
| webView.get().frameLoadDelegate = frameLoadDelegate.get(); |
| WebFrame *mainFrame = webView.get().mainFrame; |
| |
| NSString *bodyString = |
| @"<body> \ |
| <div id=\"test-div\"></div> \ |
| <script> \ |
| var testDiv = document.getElementById(\"test-div\"); \ |
| insertMyCustomProperty(testDiv); \ |
| if (testDiv.myCustomProperty === 42) { \ |
| checkForMyCustomProperty(testDiv); \ |
| } \ |
| </script> \ |
| </body>"; |
| NSURL *aboutBlankURL = [NSURL URLWithString:@"about:blank"]; |
| |
| [mainFrame loadHTMLString:bodyString baseURL:aboutBlankURL]; |
| Util::run(&didFindMyCustomProperty); |
| } |
| } |
| |
| TEST(WebKitLegacy, DidCreateJavaScriptContextBackForwardCacheTest) |
| { |
| didInsertMyCustomProperty = false; |
| didFindMyCustomProperty = false; |
| didCompleteTestSuccessfully = false; |
| @autoreleasepool { |
| RetainPtr<WebView> webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); |
| RetainPtr<DidCreateJavaScriptContextFrameLoadDelegate> frameLoadDelegate = adoptNS([[DidCreateJavaScriptContextFrameLoadDelegate alloc] init]); |
| [[webView.get() preferences] setCacheModel:WebCacheModelDocumentBrowser]; |
| |
| webView.get().frameLoadDelegate = frameLoadDelegate.get(); |
| WebFrame *mainFrame = webView.get().mainFrame; |
| |
| NSURL *url1 = [[NSBundle mainBundle] URLForResource:@"JSContextBackForwardCache1" |
| withExtension:@"html" |
| subdirectory:@"TestWebKitAPI.resources"]; |
| [mainFrame loadRequest:[NSURLRequest requestWithURL:url1]]; |
| Util::run(&didInsertMyCustomProperty); |
| |
| NSURL *url2 = [[NSBundle mainBundle] URLForResource:@"JSContextBackForwardCache2" |
| withExtension:@"html" |
| subdirectory:@"TestWebKitAPI.resources"]; |
| [mainFrame loadRequest:[NSURLRequest requestWithURL:url2]]; |
| Util::run(&didCompleteTestSuccessfully); |
| |
| didCompleteTestSuccessfully = false; |
| [[mainFrame javaScriptContext] evaluateScript: |
| @"var testDiv = document.getElementById(\"test-div\"); \ |
| if (!testDiv.myCustomProperty) { \ |
| didCompleteTestSuccessfully(); \ |
| }"]; |
| EXPECT_TRUE(didCompleteTestSuccessfully); |
| |
| if ([webView.get() goBack]) { |
| [[mainFrame javaScriptContext] evaluateScript: |
| @"var testDiv = document.getElementById(\"test-div\"); \ |
| checkForMyCustomProperty(testDiv);"]; |
| EXPECT_TRUE(didFindMyCustomProperty); |
| } else |
| EXPECT_TRUE(false); |
| } |
| } |
| |
| TEST(WebKitLegacy, ReportExceptionTest) |
| { |
| didReportException = false; |
| @autoreleasepool { |
| RetainPtr<WebView> webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); |
| RetainPtr<DidCreateJavaScriptContextFrameLoadDelegate> frameLoadDelegate = adoptNS([[DidCreateJavaScriptContextFrameLoadDelegate alloc] init]); |
| |
| webView.get().frameLoadDelegate = frameLoadDelegate.get(); |
| WebFrame *mainFrame = webView.get().mainFrame; |
| |
| NSString *bodyString = |
| @"<body> \ |
| <script> \ |
| testReportException(); \ |
| </script> \ |
| </body>"; |
| NSURL *aboutBlankURL = [NSURL URLWithString:@"about:blank"]; |
| |
| [mainFrame loadHTMLString:bodyString baseURL:aboutBlankURL]; |
| Util::run(&didReportException); |
| } |
| } |
| |
| } // namespace TestWebKitAPI |
| |
| #endif // ENABLE(JSC_OBJC_API) |