Title: [273283] trunk
Revision
273283
Author
[email protected]
Date
2021-02-22 15:19:21 -0800 (Mon, 22 Feb 2021)

Log Message

[Cocoa] Add WKWebView session restoration API
https://bugs.webkit.org/show_bug.cgi?id=220958
<rdar://70956146>

Reviewed by Geoffrey Garen.

Source/WebKit:

Add WKWebView session restoration API so that applications can easily retrieve
view state (such as back-forward list, scroll position, form data...) and
restore it on a WKWebView later on.

* UIProcess/API/Cocoa/WKWebView.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView interactionState]):
(-[WKWebView setInteractionState:]):

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKit/WKBackForwardList.mm:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (273282 => 273283)


--- trunk/Source/WebKit/ChangeLog	2021-02-22 23:07:20 UTC (rev 273282)
+++ trunk/Source/WebKit/ChangeLog	2021-02-22 23:19:21 UTC (rev 273283)
@@ -1,5 +1,22 @@
 2021-02-22  Chris Dumez  <[email protected]>
 
+        [Cocoa] Add WKWebView session restoration API
+        https://bugs.webkit.org/show_bug.cgi?id=220958
+        <rdar://70956146>
+
+        Reviewed by Geoffrey Garen.
+
+        Add WKWebView session restoration API so that applications can easily retrieve
+        view state (such as back-forward list, scroll position, form data...) and
+        restore it on a WKWebView later on.
+
+        * UIProcess/API/Cocoa/WKWebView.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView interactionState]):
+        (-[WKWebView setInteractionState:]):
+
+2021-02-22  Chris Dumez  <[email protected]>
+
         Use adoptNS() as soon as we [[ObjcClass alloc] init] to avoid leaks
         https://bugs.webkit.org/show_bug.cgi?id=222237
 

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.h (273282 => 273283)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.h	2021-02-22 23:07:20 UTC (rev 273282)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.h	2021-02-22 23:19:21 UTC (rev 273283)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2021 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -473,6 +473,12 @@
 */
 @property (nonatomic, nullable, copy) NSString *mediaType WK_API_AVAILABLE(macos(11.0), ios(14.0));
 
+/* @abstract The interaction state for the WKWebView
+ @discussion The interaction state (back-forward list, currently loaded page, scroll position, form data...) for the WKWebView, which
+ can be retrieved and set on another WKWebView to restore state.
+*/
+@property (nonatomic, nullable, copy) id interactionState WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 #if !TARGET_OS_IPHONE
 /* @abstract Returns an NSPrintOperation object configured to print the contents of this WKWebView
 @param printInfo The print info object used to configure the resulting print operation.

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (273282 => 273283)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2021-02-22 23:07:20 UTC (rev 273282)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2021-02-22 23:19:21 UTC (rev 273283)
@@ -52,6 +52,7 @@
 #import "RemoteObjectRegistryMessages.h"
 #import "ResourceLoadDelegate.h"
 #import "SafeBrowsingWarning.h"
+#import "SessionStateCoding.h"
 #import "SharedBufferCopy.h"
 #import "UIDelegate.h"
 #import "VideoFullscreenManagerProxy.h"
@@ -1235,6 +1236,22 @@
     return _page->overriddenMediaType().isNull() ? nil : (NSString *)_page->overriddenMediaType();
 }
 
+- (id)interactionState
+{
+    return WebKit::encodeSessionState(_page->sessionState()).autorelease();
+}
+
+- (void)setInteractionState:(id)interactionState
+{
+    if (![(id)interactionState isKindOfClass:[NSData class]])
+        return;
+
+    WebKit::SessionState sessionState;
+    if (!WebKit::decodeSessionState((NSData *)(interactionState), sessionState))
+        return;
+    _page->restoreFromSessionState(sessionState, true);
+}
+
 #pragma mark - iOS API
 
 #if PLATFORM(IOS_FAMILY)

Modified: trunk/Tools/ChangeLog (273282 => 273283)


--- trunk/Tools/ChangeLog	2021-02-22 23:07:20 UTC (rev 273282)
+++ trunk/Tools/ChangeLog	2021-02-22 23:19:21 UTC (rev 273283)
@@ -1,5 +1,18 @@
 2021-02-22  Chris Dumez  <[email protected]>
 
+        [Cocoa] Add WKWebView session restoration API
+        https://bugs.webkit.org/show_bug.cgi?id=220958
+        <rdar://70956146>
+
+        Reviewed by Geoffrey Garen.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKit/WKBackForwardList.mm:
+        (TEST):
+
+2021-02-22  Chris Dumez  <[email protected]>
+
         Use adoptNS() as soon as we [[ObjcClass alloc] init] to avoid leaks
         https://bugs.webkit.org/show_bug.cgi?id=222237
 

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/WKBackForwardList.mm (273282 => 273283)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit/WKBackForwardList.mm	2021-02-22 23:07:20 UTC (rev 273282)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/WKBackForwardList.mm	2021-02-22 23:19:21 UTC (rev 273283)
@@ -166,3 +166,146 @@
     TestWebKitAPI::Util::run(&done);
     EXPECT_STREQ(webView.get().backForwardList.currentItem.URL.absoluteString.UTF8String, simple.absoluteString.UTF8String);
 }
+
+TEST(WKBackForwardList, InteractionStateRestoration)
+{
+    auto webView = adoptNS([[WKWebView alloc] init]);
+
+    NSURL *url1 = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+    NSURL *url2 = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+    NSURL *url3 = [[NSBundle mainBundle] URLForResource:@"simple3" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url1]];
+    [webView _test_waitForDidFinishNavigation];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url2]];
+    [webView _test_waitForDidFinishNavigation];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url3]];
+    [webView _test_waitForDidFinishNavigation];
+
+    WKBackForwardList *list = [webView backForwardList];
+    EXPECT_EQ((NSUInteger)2, list.backList.count);
+    EXPECT_EQ((NSUInteger)0, list.forwardList.count);
+    EXPECT_STREQ([[list.currentItem URL] absoluteString].UTF8String, url3.absoluteString.UTF8String);
+
+    id interactionState = [webView interactionState];
+    RetainPtr<NSURL> temporaryFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString] isDirectory:NO];
+    NSError *error = nil;
+    RetainPtr<NSData> archivedInteractionState = [NSKeyedArchiver archivedDataWithRootObject:interactionState requiringSecureCoding:YES error:&error];
+    EXPECT_TRUE(!error);
+    interactionState = nil;
+    [archivedInteractionState writeToURL:temporaryFile.get() options:NSDataWritingAtomic error:&error];
+    archivedInteractionState = nil;
+    EXPECT_TRUE(!error);
+
+    webView = adoptNS([[WKWebView alloc] init]);
+
+    archivedInteractionState = [NSData dataWithContentsOfURL:temporaryFile.get()];
+    interactionState = [NSKeyedUnarchiver unarchivedObjectOfClass:[(id)[webView interactionState] class] fromData:archivedInteractionState.get() error:&error];
+    EXPECT_TRUE(!error);
+
+    [webView setInteractionState:interactionState];
+    [webView _test_waitForDidFinishNavigation];
+
+    WKBackForwardList *newList = [webView backForwardList];
+
+    EXPECT_EQ((NSUInteger)2, newList.backList.count);
+    EXPECT_EQ((NSUInteger)0, newList.forwardList.count);
+    EXPECT_STREQ([[newList.currentItem URL] absoluteString].UTF8String, url3.absoluteString.UTF8String);
+
+    done = false;
+    [webView evaluateJavaScript:@"document.body.innerText" completionHandler:^(id result, NSError *error) {
+        EXPECT_TRUE(!error);
+        NSString* bodyText = result;
+        EXPECT_WK_STREQ(@"Third simple HTML file.", bodyText);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    [webView goBack];
+    [webView _test_waitForDidFinishNavigation];
+
+    done = false;
+    [webView evaluateJavaScript:@"document.body.innerText" completionHandler:^(id result, NSError *error) {
+        EXPECT_TRUE(!error);
+        NSString* bodyText = result;
+        EXPECT_WK_STREQ(@"Second simple HTML file.", bodyText);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    [webView goBack];
+    [webView _test_waitForDidFinishNavigation];
+
+    done = false;
+    [webView evaluateJavaScript:@"document.body.innerText" completionHandler:^(id result, NSError *error) {
+        EXPECT_TRUE(!error);
+        NSString* bodyText = result;
+        EXPECT_WK_STREQ(@"Simple HTML file.", bodyText);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+}
+
+TEST(WKBackForwardList, InteractionStateRestorationNil)
+{
+    auto webView = adoptNS([[WKWebView alloc] init]);
+
+    NSURL *url1 = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+    NSURL *url2 = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+    NSURL *url3 = [[NSBundle mainBundle] URLForResource:@"simple3" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url1]];
+    [webView _test_waitForDidFinishNavigation];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url2]];
+    [webView _test_waitForDidFinishNavigation];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url3]];
+    [webView _test_waitForDidFinishNavigation];
+
+    WKBackForwardList *list = [webView backForwardList];
+    EXPECT_EQ((NSUInteger)2, list.backList.count);
+    EXPECT_EQ((NSUInteger)0, list.forwardList.count);
+    EXPECT_STREQ([[list.currentItem URL] absoluteString].UTF8String, url3.absoluteString.UTF8String);
+
+    [webView setInteractionState:nil];
+
+    list = [webView backForwardList];
+    EXPECT_EQ((NSUInteger)2, list.backList.count);
+    EXPECT_EQ((NSUInteger)0, list.forwardList.count);
+    EXPECT_STREQ([[list.currentItem URL] absoluteString].UTF8String, url3.absoluteString.UTF8String);
+}
+
+TEST(WKBackForwardList, InteractionStateRestorationInvalid)
+{
+    auto webView = adoptNS([[WKWebView alloc] init]);
+
+    NSURL *url1 = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+    NSURL *url2 = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+    NSURL *url3 = [[NSBundle mainBundle] URLForResource:@"simple3" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url1]];
+    [webView _test_waitForDidFinishNavigation];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url2]];
+    [webView _test_waitForDidFinishNavigation];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:url3]];
+    [webView _test_waitForDidFinishNavigation];
+
+    WKBackForwardList *list = [webView backForwardList];
+    EXPECT_EQ((NSUInteger)2, list.backList.count);
+    EXPECT_EQ((NSUInteger)0, list.forwardList.count);
+    EXPECT_STREQ([[list.currentItem URL] absoluteString].UTF8String, url3.absoluteString.UTF8String);
+
+    NSString *invalidState = @"foo";
+    [webView setInteractionState:invalidState];
+
+    list = [webView backForwardList];
+    EXPECT_EQ((NSUInteger)2, list.backList.count);
+    EXPECT_EQ((NSUInteger)0, list.forwardList.count);
+    EXPECT_STREQ([[list.currentItem URL] absoluteString].UTF8String, url3.absoluteString.UTF8String);
+}
+
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to