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

[iOS] Added ScreenshotDelegate to SceneController

ScreenshotDelegate is a delegate for UIKit's UIScreenshotService, which will be used to generate full-page screenshots and provide the user with the 'Full Page' screenshot tab when they take a screenshot.

Bug: 1103777
Change-Id: I9a297834e19507e1c0fdd90162ed40a12b63dc40
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2305035
Commit-Queue: Julian Mentasti-Meza <jmentasti@google.com>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Reviewed-by: default avatarSebastien Lalancette <seblalancette@chromium.org>
Cr-Commit-Position: refs/heads/master@{#794620}
parent e5b869b7
......@@ -5,21 +5,39 @@
source_set("screenshot") {
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
"screenshot_delegate.h",
"screenshot_delegate.mm",
"screenshot_metrics_recorder.h",
"screenshot_metrics_recorder.mm",
]
deps = [ "//base" ]
deps = [
"//base",
"//ios/chrome/browser/main",
"//ios/chrome/browser/ui/main",
"//ios/chrome/browser/web_state_list",
"//ios/web",
]
}
source_set("unit_tests") {
configs += [ "//build/config/compiler:enable_arc" ]
testonly = true
sources = [ "screenshot_metrics_recorder_unittest.mm" ]
sources = [
"screenshot_delegate_unittest.mm",
"screenshot_metrics_recorder_unittest.mm",
]
deps = [
":screenshot",
"//base",
"//base/test:test_support",
"//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/main:test_support",
"//ios/chrome/browser/ui/main",
"//ios/chrome/browser/ui/main/test",
"//ios/chrome/browser/web_state_list",
"//ios/chrome/browser/web_state_list:test_support",
"//ios/chrome/test:test_support",
"//ios/web/public/test",
"//third_party/ocmock",
]
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_SCREENSHOT_SCREENSHOT_DELEGATE_H_
#define IOS_CHROME_BROWSER_SCREENSHOT_SCREENSHOT_DELEGATE_H_
#import <UIKit/UIKit.h>
@class ScreenshotDelegate;
// TODO(crbug.com/1045560): Refactor this class to not use
// BrowserInterfaceProvider when possible.
@protocol BrowserInterfaceProvider;
// ScreenshotDelegate provides methods for UIScreenshotServiceDelegate to create
// PDF content of the captured window scene.
@interface ScreenshotDelegate : NSObject <UIScreenshotServiceDelegate>
// Init the ScreenshotDelegate and set the |browserInterfaceProvider| to
// generate PDF screenshots from.
- (instancetype)initWithBrowserInterfaceProvider:
(id<BrowserInterfaceProvider>)browserInterfaceProvider
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
#endif // IOS_CHROME_BROWSER_SCREENSHOT_SCREENSHOT_DELEGATE_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/screenshot/screenshot_delegate.h"
#import "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/web/public/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface ScreenshotDelegate ()
@property(nonatomic, strong) id<BrowserInterfaceProvider>
browserInterfaceProvider;
@end
@implementation ScreenshotDelegate
- (instancetype)initWithBrowserInterfaceProvider:
(id<BrowserInterfaceProvider>)browserInterfaceProvider {
self = [super init];
if (self) {
self.browserInterfaceProvider = browserInterfaceProvider;
}
return self;
}
#pragma mark - UIScreenshotServiceDelegate
// When there are multiple windows in the foreground UIKit will ask each
// UIScreenshotServiceDelegate for the PDF data and will display the PDF data of
// the widest window in the foreground.
- (void)screenshotService:(UIScreenshotService*)screenshotService
generatePDFRepresentationWithCompletion:
(void (^)(NSData*, NSInteger, CGRect))completionHandler
API_AVAILABLE(ios(13.0)) {
Browser* browser = [self.browserInterfaceProvider.currentInterface browser];
if (!browser) {
completionHandler(nil, 0, CGRectZero);
return;
}
web::WebState* webState = browser->GetWebStateList()->GetActiveWebState();
if (!webState) {
completionHandler(nil, 0, CGRectZero);
return;
}
base::OnceCallback<void(NSData*)> callback =
base::BindOnce(^(NSData* pdfDoumentData) {
completionHandler(pdfDoumentData, 0, CGRectZero);
});
webState->CreateFullPagePdf(std::move(callback));
}
@end
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/screenshot/screenshot_delegate.h"
#import "ios/chrome/browser/main/test_browser.h"
#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
#import "ios/chrome/browser/ui/main/test/stub_browser_interface.h"
#import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#import "ios/web/public/test/web_task_environment.h"
#import "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."
#endif
class ScreenshotDelegateTest : public PlatformTest {
protected:
ScreenshotDelegateTest() {}
~ScreenshotDelegateTest() override {}
void SetUp() override {
browser_interface_ = [[StubBrowserInterface alloc] init];
browser_interface_provider_ = [[StubBrowserInterfaceProvider alloc] init];
if (@available(iOS 13, *))
screenshot_service_ = OCMClassMock([UIScreenshotService class]);
}
void createScreenshotDelegate() {
screenshotDelegate_ = [[ScreenshotDelegate alloc]
initWithBrowserInterfaceProvider:browser_interface_provider_];
}
web::WebTaskEnvironment task_environment_;
StubBrowserInterface* browser_interface_;
StubBrowserInterfaceProvider* browser_interface_provider_;
ScreenshotDelegate* screenshotDelegate_;
id screenshot_service_;
};
// Tests that ScreenshotDelegate can be init with browserInterfaceProvider can
// be set and that data can be generated from it.
TEST_F(ScreenshotDelegateTest, screenshotService) {
// Expected: Empty NSData.
if (@available(iOS 13, *)) {
auto web_state = std::make_unique<web::TestWebState>();
TestBrowser browser;
// Insert the web_state into the Browser.
int insertion_index = browser.GetWebStateList()->InsertWebState(
WebStateList::kInvalidIndex, std::move(web_state),
WebStateList::INSERT_NO_FLAGS, WebStateOpener());
browser.GetWebStateList()->ActivateWebStateAt(insertion_index);
// Add the Browser to StubBrowserInterface.
browser_interface_.browser = &browser;
// Add the StubBrowserInterface to StubBrowserInterfaceProvider.
browser_interface_provider_.currentInterface = browser_interface_;
createScreenshotDelegate();
__block bool callback_ran = false;
[screenshotDelegate_ screenshotService:screenshot_service_
generatePDFRepresentationWithCompletion:^(NSData* PDFData,
NSInteger indexOfCurrentPage,
CGRect rectInCurrentPage) {
EXPECT_TRUE(PDFData);
callback_ran = true;
}];
EXPECT_TRUE(callback_ran);
}
}
// Tests that when ScreenshotDelegate's browserInterfaceProvider has a nil
// Browser screenshotService will return nil.
TEST_F(ScreenshotDelegateTest, nilBrowser) {
// Expected: nil NSData.
if (@available(iOS 13, *)) {
// Add the StubBrowserInterface with no set Browser to
// StubBrowserInterfaceProvider.
browser_interface_provider_.currentInterface = browser_interface_;
createScreenshotDelegate();
__block bool callback_ran = false;
[screenshotDelegate_ screenshotService:screenshot_service_
generatePDFRepresentationWithCompletion:^(NSData* PDFData,
NSInteger indexOfCurrentPage,
CGRect rectInCurrentPage) {
EXPECT_FALSE(PDFData);
callback_ran = true;
}];
EXPECT_TRUE(callback_ran);
}
}
// Tests that when ScreenshotDelegate's browserInterfaceProvider has a nil
// WebSatate screenshotService will return nil.
TEST_F(ScreenshotDelegateTest, nilWebState) {
// Expected: nil NSData.
if (@available(iOS 13, *)) {
TestBrowser browser;
// Add the empty Browser to StubBrowserInterface.
browser_interface_.browser = &browser;
// Add the StubBrowserInterface to StubBrowserInterfaceProvider.
browser_interface_provider_.currentInterface = browser_interface_;
createScreenshotDelegate();
__block bool callback_ran = false;
[screenshotDelegate_ screenshotService:screenshot_service_
generatePDFRepresentationWithCompletion:^(NSData* PDFData,
NSInteger indexOfCurrentPage,
CGRect rectInCurrentPage) {
EXPECT_FALSE(PDFData);
callback_ran = true;
}];
EXPECT_TRUE(callback_ran);
}
}
......@@ -75,6 +75,7 @@ source_set("scene") {
"//ios/chrome/browser/main",
"//ios/chrome/browser/ntp:features",
"//ios/chrome/browser/ntp_snippets:ntp_snippets",
"//ios/chrome/browser/screenshot",
"//ios/chrome/browser/signin",
"//ios/chrome/browser/snapshots",
"//ios/chrome/browser/ui:feature_flags",
......
......@@ -40,6 +40,7 @@
#import "ios/chrome/browser/main/browser_list_factory.h"
#include "ios/chrome/browser/ntp/features.h"
#import "ios/chrome/browser/ntp_snippets/content_suggestions_scheduler_notifications.h"
#include "ios/chrome/browser/screenshot/screenshot_delegate.h"
#include "ios/chrome/browser/signin/constants.h"
#include "ios/chrome/browser/signin/identity_manager_factory.h"
#import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
......@@ -150,6 +151,9 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
// Coordinator for displaying history.
@property(nonatomic, strong) HistoryCoordinator* historyCoordinator;
// Coordinates the creation of PDF screenshots with the window's content.
@property(nonatomic, strong) ScreenshotDelegate* screenshotDelegate;
// The tab switcher command and the voice search commands can be sent by views
// that reside in a different UIWindow leading to the fact that the exclusive
// touch property will be ineffective and a command for processing both
......@@ -508,6 +512,16 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
// Ensure the main browser is created. This also creates the BVC.
[self.browserViewWrangler createMainBrowser];
if (IsSceneStartupSupported() &&
base::FeatureList::IsEnabled(kEnableFullPageScreenshot)) {
if (@available(iOS 13, *)) {
self.screenshotDelegate = [[ScreenshotDelegate alloc]
initWithBrowserInterfaceProvider:self.browserViewWrangler];
[self.sceneState.scene.screenshotService
setDelegate:self.screenshotDelegate];
}
}
// Only create the restoration helper if the browser state was backed up
// successfully.
if (self.sceneState.appState.sessionRestorationRequired) {
......@@ -2209,5 +2223,4 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
// Notify the _tabSwitcher with the new Incognito Browser.
[self.tabSwitcher setOtrBrowser:self.incognitoInterface.browser];
}
@end
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