Commit d077d83e authored by Julian Mentasti-Meza's avatar Julian Mentasti-Meza Committed by Commit Bot

[iOS] Added iOS14's createPDFWithConfiguration.

iOS14 devices will now use Apple's createPDFWithConfiguration to generate single page PDFs. CreateFullPagePdf will now render the PDFs asynchronously to behave like createPDFWithConfiguration. Unittests have been updated accordingly.

Bug: 1103777
Change-Id: I6774f78c69e79d560e4d6f52ad08a7a054a88ae6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2324104
Commit-Queue: Julian Mentasti-Meza <jmentasti@google.com>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Reviewed-by: default avatarSebastien Lalancette <seblalancette@chromium.org>
Cr-Commit-Position: refs/heads/master@{#794678}
parent 8748ed79
......@@ -217,8 +217,7 @@ TEST_F(WebStateTest, Snapshot) {
});
}
// Tests that the create PDF method retuns an PDF of a rendered html page of the
// appropriate size.
// Tests that the create PDF method retuns an PDF of a rendered html page.
TEST_F(WebStateTest, CreateFullPagePdf) {
CGFloat kSaveAreaTopInset =
UIApplication.sharedApplication.keyWindow.safeAreaInsets.top;
......@@ -236,16 +235,19 @@ TEST_F(WebStateTest, CreateFullPagePdf) {
callback_data = [pdf_document_data copy];
}));
ASSERT_TRUE(callback_data);
ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForPageLoadTimeout, ^bool {
return callback_data;
}));
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(
CGDataProviderCreateWithCFData((CFDataRef)callback_data));
CGSize pdf_size =
CGPDFPageGetBoxRect(CGPDFDocumentGetPage(pdf, 1), kCGPDFMediaBox).size;
EXPECT_EQ(pdf_size.height,
EXPECT_GE(pdf_size.height,
UIScreen.mainScreen.bounds.size.height - kSaveAreaTopInset);
EXPECT_EQ(pdf_size.width, [[UIScreen mainScreen] bounds].size.width);
EXPECT_GE(pdf_size.width, [[UIScreen mainScreen] bounds].size.width);
CGPDFDocumentRelease(pdf);
}
......
......@@ -38,6 +38,7 @@ source_set("unittests") {
"//ios/web/test:test_constants",
"//net",
"//testing/gtest",
"//third_party/ocmock",
"//url",
]
......
......@@ -52,15 +52,27 @@ bool RequiresProvisionalNavigationFailureWorkaround() {
void CreateFullPagePdf(WKWebView* web_view,
base::OnceCallback<void(NSData*)> callback) {
// iOS14 createPDFWithConfiguration returns a PDF of the WebView
// Asynchronously though a |callback| thus this method's signature matches it
// for future insertion.
if (!web_view) {
std::move(callback).Run(nil);
return;
}
__block base::OnceCallback<void(NSData*)> callback_for_block =
std::move(callback);
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
if (@available(iOS 14, *)) {
WKPDFConfiguration* pdf_configuration = [[WKPDFConfiguration alloc] init];
[web_view createPDFWithConfiguration:pdf_configuration
completionHandler:^(NSData* pdf_document_data,
NSError* error) {
std::move(callback_for_block).Run(pdf_document_data);
}];
return;
}
#endif
UIPrintPageRenderer* print_renderer = [[UIPrintPageRenderer alloc] init];
[print_renderer addPrintFormatter:[web_view viewPrintFormatter]
startingAtPageAtIndex:0];
......@@ -77,11 +89,13 @@ void CreateFullPagePdf(WKWebView* web_view,
UIGraphicsPDFRenderer* pdf_renderer =
[[UIGraphicsPDFRenderer alloc] initWithBounds:entire_web_page];
dispatch_async(dispatch_get_main_queue(), ^{
NSData* pdf_document_data = [pdf_renderer
PDFDataWithActions:^(UIGraphicsPDFRendererContext* context) {
[context beginPage];
[print_renderer drawPageAtIndex:0 inRect:entire_web_page];
}];
std::move(callback).Run(pdf_document_data);
std::move(callback_for_block).Run(pdf_document_data);
});
}
} // namespace web
......@@ -5,8 +5,10 @@
#import "ios/web/web_view/wk_web_view_util.h"
#include "base/bind.h"
#import "base/test/ios/wait_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -59,8 +61,84 @@ TEST_F(WKWebViewUtilTest, TestIsSafeBrowsingWarningDisplayedInWebView) {
}
}
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
// Tests that CreateFullPagePDF calls createPDFWithConfiguration and it invokes
// the callback with NSData.
TEST_F(WKWebViewUtilTest, IOS14EnsureCallbackIsCalledWithData) {
// Expected: callback is called with valid NSData.
if (@available(iOS 14, *)) {
// Mock the web_view and make sure createPDFWithConfiguration's
// completionHandler is invoked with NSData and no errors.
id web_view_mock = OCMClassMock([WKWebView class]);
OCMStub([web_view_mock createPDFWithConfiguration:[OCMArg any]
completionHandler:[OCMArg any]])
.andDo(^(NSInvocation* invocation) {
void (^completion_block)(NSData* pdf_document_data, NSError* error);
[invocation getArgument:&completion_block atIndex:3];
completion_block([[NSData alloc] init], nil);
});
__block bool callback_called = false;
__block NSData* callback_data = nil;
CreateFullPagePdf(web_view_mock, base::Bind(^(NSData* data) {
callback_called = true;
callback_data = [data copy];
}));
ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForPageLoadTimeout, ^bool {
return callback_called;
}));
EXPECT_TRUE(callback_data);
}
}
#endif
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
// Tests that CreateFullPagePDF calls createPDFWithConfiguration and it
// generates an NSError.
TEST_F(WKWebViewUtilTest, IOS14EnsureCallbackIsCalledWithNil) {
// Expected: callback is called with nil.
if (@available(iOS 14, *)) {
// Mock the web_view and make sure createPDFWithConfiguration's
// completionHandler is invoked with NSData and an error.
id web_view_mock = OCMClassMock([WKWebView class]);
NSError* error =
[NSError errorWithDomain:NSURLErrorDomain
code:NSURLErrorServerCertificateHasUnknownRoot
userInfo:nil];
OCMStub([web_view_mock createPDFWithConfiguration:[OCMArg any]
completionHandler:[OCMArg any]])
.andDo(^(NSInvocation* invocation) {
void (^completion_block)(NSData* pdf_document_data, NSError* error);
[invocation getArgument:&completion_block atIndex:3];
completion_block(nil, error);
});
__block bool callback_called = false;
__block NSData* callback_data = nil;
CreateFullPagePdf(web_view_mock, base::Bind(^(NSData* data) {
callback_called = true;
callback_data = [data copy];
}));
ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForPageLoadTimeout, ^bool {
return callback_called;
}));
EXPECT_FALSE(callback_data);
}
}
#endif
// Tests that CreateFullPagePDF invokes the callback with NSData.
TEST_F(WKWebViewUtilTest, EnsureCallbackIsCalled) {
TEST_F(WKWebViewUtilTest, IOS13EnsureCallbackIsCalled) {
// Expeted: The callback is called with valid NSData.
if (@available(iOS 14, *))
return;
WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init];
WKWebView* web_view = [[WKWebView alloc] initWithFrame:CGRectZero
configuration:config];
......@@ -73,13 +151,17 @@ TEST_F(WKWebViewUtilTest, EnsureCallbackIsCalled) {
callback_data = [data copy];
}));
ASSERT_TRUE(callback_called);
ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForPageLoadTimeout, ^bool {
return callback_called;
}));
EXPECT_TRUE(callback_data);
}
// Tests that CreateFullPagePDF invokes the callback with NULL if
// its given a NULL WKWebView.
TEST_F(WKWebViewUtilTest, NULLWebView) {
// Expected: callback is called with nil.
__block bool callback_called = false;
__block NSData* callback_data = nil;
......@@ -88,7 +170,10 @@ TEST_F(WKWebViewUtilTest, NULLWebView) {
callback_data = [data copy];
}));
ASSERT_TRUE(callback_called);
ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForPageLoadTimeout, ^bool {
return callback_called;
}));
EXPECT_FALSE(callback_data);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment