Add support to WebPage for getting the contents as an attributed string.
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Mar 2019 21:36:56 +0000 (21:36 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Mar 2019 21:36:56 +0000 (21:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195636
rdar://problem/45055697

Reviewed by Tim Horton.

Source/WebKit:

* Shared/mac/AttributedString.h:
(WebKit::AttributedString::AttributedString):
* Shared/mac/AttributedString.mm:
(IPC::ArgumentCoder<WebKit::AttributedString>::encode):
(IPC::ArgumentCoder<WebKit::AttributedString>::decode):
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _getContentsAsAttributedStringWithCompletionHandler:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::getContentsAsAttributedString):
* UIProcess/WebPageProxy.h:
* WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
(WebKit::WebPage::getContentsAsAttributedString):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/WKWebViewGetContents.mm:
(TEST(WKWebView, GetContentsShouldReturnAttributedString): Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243012 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
Source/WebKit/ChangeLog
Source/WebKit/Shared/mac/AttributedString.h
Source/WebKit/Shared/mac/AttributedString.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewGetContents.mm

index ddb9bba..f229607 100644 (file)
@@ -1,3 +1,27 @@
+2019-03-15  Timothy Hatcher  <timothy@apple.com>
+
+        Add support to WebPage for getting the contents as an attributed string.
+        https://bugs.webkit.org/show_bug.cgi?id=195636
+        rdar://problem/45055697
+
+        Reviewed by Tim Horton.
+
+        * Shared/mac/AttributedString.h:
+        (WebKit::AttributedString::AttributedString):
+        * Shared/mac/AttributedString.mm:
+        (IPC::ArgumentCoder<WebKit::AttributedString>::encode):
+        (IPC::ArgumentCoder<WebKit::AttributedString>::decode):
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _getContentsAsAttributedStringWithCompletionHandler:]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::getContentsAsAttributedString):
+        * UIProcess/WebPageProxy.h:
+        * WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
+        (WebKit::WebPage::getContentsAsAttributedString):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2019-03-15  Per Arne Vollan  <pvollan@apple.com>
 
         [iOS] Fix sandbox violation
index ea1cd3e..8530f81 100644 (file)
@@ -38,8 +38,9 @@ struct AttributedString {
     }
 
 #if defined(__OBJC__)
-    AttributedString(NSAttributedString *attributedString)
+    AttributedString(NSAttributedString *attributedString, NSDictionary *documentAttributes = nil)
         : string(attributedString)
+        , documentAttributes(documentAttributes)
     {
     }
 
@@ -48,8 +49,9 @@ struct AttributedString {
         return string.get();
     }
 #endif
-    
+
     RetainPtr<NSAttributedString> string;
+    RetainPtr<NSDictionary> documentAttributes;
 };
 
 }
index ae08584..3c47005 100644 (file)
@@ -34,7 +34,7 @@ namespace IPC {
 
 void ArgumentCoder<WebKit::AttributedString>::encode(Encoder& encoder, const WebKit::AttributedString& attributedString)
 {
-    encoder << attributedString.string;
+    encoder << attributedString.string << attributedString.documentAttributes;
 }
 
 Optional<WebKit::AttributedString> ArgumentCoder<WebKit::AttributedString>::decode(Decoder& decoder)
@@ -42,7 +42,10 @@ Optional<WebKit::AttributedString> ArgumentCoder<WebKit::AttributedString>::deco
     RetainPtr<NSAttributedString> attributedString;
     if (!IPC::decode(decoder, attributedString))
         return WTF::nullopt;
-    return WebKit::AttributedString { attributedString.get() };
+    RetainPtr<NSDictionary> documentAttributes;
+    if (!IPC::decode(decoder, documentAttributes))
+        return WTF::nullopt;
+    return WebKit::AttributedString { attributedString.get(), documentAttributes.get() };
 }
 
 }
index f4cf47b..f7850a0 100644 (file)
@@ -29,6 +29,7 @@
 #import "APIFormClient.h"
 #import "APIPageConfiguration.h"
 #import "APISerializedScriptValue.h"
+#import "AttributedString.h"
 #import "CompletionHandlerCallChecker.h"
 #import "DiagnosticLoggingClient.h"
 #import "DynamicViewportSizeUpdate.h"
@@ -5253,6 +5254,16 @@ static inline OptionSet<WebCore::LayoutMilestone> layoutMilestones(_WKRenderingP
     });
 }
 
+- (void)_getContentsAsAttributedStringWithCompletionHandler:(void (^)(NSAttributedString *, NSDictionary<NSAttributedStringDocumentAttributeKey, id> *, NSError *))completionHandler
+{
+    _page->getContentsAsAttributedString([handler = makeBlockPtr(completionHandler)](auto& attributedString) {
+        if (attributedString.string)
+            handler([[attributedString.string.get() retain] autorelease], [[attributedString.documentAttributes.get() retain] autorelease], nil);
+        else
+            handler(nil, nil, createNSError(WKErrorUnknown).get());
+    });
+}
+
 - (void)_getApplicationManifestWithCompletionHandler:(void (^)(_WKApplicationManifest *))completionHandler
 {
 #if ENABLE(APPLICATION_MANIFEST)
index cef3b87..36df5a5 100644 (file)
@@ -364,6 +364,7 @@ typedef NS_OPTIONS(NSUInteger, _WKRectEdge) {
 - (void)_getMainResourceDataWithCompletionHandler:(void (^)(NSData *, NSError *))completionHandler;
 - (void)_getWebArchiveDataWithCompletionHandler:(void (^)(NSData *, NSError *))completionHandler;
 - (void)_getContentsAsStringWithCompletionHandler:(void (^)(NSString *, NSError *))completionHandler WK_API_AVAILABLE(macosx(10.13), ios(11.0));
+- (void)_getContentsAsAttributedStringWithCompletionHandler:(void (^)(NSAttributedString *, NSDictionary<NSAttributedStringDocumentAttributeKey, id> *, NSError *))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_MAC_TBA));
 
 - (void)_getApplicationManifestWithCompletionHandler:(void (^)(_WKApplicationManifest *))completionHandler WK_API_AVAILABLE(macosx(10.13.4), ios(11.3));
 
index 4dd2214..485cd42 100644 (file)
@@ -52,6 +52,7 @@
 #include "APIUIClient.h"
 #include "APIURLRequest.h"
 #include "APIWebsitePolicies.h"
+#include "AttributedString.h"
 #include "AuthenticationChallengeProxy.h"
 #include "AuthenticationDecisionListener.h"
 #include "DataReference.h"
@@ -3601,6 +3602,21 @@ void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, Callba
     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
 }
 
+void WebPageProxy::getContentsAsAttributedString(CompletionHandler<void(const AttributedString&)>&& completionHandler)
+{
+#if PLATFORM(COCOA)
+    if (!isValid()) {
+        completionHandler(AttributedString());
+        return;
+    }
+
+    m_process->connection()->sendWithAsyncReply(Messages::WebPage::GetContentsAsAttributedString(), WTFMove(completionHandler), m_pageID);
+#else
+    ASSERT_NOT_REACHED();
+    completionHandler(AttributedString());
+#endif
+}
+
 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
 {
     if (!isValid()) {
index 90588d9..83ce0fb 100644 (file)
@@ -973,6 +973,7 @@ public:
     void didFindStringMatches(const String&, const Vector<Vector<WebCore::IntRect>>& matchRects, int32_t firstIndexAfterSelection);
 
     void getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&&);
+    void getContentsAsAttributedString(CompletionHandler<void(const AttributedString&)>&&);
     void getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&&);
     void getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&&);
 
index d630670..bd87bfe 100644 (file)
@@ -27,6 +27,7 @@
 #import "WebPage.h"
 
 
+#import "AttributedString.h"
 #import "LoadParameters.h"
 #import "PluginView.h"
 #import "WebPageProxyMessages.h"
@@ -42,6 +43,7 @@
 #import <WebCore/PlatformMediaSessionManager.h>
 #import <WebCore/RenderElement.h>
 #import <WebCore/RenderObject.h>
+#import <WebCore/TextIterator.h>
 
 #if PLATFORM(COCOA)
 
@@ -201,6 +203,21 @@ WebPaymentCoordinator* WebPage::paymentCoordinator()
 }
 #endif
 
+void WebPage::getContentsAsAttributedString(CompletionHandler<void(const AttributedString&)>&& completionHandler)
+{
+    Frame& frame = m_page->mainFrame();
+
+    RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(frame.document()->documentElement(), 0, INT_MAX);
+
+    NSDictionary* documentAttributes = nil;
+
+    AttributedString result;
+    result.string = attributedStringFromRange(*range, &documentAttributes);
+    result.documentAttributes = documentAttributes;
+
+    completionHandler({ result });
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(COCOA)
index a226cad..0bc6406 100644 (file)
@@ -1315,6 +1315,9 @@ private:
     void viewWillEndLiveResize();
 
     void getContentsAsString(CallbackID);
+#if PLATFORM(COCOA)
+    void getContentsAsAttributedString(CompletionHandler<void(const AttributedString&)>&&);
+#endif
 #if ENABLE(MHTML)
     void getContentsAsMHTMLData(CallbackID);
 #endif
index 042b474..d2484a5 100644 (file)
@@ -182,6 +182,9 @@ messages -> WebPage LegacyReceiver {
 
     # Callbacks.
     GetContentsAsString(WebKit::CallbackID callbackID)
+#if PLATFORM(COCOA)
+    GetContentsAsAttributedString() -> (struct WebKit::AttributedString result) Async
+#endif
 #if ENABLE(MHTML)
     GetContentsAsMHTMLData(WebKit::CallbackID callbackID)
 #endif
index 8a653a5..1f498b6 100644 (file)
@@ -1,3 +1,14 @@
+2019-03-15  Timothy Hatcher  <timothy@apple.com>
+
+        Add support to WebPage for getting the contents as an attributed string.
+        https://bugs.webkit.org/show_bug.cgi?id=195636
+        rdar://problem/45055697
+
+        Reviewed by Tim Horton.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKWebViewGetContents.mm:
+        (TEST(WKWebView, GetContentsShouldReturnAttributedString): Added.
+
 2019-03-15  Chris Dumez  <cdumez@apple.com>
 
         [PSON] Make sure the WebProcessCache is leverage when relaunching a process after termination
index 798e44a..4337bda 100644 (file)
@@ -48,3 +48,48 @@ TEST(WKWebView, GetContentsShouldReturnString)
 
     TestWebKitAPI::Util::run(&finished);
 }
+
+TEST(WKWebView, GetContentsShouldReturnAttributedString)
+{
+    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+
+    [webView synchronouslyLoadHTMLString:@"<body bgcolor='red'>Hello <b>World!</b>"];
+
+    __block bool finished = false;
+
+#if USE(APPKIT)
+    using PlatformFont = NSFont;
+    using PlatformColor = NSColor;
+#else
+    using PlatformFont = UIFont;
+    using PlatformColor = UIColor;
+#endif
+
+    [webView _getContentsAsAttributedStringWithCompletionHandler:^(NSAttributedString *attributedString, NSDictionary<NSAttributedStringDocumentAttributeKey, id> *documentAttributes, NSError *error) {
+        EXPECT_NOT_NULL(attributedString);
+        EXPECT_NOT_NULL(documentAttributes);
+        EXPECT_NULL(error);
+
+        __block size_t i = 0;
+        [attributedString enumerateAttributesInRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(NSDictionary *attributes, NSRange attributeRange, BOOL *stop) {
+            auto* substring = [attributedString attributedSubstringFromRange:attributeRange];
+
+            if (!i) {
+                EXPECT_WK_STREQ(@"Hello ", substring.string);
+                EXPECT_WK_STREQ(@"Times-Roman", dynamic_objc_cast<PlatformFont>(attributes[NSFontAttributeName]).fontName);
+            } else if (i == 1) {
+                EXPECT_WK_STREQ(@"World!", substring.string);
+                EXPECT_WK_STREQ(@"Times-Bold", dynamic_objc_cast<PlatformFont>(attributes[NSFontAttributeName]).fontName);
+            } else
+                ASSERT_NOT_REACHED();
+
+            ++i;
+        }];
+
+        EXPECT_WK_STREQ(@"sRGB IEC61966-2.1 colorspace 1 0 0 1", dynamic_objc_cast<PlatformColor>(documentAttributes[NSBackgroundColorDocumentAttribute]).description);
+
+        finished = true;
+    }];
+
+    TestWebKitAPI::Util::run(&finished);
+}