blob: 96742dbb1ebec91ef5ea1b4358b6f18f2a4f458b [file] [log] [blame]
// Copyright 2015 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.
#include "components/open_from_clipboard/clipboard_recent_content_ios.h"
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIKit.h>
#include <memory>
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#import "components/open_from_clipboard/clipboard_recent_content_impl_ios.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
namespace {
UIImage* TestUIImage(UIColor* color = [UIColor redColor]) {
CGRect frame = CGRectMake(0, 0, 1.0, 1.0);
UIGraphicsBeginImageContext(frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, frame);
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
void SetPasteboardImage(UIImage* image) {
[[UIPasteboard generalPasteboard] setImage:image];
}
void SetPasteboardContent(const char* data) {
[[UIPasteboard generalPasteboard]
setValue:[NSString stringWithUTF8String:data]
forPasteboardType:@"public.plain-text"];
}
const char kUnrecognizedURL[] = "bad://foo/";
const char kRecognizedURL[] = "good://bar/";
const char kRecognizedURL2[] = "good://bar/2";
const char kAppSpecificURL[] = "test://qux/";
const char kAppSpecificScheme[] = "test";
const char kRecognizedScheme[] = "good";
NSTimeInterval kLongerThanMaxAge = 60 * 60 * 7;
NSTimeInterval kMaxAge = 60 * 60 * 1;
} // namespace
@interface ClipboardRecentContentImplIOSWithFakeUptime
: ClipboardRecentContentImplIOS
@property(nonatomic) NSTimeInterval fakeUptime;
- (instancetype)initWithMaxAge:(NSTimeInterval)maxAge
authorizedSchemes:(NSArray*)authorizedSchemes
userDefaults:(NSUserDefaults*)groupUserDefaults
uptime:(NSTimeInterval)uptime;
@end
@implementation ClipboardRecentContentImplIOSWithFakeUptime
@synthesize fakeUptime = _fakeUptime;
- (instancetype)initWithMaxAge:(NSTimeInterval)maxAge
authorizedSchemes:(NSSet*)authorizedSchemes
userDefaults:(NSUserDefaults*)groupUserDefaults
uptime:(NSTimeInterval)uptime {
self = [super initWithMaxAge:maxAge
authorizedSchemes:authorizedSchemes
userDefaults:groupUserDefaults
delegate:nil];
if (self) {
_fakeUptime = uptime;
}
return self;
}
- (NSTimeInterval)uptime {
return self.fakeUptime;
}
@end
class ClipboardRecentContentIOSWithFakeUptime
: public ClipboardRecentContentIOS {
public:
ClipboardRecentContentIOSWithFakeUptime(
ClipboardRecentContentImplIOS* implementation)
: ClipboardRecentContentIOS(implementation) {}
};
class ClipboardRecentContentIOSTest : public ::testing::Test {
protected:
ClipboardRecentContentIOSTest() {
// By default, set that the device booted 10 days ago.
ResetClipboardRecentContent(kAppSpecificScheme,
base::TimeDelta::FromDays(10));
}
void SimulateDeviceRestart() {
ResetClipboardRecentContent(kAppSpecificScheme,
base::TimeDelta::FromSeconds(0));
}
void ResetClipboardRecentContent(const std::string& application_scheme,
base::TimeDelta time_delta) {
clipboard_content_implementation_ =
[[ClipboardRecentContentImplIOSWithFakeUptime alloc]
initWithMaxAge:kMaxAge
authorizedSchemes:@[
base::SysUTF8ToNSString(kRecognizedScheme),
base::SysUTF8ToNSString(application_scheme)
]
userDefaults:[NSUserDefaults standardUserDefaults]
uptime:time_delta.InSecondsF()];
clipboard_content_ =
std::make_unique<ClipboardRecentContentIOSWithFakeUptime>(
clipboard_content_implementation_);
}
void SetStoredPasteboardChangeDate(NSDate* change_date) {
clipboard_content_implementation_.lastPasteboardChangeDate =
[change_date copy];
[clipboard_content_implementation_ saveToUserDefaults];
}
protected:
std::unique_ptr<ClipboardRecentContentIOSWithFakeUptime> clipboard_content_;
ClipboardRecentContentImplIOSWithFakeUptime*
clipboard_content_implementation_;
void VerifyClipboardURLExists(const char* expected_url) {
base::Optional<GURL> optional_gurl =
clipboard_content_->GetRecentURLFromClipboard();
EXPECT_TRUE(optional_gurl.has_value());
EXPECT_STREQ(expected_url, optional_gurl.value().spec().c_str());
}
void VerifyClipboardURLDoesNotExist() {
EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard().has_value());
}
void VerifyClipboardTextExists(const char* expected_text) {
base::Optional<base::string16> optional_text =
clipboard_content_->GetRecentTextFromClipboard();
EXPECT_TRUE(optional_text.has_value());
EXPECT_STREQ(expected_text,
base::UTF16ToUTF8(optional_text.value()).c_str());
}
void VerifyClipboardTextDoesNotExist() {
EXPECT_FALSE(clipboard_content_->GetRecentTextFromClipboard().has_value());
}
void VerifyIfClipboardImageExists(bool exists) {
EXPECT_EQ(clipboard_content_->GetRecentImageFromClipboard().has_value(),
exists);
}
};
TEST_F(ClipboardRecentContentIOSTest, SchemeFiltering) {
// Test unrecognized URL.
SetPasteboardContent(kUnrecognizedURL);
VerifyClipboardURLDoesNotExist();
// Test recognized URL.
SetPasteboardContent(kRecognizedURL);
VerifyClipboardURLExists(kRecognizedURL);
// Test URL with app specific scheme.
SetPasteboardContent(kAppSpecificURL);
VerifyClipboardURLExists(kAppSpecificURL);
// Test URL without app specific scheme.
ResetClipboardRecentContent(std::string(), base::TimeDelta::FromDays(10));
SetPasteboardContent(kAppSpecificURL);
VerifyClipboardURLDoesNotExist();
}
TEST_F(ClipboardRecentContentIOSTest, PasteboardURLObsolescence) {
SetPasteboardContent(kRecognizedURL);
// Test that recent pasteboard data is provided.
VerifyClipboardURLExists(kRecognizedURL);
VerifyClipboardTextExists(kRecognizedURL);
// Test that old pasteboard data is not provided.
SetStoredPasteboardChangeDate(
[NSDate dateWithTimeIntervalSinceNow:-kLongerThanMaxAge]);
VerifyClipboardURLDoesNotExist();
VerifyClipboardTextDoesNotExist();
// Tests that if chrome is relaunched, old pasteboard data is still
// not provided.
ResetClipboardRecentContent(kAppSpecificScheme,
base::TimeDelta::FromDays(10));
VerifyClipboardURLDoesNotExist();
VerifyClipboardTextDoesNotExist();
SimulateDeviceRestart();
// Tests that if the device is restarted, old pasteboard data is still
// not provided.
VerifyClipboardURLDoesNotExist();
VerifyClipboardTextDoesNotExist();
}
// Checks that if the user suppresses content, no text will be returned,
// and if the text changes, the new text will be returned again.
TEST_F(ClipboardRecentContentIOSTest, SupressedPasteboardText) {
SetPasteboardContent(kRecognizedURL);
// Test that recent pasteboard data is provided.
VerifyClipboardURLExists(kRecognizedURL);
VerifyClipboardTextExists(kRecognizedURL);
// Suppress the content of the pasteboard.
clipboard_content_->SuppressClipboardContent();
// Check that the pasteboard content is suppressed.
VerifyClipboardURLDoesNotExist();
VerifyClipboardTextDoesNotExist();
// Create a new clipboard content to test persistence.
ResetClipboardRecentContent(kAppSpecificScheme,
base::TimeDelta::FromDays(10));
// Check that the pasteboard content is still suppressed.
VerifyClipboardURLDoesNotExist();
VerifyClipboardTextDoesNotExist();
// Check that even if the device is restarted, pasteboard content is
// still suppressed.
SimulateDeviceRestart();
VerifyClipboardURLDoesNotExist();
VerifyClipboardTextDoesNotExist();
// Check that if the pasteboard changes, the new content is not
// supressed anymore.
SetPasteboardContent(kRecognizedURL2);
VerifyClipboardURLExists(kRecognizedURL2);
VerifyClipboardTextExists(kRecognizedURL2);
}
// Checks that if the user suppresses content, no image will be returned,
// and if the image changes, the new image will be returned again.
TEST_F(ClipboardRecentContentIOSTest, SupressedPasteboardImage) {
SetPasteboardImage(TestUIImage());
// Test that recent pasteboard data is provided.
VerifyIfClipboardImageExists(true);
// Suppress the content of the pasteboard.
clipboard_content_->SuppressClipboardContent();
// Check that the pasteboard content is suppressed.
VerifyIfClipboardImageExists(false);
// Create a new clipboard content to test persistence.
ResetClipboardRecentContent(kAppSpecificScheme,
base::TimeDelta::FromDays(10));
// Check that the pasteboard content is still suppressed.
VerifyIfClipboardImageExists(false);
// Check that even if the device is restarted, pasteboard content is
// still suppressed.
SimulateDeviceRestart();
VerifyIfClipboardImageExists(false);
// Check that if the pasteboard changes, the new content is not
// supressed anymore.
SetPasteboardImage(TestUIImage([UIColor greenColor]));
VerifyIfClipboardImageExists(true);
}
// Checks that if user copies something other than a string we don't cache the
// string in pasteboard.
TEST_F(ClipboardRecentContentIOSTest, AddingNonStringRemovesCachedString) {
SetPasteboardContent(kRecognizedURL);
// Test that recent pasteboard data is provided as text and url.
VerifyClipboardURLExists(kRecognizedURL);
VerifyClipboardTextExists(kRecognizedURL);
// Image pasteboard should be empty
VerifyIfClipboardImageExists(false);
// Overwrite pasteboard with an image.
SetPasteboardImage(TestUIImage());
// Url and text pasteboard should appear empty.
VerifyClipboardURLDoesNotExist();
VerifyClipboardTextDoesNotExist();
// Image pasteboard should be full
VerifyIfClipboardImageExists(true);
// Tests that if URL is added again, pasteboard provides it normally.
SetPasteboardContent(kRecognizedURL);
VerifyClipboardURLExists(kRecognizedURL);
VerifyClipboardTextExists(kRecognizedURL);
// Image pasteboard should be empty
VerifyIfClipboardImageExists(false);
}