Commit 40f1bad5 authored by Justin Cohen's avatar Justin Cohen Committed by Commit Bot

Revert "Fix iOS Omnibox Clipboard Suggestions to not immediately read clipboard"

This reverts commit 0ab91ac7.

Reason for revert: Failures starting in:
https://ci.chromium.org/p/chromium/builders/ci/ios14-sdk-simulator/2281

* ClipboardRecentContentIOSTest.AddingNonStringRemovesCachedString
* ClipboardRecentContentIOSTest.PasteboardURLObsolescence
* ClipboardRecentContentIOSTest.SchemeFiltering
* ClipboardRecentContentIOSTest.SuppressedPasteboardImage
* ClipboardRecentContentIOSTest.SuppressedPasteboardText

https://logs.chromium.org/logs/chromium/buildbucket/cr-buildbucket.appspot.com/8872067354517054672/+/steps/components_unittests_iPhone_6s_14.0_on_Mac-10.15/0/stdout

Original change's description:
> Fix iOS Omnibox Clipboard Suggestions to not immediately read clipboard
> 
> The basic idea here is to factor out the match creation methods. On iOS
> 14, if the clipboard contains content, we create a blank match of the
> correct type (one without any destination_url). Then, when the match
> is selected for opening, we can ask the clipboard_provider for a new
> match using the proper text, and open that one instead.
> 
> For other platforms, we can keep using the old method, where we access
> the clipboard immediately and construct the destination_url at match
> creation time. iOS 14 also uses this behavior if there is cached
> clipboard content.
> 
> Bug: 1105869
> Change-Id: I70d26f4bcc485e4dc9073db2257161355adc8a40
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2346290
> Commit-Queue: Robbie Gibson <rkgibson@google.com>
> Reviewed-by: Ted Choc <tedchoc@chromium.org>
> Reviewed-by: Justin Donnelly <jdonnelly@chromium.org>
> Reviewed-by: manuk hovanesian <manukh@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#797671}

TBR=jdonnelly@chromium.org,tedchoc@chromium.org,manukh@chromium.org,rkgibson@google.com

Change-Id: I170940bf76f9e60ab0eb9d15e549fd4a62de45d3
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1105869
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2354524Reviewed-by: default avatarJustin Cohen <justincohen@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797803}
parent 03358347
...@@ -43,8 +43,18 @@ int AutocompleteClassifier::DefaultOmniboxProviders() { ...@@ -43,8 +43,18 @@ int AutocompleteClassifier::DefaultOmniboxProviders() {
#if !defined(OS_ANDROID) && !defined(OS_IOS) #if !defined(OS_ANDROID) && !defined(OS_IOS)
// Custom search engines cannot be used on mobile. // Custom search engines cannot be used on mobile.
AutocompleteProvider::TYPE_KEYWORD | AutocompleteProvider::TYPE_KEYWORD |
#else #endif
#if defined(OS_ANDROID)
AutocompleteProvider::TYPE_CLIPBOARD | AutocompleteProvider::TYPE_CLIPBOARD |
#endif
#if defined(OS_IOS)
// On iOS 14, a notification appears whenever the clipboard is accessed.
// The clipboard provider accesses the clipboard every time the omnibox is
// opened. Until a better solution is found, disable the clipboard
// provider temporarily. See crbug.com/1098722.
(!base::ios::IsRunningOnIOS14OrLater()
? AutocompleteProvider::TYPE_CLIPBOARD
: 0) |
#endif #endif
AutocompleteProvider::TYPE_ZERO_SUGGEST | AutocompleteProvider::TYPE_ZERO_SUGGEST |
AutocompleteProvider::TYPE_ZERO_SUGGEST_LOCAL_HISTORY | AutocompleteProvider::TYPE_ZERO_SUGGEST_LOCAL_HISTORY |
......
...@@ -320,10 +320,9 @@ AutocompleteController::AutocompleteController( ...@@ -320,10 +320,9 @@ AutocompleteController::AutocompleteController(
// ClipboardRecentContent can be null in iOS tests. For non-iOS, we // ClipboardRecentContent can be null in iOS tests. For non-iOS, we
// create a ClipboardRecentContent as above (for both Chrome and tests). // create a ClipboardRecentContent as above (for both Chrome and tests).
if (ClipboardRecentContent::GetInstance()) { if (ClipboardRecentContent::GetInstance()) {
clipboard_provider_ = new ClipboardProvider( providers_.push_back(new ClipboardProvider(
provider_client_.get(), this, history_url_provider_, provider_client_.get(), this, history_url_provider_,
ClipboardRecentContent::GetInstance()); ClipboardRecentContent::GetInstance()));
providers_.push_back(clipboard_provider_);
} }
} }
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/omnibox/browser/autocomplete_provider_listener.h"
#include "components/omnibox/browser/autocomplete_result.h" #include "components/omnibox/browser/autocomplete_result.h"
class ClipboardProvider;
class DocumentProvider; class DocumentProvider;
class HistoryURLProvider; class HistoryURLProvider;
class KeywordProvider; class KeywordProvider;
...@@ -161,7 +160,6 @@ class AutocompleteController : public AutocompleteProviderListener, ...@@ -161,7 +160,6 @@ class AutocompleteController : public AutocompleteProviderListener,
} }
KeywordProvider* keyword_provider() const { return keyword_provider_; } KeywordProvider* keyword_provider() const { return keyword_provider_; }
SearchProvider* search_provider() const { return search_provider_; } SearchProvider* search_provider() const { return search_provider_; }
ClipboardProvider* clipboard_provider() const { return clipboard_provider_; }
const AutocompleteInput& input() const { return input_; } const AutocompleteInput& input() const { return input_; }
const AutocompleteResult& result() const { return result_; } const AutocompleteResult& result() const { return result_; }
...@@ -296,8 +294,6 @@ class AutocompleteController : public AutocompleteProviderListener, ...@@ -296,8 +294,6 @@ class AutocompleteController : public AutocompleteProviderListener,
OnDeviceHeadProvider* on_device_head_provider_; OnDeviceHeadProvider* on_device_head_provider_;
ClipboardProvider* clipboard_provider_;
// Input passed to Start. // Input passed to Start.
AutocompleteInput input_; AutocompleteInput input_;
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
class AutocompleteProviderClient; class AutocompleteProviderClient;
class ClipboardRecentContent; class ClipboardRecentContent;
class HistoryURLProvider; class HistoryURLProvider;
enum class ClipboardContentType;
// Autocomplete provider offering content based on the clipboard's content. // Autocomplete provider offering content based on the clipboard's content.
class ClipboardProvider : public AutocompleteProvider { class ClipboardProvider : public AutocompleteProvider {
...@@ -25,23 +24,6 @@ class ClipboardProvider : public AutocompleteProvider { ...@@ -25,23 +24,6 @@ class ClipboardProvider : public AutocompleteProvider {
ClipboardProvider(const ClipboardProvider&) = delete; ClipboardProvider(const ClipboardProvider&) = delete;
ClipboardProvider& operator=(const ClipboardProvider&) = delete; ClipboardProvider& operator=(const ClipboardProvider&) = delete;
// Returns a new AutocompleteMatch clipboard match that will navigate to the
// given copied url. Used to construct a match later when the URL is not
// available at match creation time (e.g. iOS 14).
AutocompleteMatch NewClipboardURLMatch(GURL url);
// Returns a new AutocompleteMatch clipboard match that will search for the
// given copied text. Used to construct a match later when the text is not
// available at match creation time (e.g. iOS 14).
base::Optional<AutocompleteMatch> NewClipboardTextMatch(base::string16 text);
using ClipboardImageMatchCallback =
base::OnceCallback<void(base::Optional<AutocompleteMatch>)>;
// Returns a new AutocompleteMatch clipboard match that will search for the
// given copied image. Used to construct a match later when the image is not
// available at match creation time (e.g. iOS 14).
void NewClipboardImageMatch(gfx::Image image,
ClipboardImageMatchCallback callback);
// AutocompleteProvider implementation. // AutocompleteProvider implementation.
void Start(const AutocompleteInput& input, bool minimal_changes) override; void Start(const AutocompleteInput& input, bool minimal_changes) override;
void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; void Stop(bool clear_cached_results, bool due_to_user_inactivity) override;
...@@ -61,72 +43,23 @@ class ClipboardProvider : public AutocompleteProvider { ...@@ -61,72 +43,23 @@ class ClipboardProvider : public AutocompleteProvider {
const AutocompleteMatch& match, const AutocompleteMatch& match,
const base::TimeDelta clipboard_contents_age); const base::TimeDelta clipboard_contents_age);
// Uses asynchronous clipboard APIs to check which content types have // If there is a url copied to the clipboard, use it to create a match.
// clipboard data without actually accessing the data. If any do, then one
// clipboard match is created. Calls back to |OnReceiveClipboardContent| with
// the result.
void CheckClipboardContent(const AutocompleteInput& input);
// Called when the clipboard data is returned from the asynchronous call.
void OnReceiveClipboardContent(const AutocompleteInput& input,
base::TimeDelta clipboard_contents_age,
std::set<ClipboardContentType> matched_types);
// Checks whether the current template url supports text searches.
bool TemplateURLSupportsTextSearch();
// Checks whether the current template url supports image searches.
bool TemplateURLSupportsImageSearch();
// Returns a URL match with no URL. This can be used if the clipboard content
// is inaccessible at match creation time (e.g. iOS 14).
AutocompleteMatch NewBlankURLMatch();
// Returns a text match with no text. This can be used if the clipboard
// content is inaccessible at match creation time (e.g. iOS 14).
AutocompleteMatch NewBlankTextMatch();
// Returns a image match with no attached image. This can be used if the
// clipboard content is inaccessible at match creation time (e.g. iOS 14).
AutocompleteMatch NewBlankImageMatch();
// If there is a url copied to the clipboard and accessing it will not show a
// clipboard access notification (e.g. iOS 14), use it to create a match.
// |read_clipboard_content| will be filled with false if the clipboard didn't
// have any content (either because there was none or because accessing it
// would have shown a clipboard access notification, and true if there was
// content.
base::Optional<AutocompleteMatch> CreateURLMatch( base::Optional<AutocompleteMatch> CreateURLMatch(
const AutocompleteInput& input, const AutocompleteInput& input);
bool* read_clipboard_content); // If there is text copied to the clipboard, use it to create a match.
// If there is text copied to the clipboard and accessing it will not show a
// clipboard access notification (e.g. iOS 14), use it to create a match.
// |read_clipboard_content| will be filled with false if the clipboard didn't
// have any content (either because there was none or because accessing it
// would have shown a clipboard access notification, and true if there was
// content.
base::Optional<AutocompleteMatch> CreateTextMatch( base::Optional<AutocompleteMatch> CreateTextMatch(
const AutocompleteInput& input, const AutocompleteInput& input);
bool* read_clipboard_content); // If there is an image copied to the clipboard, use it to create a match.
// If there is an image copied to the clipboard and accessing it will not show
// a clipboard access notification (e.g. iOS 14), use it to create a match.
// The image match is asynchronous (because constructing the image post data // The image match is asynchronous (because constructing the image post data
// takes time), so instead of returning an optional match like the other // takes time), so instead of returning an optional match like the other
// Create functions, it returns a boolean indicating whether there will be a // Create functions, it returns a boolean indicating whether there will be a
// match. // match.
bool CreateImageMatch(const AutocompleteInput& input); bool CreateImageMatch(const AutocompleteInput& input);
// Handles the callback response from |CreateImageMatch| and turns the image // Called when received image data from clipboard.
// into an AutocompleteMatch. void OnReceiveImage(const AutocompleteInput& input,
void CreateImageMatchCallback(const AutocompleteInput& input, TemplateURLService* url_service,
const base::TimeDelta clipboard_contents_age, base::TimeDelta clipboard_contents_age,
base::Optional<gfx::Image>);
// Handles the callback response from |CreateImageMatchCallback| and adds the
// created AutocompleteMatch to the matches list.
void AddImageMatchCallback(const AutocompleteInput& input,
const base::TimeDelta clipboard_contents_age,
base::Optional<AutocompleteMatch> match);
// Called when image data is received from clipboard.
void OnReceiveImage(ClipboardImageMatchCallback callback,
base::Optional<gfx::Image> optional_image); base::Optional<gfx::Image> optional_image);
// Resize and encode the image data into bytes. This can take some time if the // Resize and encode the image data into bytes. This can take some time if the
...@@ -136,7 +69,9 @@ class ClipboardProvider : public AutocompleteProvider { ...@@ -136,7 +69,9 @@ class ClipboardProvider : public AutocompleteProvider {
// Construct the actual image match once the image has been encoded into // Construct the actual image match once the image has been encoded into
// bytes. This should be called back on the main thread. // bytes. This should be called back on the main thread.
void ConstructImageMatchCallback( void ConstructImageMatchCallback(
ClipboardImageMatchCallback callback, const AutocompleteInput& input,
TemplateURLService* url_service,
base::TimeDelta clipboard_contents_age,
scoped_refptr<base::RefCountedMemory> image_bytes); scoped_refptr<base::RefCountedMemory> image_bytes);
AutocompleteProviderClient* client_; AutocompleteProviderClient* client_;
......
...@@ -82,10 +82,6 @@ class ClipboardProviderTest : public testing::Test, ...@@ -82,10 +82,6 @@ class ClipboardProviderTest : public testing::Test,
return input; return input;
} }
void MatchesImageCallback(base::Optional<AutocompleteMatch> match) {
matches_image_match_ = match;
}
protected: protected:
// AutocompleteProviderListener: // AutocompleteProviderListener:
void OnProviderUpdate(bool updated_matches) override; void OnProviderUpdate(bool updated_matches) override;
...@@ -94,8 +90,6 @@ class ClipboardProviderTest : public testing::Test, ...@@ -94,8 +90,6 @@ class ClipboardProviderTest : public testing::Test,
FakeClipboardRecentContent clipboard_content_; FakeClipboardRecentContent clipboard_content_;
std::unique_ptr<MockAutocompleteProviderClient> client_; std::unique_ptr<MockAutocompleteProviderClient> client_;
scoped_refptr<ClipboardProvider> provider_; scoped_refptr<ClipboardProvider> provider_;
base::Optional<AutocompleteMatch> matches_image_match_;
}; };
void ClipboardProviderTest::OnProviderUpdate(bool updated_matches) { void ClipboardProviderTest::OnProviderUpdate(bool updated_matches) {
...@@ -108,18 +102,12 @@ TEST_F(ClipboardProviderTest, NotFromOmniboxFocus) { ...@@ -108,18 +102,12 @@ TEST_F(ClipboardProviderTest, NotFromOmniboxFocus) {
} }
TEST_F(ClipboardProviderTest, EmptyClipboard) { TEST_F(ClipboardProviderTest, EmptyClipboard) {
auto template_url_service = std::make_unique<TemplateURLService>(
/*initializers=*/nullptr, /*count=*/0);
client_->set_template_url_service(std::move(template_url_service));
ClearClipboard(); ClearClipboard();
provider_->Start(CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS), false); provider_->Start(CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS), false);
EXPECT_TRUE(provider_->matches().empty()); EXPECT_TRUE(provider_->matches().empty());
} }
TEST_F(ClipboardProviderTest, ClipboardIsCurrentURL) { TEST_F(ClipboardProviderTest, ClipboardIsCurrentURL) {
auto template_url_service = std::make_unique<TemplateURLService>(
/*initializers=*/nullptr, /*count=*/0);
client_->set_template_url_service(std::move(template_url_service));
SetClipboardUrl(GURL(kCurrentURL)); SetClipboardUrl(GURL(kCurrentURL));
provider_->Start(CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS), false); provider_->Start(CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS), false);
EXPECT_TRUE(provider_->matches().empty()); EXPECT_TRUE(provider_->matches().empty());
...@@ -164,21 +152,20 @@ TEST_F(ClipboardProviderTest, MatchesImage) { ...@@ -164,21 +152,20 @@ TEST_F(ClipboardProviderTest, MatchesImage) {
base::Feature imageFeature = base::Feature imageFeature =
omnibox::kEnableClipboardProviderImageSuggestions; omnibox::kEnableClipboardProviderImageSuggestions;
feature_list.InitAndEnableFeature(imageFeature); feature_list.InitAndEnableFeature(imageFeature);
auto template_url_service = TemplateURLService template_url_service(/*initializers=*/nullptr,
std::make_unique<TemplateURLService>(/*initializers=*/nullptr, /*count=*/0);
/*count=*/0); base::TimeDelta clipboard_age = base::TimeDelta::FromSeconds(5);
client_->set_template_url_service(std::move(template_url_service));
gfx::Image test_image = gfx::test::CreateImage(/*height=*/10, /*width=*/10); gfx::Image test_image = gfx::test::CreateImage(/*height=*/10, /*width=*/10);
scoped_refptr<base::RefCountedMemory> image_bytes = scoped_refptr<base::RefCountedMemory> image_bytes =
provider_->EncodeClipboardImage(*test_image.ToImageSkia()); provider_->EncodeClipboardImage(*test_image.ToImageSkia());
ASSERT_TRUE(image_bytes); ASSERT_TRUE(image_bytes);
provider_->ConstructImageMatchCallback( provider_->ConstructImageMatchCallback(
base::BindOnce(&ClipboardProviderTest::MatchesImageCallback, CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS),
base::Unretained(this)), &template_url_service, clipboard_age, image_bytes);
image_bytes); ASSERT_GE(provider_->matches().size(), 1U);
ASSERT_TRUE(matches_image_match_); EXPECT_EQ(AutocompleteMatchType::CLIPBOARD_IMAGE,
EXPECT_EQ(AutocompleteMatchType::CLIPBOARD_IMAGE, matches_image_match_->type); provider_->matches().back().type);
} }
TEST_F(ClipboardProviderTest, DeleteMatch) { TEST_F(ClipboardProviderTest, DeleteMatch) {
......
...@@ -33,17 +33,21 @@ class ClipboardRecentContent { ...@@ -33,17 +33,21 @@ class ClipboardRecentContent {
static void SetInstance(std::unique_ptr<ClipboardRecentContent> new_instance); static void SetInstance(std::unique_ptr<ClipboardRecentContent> new_instance);
// Returns clipboard content as URL, if it has a compatible type, // Returns clipboard content as URL, if it has a compatible type,
// is recent enough, has not been suppressed and will not trigger a system // is recent enough and has not been suppressed.
// notification that the clipboard has been accessed.
virtual base::Optional<GURL> GetRecentURLFromClipboard() = 0; virtual base::Optional<GURL> GetRecentURLFromClipboard() = 0;
// Returns clipboard content as text, if it has a compatible type, // Returns clipboard content as text, if it has a compatible type,
// is recent enough, has not been suppressed and will not trigger a system // is recent enough and has not been suppressed.
// notification that the clipboard has been accessed.
virtual base::Optional<base::string16> GetRecentTextFromClipboard() = 0; virtual base::Optional<base::string16> GetRecentTextFromClipboard() = 0;
// Return if system's clipboard contains an image that will not trigger a using GetRecentImageCallback =
// system notification that the clipboard has been accessed. base::OnceCallback<void(base::Optional<gfx::Image>)>;
// Returns clipboard content as image to |GetRecentImageCallback|, if it has a
// compatible type, is recent enough and has not been suppressed.
virtual void GetRecentImageFromClipboard(GetRecentImageCallback callback) = 0;
// Return if system's clipboard contains an image.
virtual bool HasRecentImageFromClipboard() = 0; virtual bool HasRecentImageFromClipboard() = 0;
/* /*
...@@ -55,27 +59,19 @@ class ClipboardRecentContent { ...@@ -55,27 +59,19 @@ class ClipboardRecentContent {
using GetRecentURLCallback = base::OnceCallback<void(base::Optional<GURL>)>; using GetRecentURLCallback = base::OnceCallback<void(base::Optional<GURL>)>;
using GetRecentTextCallback = using GetRecentTextCallback =
base::OnceCallback<void(base::Optional<base::string16>)>; base::OnceCallback<void(base::Optional<base::string16>)>;
using GetRecentImageCallback =
base::OnceCallback<void(base::Optional<gfx::Image>)>;
// Returns whether the clipboard contains a URL to |HasDataCallback| if it // Returns whether the clipboard contains a URL to |HasDataCallback| if it
// is recent enough and has not been suppressed. // is recent enough and has not been suppressed.
virtual void HasRecentContentFromClipboard( virtual void HasRecentContentFromClipboard(
std::set<ClipboardContentType> types, std::set<ClipboardContentType> types,
HasDataCallback callback) = 0; HasDataCallback callback) = 0;
// Returns clipboard content as URL to |GetRecentURLCallback|, if it has a // Returns clipboard content as URL to |GetRecentURLCallback|, if it has a
// compatible type, is recent enough and has not been suppressed. // compatible type, is recent enough and has not been suppressed.
virtual void GetRecentURLFromClipboard(GetRecentURLCallback callback) = 0; virtual void GetRecentURLFromClipboard(GetRecentURLCallback callback) = 0;
// Returns clipboard content as a string to |GetRecentTextCallback|, if it has // Returns clipboard content as a string to |GetRecentTextCallback|, if it has
// a compatible type, is recent enough and has not been suppressed. // a compatible type, is recent enough and has not been suppressed.
virtual void GetRecentTextFromClipboard(GetRecentTextCallback callback) = 0; virtual void GetRecentTextFromClipboard(GetRecentTextCallback callback) = 0;
// Returns clipboard content as image to |GetRecentImageCallback|, if it has a
// compatible type, is recent enough and has not been suppressed.
virtual void GetRecentImageFromClipboard(GetRecentImageCallback callback) = 0;
// Returns how old the content of the clipboard is. // Returns how old the content of the clipboard is.
virtual base::TimeDelta GetClipboardContentAge() const = 0; virtual base::TimeDelta GetClipboardContentAge() const = 0;
......
...@@ -39,18 +39,15 @@ extern ContentType const ContentTypeImage; ...@@ -39,18 +39,15 @@ extern ContentType const ContentTypeImage;
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
// Returns the copied URL if the clipboard contains a recent URL that has not // Returns the copied URL if the clipboard contains a recent URL that has not
// been suppressed and will not trigger a pasteboard access notification. // been supressed. Otherwise, returns nil.
// Otherwise, returns nil.
- (NSURL*)recentURLFromClipboard; - (NSURL*)recentURLFromClipboard;
// Returns the copied string if the clipboard contains a recent string that has // Returns the copied string if the clipboard contains a recent string that has
// not been suppresed and will not trigger a pasteboard access notification. // not been suppresed. Otherwise, returns nil.
// Otherwise, returns nil.
- (NSString*)recentTextFromClipboard; - (NSString*)recentTextFromClipboard;
// Returns the copied image if the clipboard contains a recent image that has // Returns the copied image if the clipboard contains a recent image that has
// not been suppressed and will not trigger a pasteboard access notification. // not been suppressed. Otherwise, returns nil.
// Otherwise, returns nil.
- (UIImage*)recentImageFromClipboard; - (UIImage*)recentImageFromClipboard;
// Uses the new iOS 14 pasteboard detection pattern API to asynchronously detect // Uses the new iOS 14 pasteboard detection pattern API to asynchronously detect
......
...@@ -131,13 +131,8 @@ NSString* const kPasteboardChangeDateKey = @"PasteboardChangeDate"; ...@@ -131,13 +131,8 @@ NSString* const kPasteboardChangeDateKey = @"PasteboardChangeDate";
if (![self shouldReturnValueOfClipboard]) if (![self shouldReturnValueOfClipboard])
return nil; return nil;
if (@available(iOS 14, *)) { if (!self.cachedURL) {
// On iOS 14, don't actually access the pasteboard in this method. This self.cachedURL = [self URLFromPasteboard];
// prevents the pasteboard access notification from appearing.
} else {
if (!self.cachedURL) {
self.cachedURL = [self URLFromPasteboard];
}
} }
return self.cachedURL; return self.cachedURL;
} }
...@@ -148,13 +143,8 @@ NSString* const kPasteboardChangeDateKey = @"PasteboardChangeDate"; ...@@ -148,13 +143,8 @@ NSString* const kPasteboardChangeDateKey = @"PasteboardChangeDate";
if (![self shouldReturnValueOfClipboard]) if (![self shouldReturnValueOfClipboard])
return nil; return nil;
if (@available(iOS 14, *)) { if (!self.cachedText) {
// On iOS 14, don't actually access the pasteboard in this method. This self.cachedText = UIPasteboard.generalPasteboard.string;
// prevents the pasteboard access notification from appearing.
} else {
if (!self.cachedText) {
self.cachedText = UIPasteboard.generalPasteboard.string;
}
} }
return self.cachedText; return self.cachedText;
} }
...@@ -165,13 +155,8 @@ NSString* const kPasteboardChangeDateKey = @"PasteboardChangeDate"; ...@@ -165,13 +155,8 @@ NSString* const kPasteboardChangeDateKey = @"PasteboardChangeDate";
if (![self shouldReturnValueOfClipboard]) if (![self shouldReturnValueOfClipboard])
return nil; return nil;
if (@available(iOS 14, *)) { if (!self.cachedImage) {
// On iOS 14, don't actually access the pasteboard in this method. This self.cachedImage = UIPasteboard.generalPasteboard.image;
// prevents the pasteboard access notification from appearing.
} else {
if (!self.cachedImage) {
self.cachedImage = UIPasteboard.generalPasteboard.image;
}
} }
return self.cachedImage; return self.cachedImage;
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "base/system/sys_info.h" #include "base/system/sys_info.h"
#include "base/threading/sequenced_task_runner_handle.h"
#import "components/open_from_clipboard/clipboard_recent_content_impl_ios.h" #import "components/open_from_clipboard/clipboard_recent_content_impl_ios.h"
#import "net/base/mac/url_conversions.h" #import "net/base/mac/url_conversions.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -117,6 +116,19 @@ ClipboardRecentContentIOS::GetRecentTextFromClipboard() { ...@@ -117,6 +116,19 @@ ClipboardRecentContentIOS::GetRecentTextFromClipboard() {
return base::SysNSStringToUTF16(text_from_pasteboard); return base::SysNSStringToUTF16(text_from_pasteboard);
} }
void ClipboardRecentContentIOS::GetRecentImageFromClipboard(
GetRecentImageCallback callback) {
__block GetRecentImageCallback callback_for_block = std::move(callback);
[implementation_ recentImageFromClipboardAsync:^(UIImage* image) {
if (!image) {
std::move(callback_for_block).Run(base::nullopt);
return;
}
std::move(callback_for_block).Run(gfx::Image(image));
}];
}
bool ClipboardRecentContentIOS::HasRecentImageFromClipboard() { bool ClipboardRecentContentIOS::HasRecentImageFromClipboard() {
return GetRecentImageFromClipboardInternal().has_value(); return GetRecentImageFromClipboardInternal().has_value();
} }
...@@ -129,93 +141,39 @@ void ClipboardRecentContentIOS::HasRecentContentFromClipboard( ...@@ -129,93 +141,39 @@ void ClipboardRecentContentIOS::HasRecentContentFromClipboard(
for (ClipboardContentType type : types) { for (ClipboardContentType type : types) {
[ios_types addObject:ContentTypeFromClipboardContentType(type)]; [ios_types addObject:ContentTypeFromClipboardContentType(type)];
} }
// The iOS methods for checking clipboard content call their callbacks on an [implementation_ hasContentMatchingTypes:ios_types
// arbitrary thread. As Objective-C doesn't have very good thread-management completionHandler:^(NSSet<ContentType>* results) {
// techniques, make sure this method calls its callback on the same thread std::set<ClipboardContentType> matching_types;
// that it was called on. for (ContentType type in results) {
scoped_refptr<base::SequencedTaskRunner> task_runner = matching_types.insert(
base::SequencedTaskRunnerHandle::Get(); ClipboardContentTypeFromContentType(type));
[implementation_ }
hasContentMatchingTypes:ios_types std::move(callback_for_block).Run(matching_types);
completionHandler:^(NSSet<ContentType>* results) { }];
std::set<ClipboardContentType> matching_types;
for (ContentType type in results) {
matching_types.insert(
ClipboardContentTypeFromContentType(type));
}
task_runner->PostTask(
FROM_HERE, base::BindOnce(^{
std::move(callback_for_block).Run(matching_types);
}));
}];
} }
void ClipboardRecentContentIOS::GetRecentURLFromClipboard( void ClipboardRecentContentIOS::GetRecentURLFromClipboard(
GetRecentURLCallback callback) { GetRecentURLCallback callback) {
__block GetRecentURLCallback callback_for_block = std::move(callback); __block GetRecentURLCallback callback_for_block = std::move(callback);
// The iOS methods for checking clipboard content call their callbacks on an
// arbitrary thread. As Objective-C doesn't have very good thread-management
// techniques, make sure this method calls its callback on the same thread
// that it was called on.
scoped_refptr<base::SequencedTaskRunner> task_runner =
base::SequencedTaskRunnerHandle::Get();
[implementation_ recentURLFromClipboardAsync:^(NSURL* url) { [implementation_ recentURLFromClipboardAsync:^(NSURL* url) {
GURL converted_url = net::GURLWithNSURL(url); GURL converted_url = net::GURLWithNSURL(url);
if (!converted_url.is_valid()) { if (!converted_url.is_valid()) {
task_runner->PostTask(FROM_HERE, base::BindOnce(^{ std::move(callback_for_block).Run(base::nullopt);
std::move(callback_for_block).Run(base::nullopt);
}));
return; return;
} }
task_runner->PostTask(FROM_HERE, base::BindOnce(^{ std::move(callback_for_block).Run(converted_url);
std::move(callback_for_block).Run(converted_url);
}));
}]; }];
} }
void ClipboardRecentContentIOS::GetRecentTextFromClipboard( void ClipboardRecentContentIOS::GetRecentTextFromClipboard(
GetRecentTextCallback callback) { GetRecentTextCallback callback) {
__block GetRecentTextCallback callback_for_block = std::move(callback); __block GetRecentTextCallback callback_for_block = std::move(callback);
// The iOS methods for checking clipboard content call their callbacks on an
// arbitrary thread. As Objective-C doesn't have very good thread-management
// techniques, make sure this method calls its callback on the same thread
// that it was called on.
scoped_refptr<base::SequencedTaskRunner> task_runner =
base::SequencedTaskRunnerHandle::Get();
[implementation_ recentTextFromClipboardAsync:^(NSString* text) { [implementation_ recentTextFromClipboardAsync:^(NSString* text) {
if (!text) { if (!text) {
task_runner->PostTask(FROM_HERE, base::BindOnce(^{ std::move(callback_for_block).Run(base::nullopt);
std::move(callback_for_block).Run(base::nullopt);
}));
return;
}
task_runner->PostTask(
FROM_HERE, base::BindOnce(^{
std::move(callback_for_block).Run(base::SysNSStringToUTF16(text));
}));
}];
}
void ClipboardRecentContentIOS::GetRecentImageFromClipboard(
GetRecentImageCallback callback) {
__block GetRecentImageCallback callback_for_block = std::move(callback);
// The iOS methods for checking clipboard content call their callbacks on an
// arbitrary thread. As Objective-C doesn't have very good thread-management
// techniques, make sure this method calls its callback on the same thread
// that it was called on.
scoped_refptr<base::SequencedTaskRunner> task_runner =
base::SequencedTaskRunnerHandle::Get();
[implementation_ recentImageFromClipboardAsync:^(UIImage* image) {
if (!image) {
task_runner->PostTask(FROM_HERE, base::BindOnce(^{
std::move(callback_for_block).Run(base::nullopt);
}));
return; return;
} }
task_runner->PostTask( std::move(callback_for_block).Run(base::SysNSStringToUTF16(text));
FROM_HERE, base::BindOnce(^{
std::move(callback_for_block).Run(gfx::Image(image));
}));
}]; }];
} }
......
...@@ -39,8 +39,6 @@ class OmniboxViewIOS : public OmniboxView, ...@@ -39,8 +39,6 @@ class OmniboxViewIOS : public OmniboxView,
ChromeBrowserState* browser_state, ChromeBrowserState* browser_state,
id<OmniboxCommands> omnibox_focuser); id<OmniboxCommands> omnibox_focuser);
~OmniboxViewIOS() override;
void SetPopupProvider(OmniboxPopupProvider* provider) { void SetPopupProvider(OmniboxPopupProvider* provider) {
popup_provider_ = provider; popup_provider_ = provider;
} }
...@@ -51,41 +49,6 @@ class OmniboxViewIOS : public OmniboxView, ...@@ -51,41 +49,6 @@ class OmniboxViewIOS : public OmniboxView,
security_state::SecurityLevel security_level, security_state::SecurityLevel security_level,
bool in_dark_mode); bool in_dark_mode);
void OnReceiveClipboardURLForOpenMatch(
const AutocompleteMatch& match,
WindowOpenDisposition disposition,
const GURL& alternate_nav_url,
const base::string16& pasted_text,
size_t selected_line,
base::TimeTicks match_selection_timestamp,
base::Optional<GURL> optional_gurl);
void OnReceiveClipboardTextForOpenMatch(
const AutocompleteMatch& match,
WindowOpenDisposition disposition,
const GURL& alternate_nav_url,
const base::string16& pasted_text,
size_t selected_line,
base::TimeTicks match_selection_timestamp,
base::Optional<base::string16> optional_text);
void OnReceiveClipboardImageForOpenMatch(
const AutocompleteMatch& match,
WindowOpenDisposition disposition,
const GURL& alternate_nav_url,
const base::string16& pasted_text,
size_t selected_line,
base::TimeTicks match_selection_timestamp,
base::Optional<gfx::Image> optional_image);
void OnReceiveImageMatchForOpenMatch(
WindowOpenDisposition disposition,
const GURL& alternate_nav_url,
const base::string16& pasted_text,
size_t selected_line,
base::TimeTicks match_selection_timestamp,
base::Optional<AutocompleteMatch> optional_match);
// OmniboxView implementation. // OmniboxView implementation.
void OpenMatch(const AutocompleteMatch& match, void OpenMatch(const AutocompleteMatch& match,
WindowOpenDisposition disposition, WindowOpenDisposition disposition,
...@@ -236,9 +199,6 @@ class OmniboxViewIOS : public OmniboxView, ...@@ -236,9 +199,6 @@ class OmniboxViewIOS : public OmniboxView,
NSMutableAttributedString* attributing_display_string_; NSMutableAttributedString* attributing_display_string_;
OmniboxPopupProvider* popup_provider_; // weak OmniboxPopupProvider* popup_provider_; // weak
// Used to cancel clipboard callbacks if this is deallocated;
base::WeakPtrFactory<OmniboxViewIOS> weak_ptr_factory_{this};
}; };
#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_VIEW_IOS_H_ #endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_VIEW_IOS_H_
...@@ -17,12 +17,10 @@ ...@@ -17,12 +17,10 @@
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/clipboard_provider.h"
#include "components/omnibox/browser/location_bar_model.h" #include "components/omnibox/browser/location_bar_model.h"
#include "components/omnibox/browser/omnibox_edit_model.h" #include "components/omnibox/browser/omnibox_edit_model.h"
#include "components/omnibox/browser/omnibox_popup_model.h" #include "components/omnibox/browser/omnibox_popup_model.h"
#include "components/omnibox/common/omnibox_focus_state.h" #include "components/omnibox/common/omnibox_focus_state.h"
#include "components/open_from_clipboard/clipboard_recent_content.h"
#include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h" #include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/ui/commands/omnibox_commands.h" #import "ios/chrome/browser/ui/commands/omnibox_commands.h"
...@@ -97,8 +95,6 @@ OmniboxViewIOS::OmniboxViewIOS(OmniboxTextFieldIOS* field, ...@@ -97,8 +95,6 @@ OmniboxViewIOS::OmniboxViewIOS(OmniboxTextFieldIOS* field,
!base::ios::IsRunningOnOrLater(11, 2, 0); !base::ios::IsRunningOnOrLater(11, 2, 0);
} }
OmniboxViewIOS::~OmniboxViewIOS() = default;
void OmniboxViewIOS::OpenMatch(const AutocompleteMatch& match, void OmniboxViewIOS::OpenMatch(const AutocompleteMatch& match,
WindowOpenDisposition disposition, WindowOpenDisposition disposition,
const GURL& alternate_nav_url, const GURL& alternate_nav_url,
...@@ -110,125 +106,10 @@ void OmniboxViewIOS::OpenMatch(const AutocompleteMatch& match, ...@@ -110,125 +106,10 @@ void OmniboxViewIOS::OpenMatch(const AutocompleteMatch& match,
return; return;
} }
// Fill in clipboard matches if they don't have a destination URL.
if (match.destination_url.is_empty()) {
if (match.type == AutocompleteMatchType::CLIPBOARD_URL) {
ClipboardRecentContent* clipboard_recent_content =
ClipboardRecentContent::GetInstance();
clipboard_recent_content->GetRecentURLFromClipboard(base::BindOnce(
&OmniboxViewIOS::OnReceiveClipboardURLForOpenMatch,
weak_ptr_factory_.GetWeakPtr(), match, disposition, alternate_nav_url,
pasted_text, selected_line, match_selection_timestamp));
return;
} else if (match.type == AutocompleteMatchType::CLIPBOARD_TEXT) {
ClipboardRecentContent* clipboard_recent_content =
ClipboardRecentContent::GetInstance();
clipboard_recent_content->GetRecentTextFromClipboard(base::BindOnce(
&OmniboxViewIOS::OnReceiveClipboardTextForOpenMatch,
weak_ptr_factory_.GetWeakPtr(), match, disposition, alternate_nav_url,
pasted_text, selected_line, match_selection_timestamp));
return;
} else if (match.type == AutocompleteMatchType::CLIPBOARD_IMAGE) {
ClipboardRecentContent* clipboard_recent_content =
ClipboardRecentContent::GetInstance();
clipboard_recent_content->GetRecentImageFromClipboard(base::BindOnce(
&OmniboxViewIOS::OnReceiveClipboardImageForOpenMatch,
weak_ptr_factory_.GetWeakPtr(), match, disposition, alternate_nav_url,
pasted_text, selected_line, match_selection_timestamp));
return;
}
}
OmniboxView::OpenMatch(match, disposition, alternate_nav_url, pasted_text, OmniboxView::OpenMatch(match, disposition, alternate_nav_url, pasted_text,
selected_line, match_selection_timestamp); selected_line, match_selection_timestamp);
} }
void OmniboxViewIOS::OnReceiveClipboardURLForOpenMatch(
const AutocompleteMatch& match,
WindowOpenDisposition disposition,
const GURL& alternate_nav_url,
const base::string16& pasted_text,
size_t selected_line,
base::TimeTicks match_selection_timestamp,
base::Optional<GURL> optional_gurl) {
if (!optional_gurl) {
return;
}
GURL url = std::move(optional_gurl).value();
ClipboardProvider* clipboard_provider =
model()->autocomplete_controller()->clipboard_provider();
AutocompleteMatch new_match = clipboard_provider->NewClipboardURLMatch(url);
OmniboxView::OpenMatch(new_match, disposition, alternate_nav_url, pasted_text,
selected_line, match_selection_timestamp);
}
void OmniboxViewIOS::OnReceiveClipboardTextForOpenMatch(
const AutocompleteMatch& match,
WindowOpenDisposition disposition,
const GURL& alternate_nav_url,
const base::string16& pasted_text,
size_t selected_line,
base::TimeTicks match_selection_timestamp,
base::Optional<base::string16> optional_text) {
if (!optional_text) {
return;
}
base::string16 text = std::move(optional_text).value();
ClipboardProvider* clipboard_provider =
model()->autocomplete_controller()->clipboard_provider();
base::Optional<AutocompleteMatch> new_match =
clipboard_provider->NewClipboardTextMatch(text);
if (!new_match) {
return;
}
OmniboxView::OpenMatch(new_match.value(), disposition, alternate_nav_url,
pasted_text, selected_line, match_selection_timestamp);
}
void OmniboxViewIOS::OnReceiveClipboardImageForOpenMatch(
const AutocompleteMatch& match,
WindowOpenDisposition disposition,
const GURL& alternate_nav_url,
const base::string16& pasted_text,
size_t selected_line,
base::TimeTicks match_selection_timestamp,
base::Optional<gfx::Image> optional_image) {
if (!optional_image) {
return;
}
gfx::Image image = std::move(optional_image).value();
ClipboardProvider* clipboard_provider =
model()->autocomplete_controller()->clipboard_provider();
clipboard_provider->NewClipboardImageMatch(
image, base::BindOnce(&OmniboxViewIOS::OnReceiveImageMatchForOpenMatch,
weak_ptr_factory_.GetWeakPtr(), disposition,
alternate_nav_url, pasted_text, selected_line,
match_selection_timestamp));
}
void OmniboxViewIOS::OnReceiveImageMatchForOpenMatch(
WindowOpenDisposition disposition,
const GURL& alternate_nav_url,
const base::string16& pasted_text,
size_t selected_line,
base::TimeTicks match_selection_timestamp,
base::Optional<AutocompleteMatch> optional_match) {
if (!optional_match) {
return;
}
OmniboxView::OpenMatch(optional_match.value(), disposition, alternate_nav_url,
pasted_text, selected_line, match_selection_timestamp);
}
base::string16 OmniboxViewIOS::GetText() const { base::string16 OmniboxViewIOS::GetText() const {
return base::SysNSStringToUTF16([field_ displayedText]); return base::SysNSStringToUTF16([field_ displayedText]);
} }
......
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