/* * Copyright (C) 2014 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" #if PLATFORM(MAC) #import "PlatformUtilities.h" #import "Test.h" #import #import #import #import static bool finishedNavigation; @interface UserInitiatedActionInNavigationActionDelegate : NSObject @property (nonatomic, copy) void (^policyForNavigationAction)(WKNavigationAction *, void (^)(WKNavigationActionPolicy)); @end @implementation UserInitiatedActionInNavigationActionDelegate - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { if (_policyForNavigationAction) { _policyForNavigationAction(navigationAction, decisionHandler); return; } decisionHandler(WKNavigationActionPolicyAllow); } - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { finishedNavigation = true; } @end class UserInitiatedActionTest : public testing::Test { public: RetainPtr webView; RetainPtr window; RetainPtr delegate; RetainPtr URL; virtual void SetUp() { webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]); window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]); [[window contentView] addSubview:webView.get()]; delegate = adoptNS([[UserInitiatedActionInNavigationActionDelegate alloc] init]); [webView setNavigationDelegate:delegate.get()]; URL = [[NSBundle mainBundle] URLForResource:@"open-multiple-external-url" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; } NSURL *URLWithFragment(NSString *fragment) { auto urlComponents = adoptNS([[NSURLComponents alloc] initWithURL:URL.get() resolvingAgainstBaseURL:NO]); [urlComponents setFragment:fragment]; return [urlComponents URL]; } void loadTest(NSString *test) { [webView loadRequest:[NSURLRequest requestWithURL:URLWithFragment(test)]]; TestWebKitAPI::Util::run(&finishedNavigation); finishedNavigation = false; } void click() { NSPoint clickPoint = NSMakePoint(100, 100); [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]]; [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]]; } }; TEST_F(UserInitiatedActionTest, MailtoInNormalLoop) { loadTest(@"normalLoop"); __block _WKUserInitiatedAction *initialUserInitiatedAction = nil; __block unsigned count = 0; __block bool finishedPolicy = false; delegate.get().policyForNavigationAction = ^(WKNavigationAction *navigationAction, void (^decisionHandler)(WKNavigationActionPolicy)) { if ([navigationAction.request.URL.scheme isEqualToString:@"about"]) { decisionHandler(WKNavigationActionPolicyAllow); return; } EXPECT_WK_STREQ(@"mailto", navigationAction.request.URL.scheme); EXPECT_FALSE(navigationAction._canHandleRequest); if (count == 0) { EXPECT_TRUE(navigationAction._isUserInitiated); EXPECT_NOT_NULL(navigationAction._userInitiatedAction); EXPECT_FALSE(navigationAction._userInitiatedAction.consumed); initialUserInitiatedAction = navigationAction._userInitiatedAction; [navigationAction._userInitiatedAction consume]; } else { EXPECT_TRUE(navigationAction._isUserInitiated); EXPECT_EQ(initialUserInitiatedAction, navigationAction._userInitiatedAction); EXPECT_TRUE(navigationAction._userInitiatedAction.consumed); } if (++count == 3) finishedPolicy = true; decisionHandler(WKNavigationActionPolicyCancel); }; click(); TestWebKitAPI::Util::run(&finishedPolicy); } TEST_F(UserInitiatedActionTest, MailtoInLoopAfterTimer) { loadTest(@"loopAfterTimer"); __block _WKUserInitiatedAction *initialUserInitiatedAction = nil; __block unsigned count = 0; __block bool finishedPolicy = false; delegate.get().policyForNavigationAction = ^(WKNavigationAction *navigationAction, void (^decisionHandler)(WKNavigationActionPolicy)) { if ([navigationAction.request.URL.scheme isEqualToString:@"about"]) { decisionHandler(WKNavigationActionPolicyAllow); return; } EXPECT_WK_STREQ(@"mailto", navigationAction.request.URL.scheme); EXPECT_FALSE(navigationAction._canHandleRequest); if (count == 0) { EXPECT_TRUE(navigationAction._isUserInitiated); EXPECT_NOT_NULL(navigationAction._userInitiatedAction); EXPECT_FALSE(navigationAction._userInitiatedAction.consumed); initialUserInitiatedAction = navigationAction._userInitiatedAction; [navigationAction._userInitiatedAction consume]; } else { EXPECT_TRUE(navigationAction._isUserInitiated); EXPECT_EQ(initialUserInitiatedAction, navigationAction._userInitiatedAction); EXPECT_TRUE(navigationAction._userInitiatedAction.consumed); } if (++count == 3) finishedPolicy = true; decisionHandler(WKNavigationActionPolicyCancel); }; click(); TestWebKitAPI::Util::run(&finishedPolicy); } TEST_F(UserInitiatedActionTest, MailtoInLoopAfterPostMessage) { loadTest(@"loopAfterPostMessage"); __block _WKUserInitiatedAction *initialUserInitiatedAction = nil; __block unsigned count = 0; __block bool finishedPolicy = false; delegate.get().policyForNavigationAction = ^(WKNavigationAction *navigationAction, void (^decisionHandler)(WKNavigationActionPolicy)) { if ([navigationAction.request.URL.scheme isEqualToString:@"about"]) { decisionHandler(WKNavigationActionPolicyAllow); return; } EXPECT_WK_STREQ(@"mailto", navigationAction.request.URL.scheme); EXPECT_FALSE(navigationAction._canHandleRequest); if (count == 0) { EXPECT_TRUE(navigationAction._isUserInitiated); EXPECT_NOT_NULL(navigationAction._userInitiatedAction); EXPECT_FALSE(navigationAction._userInitiatedAction.consumed); initialUserInitiatedAction = navigationAction._userInitiatedAction; [navigationAction._userInitiatedAction consume]; } else { EXPECT_TRUE(navigationAction._isUserInitiated); EXPECT_EQ(initialUserInitiatedAction, navigationAction._userInitiatedAction); EXPECT_TRUE(navigationAction._userInitiatedAction.consumed); } if (++count == 3) finishedPolicy = true; decisionHandler(WKNavigationActionPolicyCancel); }; click(); TestWebKitAPI::Util::run(&finishedPolicy); } TEST_F(UserInitiatedActionTest, MailtoInLoopAfterLongTimer) { loadTest(@"loopAfterLongTimer"); __block unsigned count = 0; __block bool finishedPolicy = false; delegate.get().policyForNavigationAction = ^(WKNavigationAction *navigationAction, void (^decisionHandler)(WKNavigationActionPolicy)) { if ([navigationAction.request.URL.scheme isEqualToString:@"about"]) { decisionHandler(WKNavigationActionPolicyAllow); return; } EXPECT_WK_STREQ(@"mailto", navigationAction.request.URL.scheme); EXPECT_FALSE(navigationAction._canHandleRequest); EXPECT_FALSE(navigationAction._isUserInitiated); EXPECT_NULL(navigationAction._userInitiatedAction); if (++count == 3) finishedPolicy = true; decisionHandler(WKNavigationActionPolicyCancel); }; click(); TestWebKitAPI::Util::run(&finishedPolicy); } #endif