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

[iOS] Added WebState's CreateFullPagePDF Public API

Generates a PDF of the webView and invokes the callback with the NSData of the PDF or nil if a PDF couldn't be generated.

The WebState calls the WebController that will invoke WKWebViewUtility's CreateFullPagePDF with the current webView. The callback is passed though at each step.

Bug: 1103777
Change-Id: I3b83082937849e2851f6ceb1954b91cc0bc242ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2295784
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@{#790411}
parent 3a98cccc
...@@ -91,6 +91,7 @@ class TestWebState : public WebState { ...@@ -91,6 +91,7 @@ class TestWebState : public WebState {
void SetHasOpener(bool has_opener) override; void SetHasOpener(bool has_opener) override;
bool CanTakeSnapshot() const override; bool CanTakeSnapshot() const override;
void TakeSnapshot(const gfx::RectF& rect, SnapshotCallback callback) override; void TakeSnapshot(const gfx::RectF& rect, SnapshotCallback callback) override;
void CreateFullPagePdf(base::OnceCallback<void(NSData*)> callback) override;
// Setters for test data. // Setters for test data.
void SetBrowserState(BrowserState* browser_state); void SetBrowserState(BrowserState* browser_state);
......
...@@ -458,4 +458,9 @@ void TestWebState::TakeSnapshot(const gfx::RectF& rect, ...@@ -458,4 +458,9 @@ void TestWebState::TakeSnapshot(const gfx::RectF& rect,
std::move(callback).Run(gfx::Image([[UIImage alloc] init])); std::move(callback).Run(gfx::Image([[UIImage alloc] init]));
} }
void TestWebState::CreateFullPagePdf(
base::OnceCallback<void(NSData*)> callback) {
std::move(callback).Run([[NSData alloc] init]);
}
} // namespace web } // namespace web
...@@ -369,6 +369,11 @@ class WebState : public base::SupportsUserData { ...@@ -369,6 +369,11 @@ class WebState : public base::SupportsUserData {
virtual void TakeSnapshot(const gfx::RectF& rect, virtual void TakeSnapshot(const gfx::RectF& rect,
SnapshotCallback callback) = 0; SnapshotCallback callback) = 0;
// Creates PDF representation of the web page and invokes the |callback| with
// the NSData of the PDF or nil if a PDF couldn't be generated.
virtual void CreateFullPagePdf(
base::OnceCallback<void(NSData*)> callback) = 0;
// Adds and removes observers for page navigation notifications. The order in // Adds and removes observers for page navigation notifications. The order in
// which notifications are sent to observers is undefined. Clients must be // which notifications are sent to observers is undefined. Clients must be
// sure to remove the observer before they go away. // sure to remove the observer before they go away.
......
...@@ -178,6 +178,11 @@ class WebStateImpl; ...@@ -178,6 +178,11 @@ class WebStateImpl;
- (void)takeSnapshotWithRect:(CGRect)rect - (void)takeSnapshotWithRect:(CGRect)rect
completion:(void (^)(UIImage* snapshot))completion; completion:(void (^)(UIImage* snapshot))completion;
// Creates PDF representation of the web page and invokes the |completion| with
// the NSData of the PDF or nil if a PDF couldn't be generated.
- (void)createFullPagePDFWithCompletion:
(void (^)(NSData* PDFDocumentData))completion;
// Creates a web view if it's not yet created. Returns the web view. // Creates a web view if it's not yet created. Returns the web view.
- (WKWebView*)ensureWebViewCreated; - (WKWebView*)ensureWebViewCreated;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#import <WebKit/WebKit.h> #import <WebKit/WebKit.h>
#include "base/bind.h"
#import "base/ios/block_types.h" #import "base/ios/block_types.h"
#include "base/ios/ios_util.h" #include "base/ios/ios_util.h"
#include "base/json/string_escape.h" #include "base/json/string_escape.h"
...@@ -860,6 +861,10 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*); ...@@ -860,6 +861,10 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
}]; }];
} }
- (void)createFullPagePDFWithCompletion:(void (^)(NSData*))completionBlock {
web::CreateFullPagePdf(self.webView, base::BindOnce(completionBlock));
}
#pragma mark - CRWTouchTrackingDelegate (Public) #pragma mark - CRWTouchTrackingDelegate (Public)
- (void)touched:(BOOL)touched { - (void)touched:(BOOL)touched {
......
...@@ -229,6 +229,7 @@ class WebStateImpl : public WebState, ...@@ -229,6 +229,7 @@ class WebStateImpl : public WebState,
void SetHasOpener(bool has_opener) override; void SetHasOpener(bool has_opener) override;
bool CanTakeSnapshot() const override; bool CanTakeSnapshot() const override;
void TakeSnapshot(const gfx::RectF& rect, SnapshotCallback callback) override; void TakeSnapshot(const gfx::RectF& rect, SnapshotCallback callback) override;
void CreateFullPagePdf(base::OnceCallback<void(NSData*)> callback) override;
void AddObserver(WebStateObserver* observer) override; void AddObserver(WebStateObserver* observer) override;
void RemoveObserver(WebStateObserver* observer) override; void RemoveObserver(WebStateObserver* observer) override;
void CloseWebState() override; void CloseWebState() override;
......
...@@ -804,6 +804,18 @@ void WebStateImpl::TakeSnapshot(const gfx::RectF& rect, ...@@ -804,6 +804,18 @@ void WebStateImpl::TakeSnapshot(const gfx::RectF& rect,
}]; }];
} }
void WebStateImpl::CreateFullPagePdf(
base::OnceCallback<void(NSData*)> callback) {
// Move the callback to a __block pointer, which will be in scope as long
// as the callback is retained.
__block base::OnceCallback<void(NSData*)> callback_for_block =
std::move(callback);
[web_controller_
createFullPagePDFWithCompletion:^(NSData* pdf_document_data) {
std::move(callback_for_block).Run(pdf_document_data);
}];
}
void WebStateImpl::OnNavigationStarted(web::NavigationContextImpl* context) { void WebStateImpl::OnNavigationStarted(web::NavigationContextImpl* context) {
// Navigation manager loads internal URLs to restore session history and // Navigation manager loads internal URLs to restore session history and
// create back-forward entries for WebUI. Do not trigger external callbacks. // create back-forward entries for WebUI. Do not trigger external callbacks.
......
...@@ -217,6 +217,39 @@ TEST_F(WebStateTest, Snapshot) { ...@@ -217,6 +217,39 @@ TEST_F(WebStateTest, Snapshot) {
}); });
} }
// Tests that the create PDF method retuns an PDF of a rendered html page of the
// appropriate size.
TEST_F(WebStateTest, CreateFullPagePdf) {
CGFloat kSaveAreaTopInset =
UIApplication.sharedApplication.keyWindow.safeAreaInsets.top;
ASSERT_TRUE(LoadHtml("<html><div style='background-color:#FF0000; width:50%; "
"height:100%;'></div></html>"));
[[[UIApplication sharedApplication] keyWindow]
addSubview:web_state()->GetView()];
// The subview is added but not immediately painted, so a small delay is
// necessary.
base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSecondsD(0.2));
__block NSData* callback_data = nil;
web_state()->CreateFullPagePdf(base::BindOnce(^(NSData* pdf_document_data) {
callback_data = [pdf_document_data copy];
}));
ASSERT_TRUE(callback_data);
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(
CGDataProviderCreateWithCFData((CFDataRef)callback_data));
CGSize pdf_size =
CGPDFPageGetBoxRect(CGPDFDocumentGetPage(pdf, 1), kCGPDFMediaBox).size;
EXPECT_EQ(pdf_size.height,
UIScreen.mainScreen.bounds.size.height - kSaveAreaTopInset);
EXPECT_EQ(pdf_size.width, [[UIScreen mainScreen] bounds].size.width);
CGPDFDocumentRelease(pdf);
}
// Tests that message sent from main frame triggers the ScriptCommandCallback // Tests that message sent from main frame triggers the ScriptCommandCallback
// with |is_main_frame| = true. // with |is_main_frame| = true.
TEST_F(WebStateTest, MessageFromMainFrame) { TEST_F(WebStateTest, MessageFromMainFrame) {
......
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