Commit c5472233 authored by Sébastien Séguin-Gagnon's avatar Sébastien Séguin-Gagnon Committed by Commit Bot

[SH] Create the basic infrastructure for link-to-text on Bling.

Adds a link-to-text button when clicking on selected text in the
browser container.
Creates and hooks up a mediator and tab helper to handle the click
on the new link-to-text button.

Bug: 1134703
Change-Id: I72196fc7a95b81ea32700414c70a645af16bfc52
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2446202
Commit-Queue: sebsg <sebsg@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Reviewed-by: default avatarSebastien Lalancette <seblalancette@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814253}
parent 637d16ac
# 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.
source_set("link_to_text") {
sources = [
"link_to_text_tab_helper.h",
"link_to_text_tab_helper.mm",
"shared_highlight.h",
]
deps = [ "//ios/web/public" ]
configs += [ "//build/config/compiler:enable_arc" ]
}
// 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_LINK_TO_TEXT_LINK_TO_TEXT_TAB_HELPER_H_
#define IOS_CHROME_BROWSER_LINK_TO_TEXT_LINK_TO_TEXT_TAB_HELPER_H_
#import "base/macros.h"
#import "ios/chrome/browser/link_to_text/shared_highlight.h"
#import "ios/web/public/web_state_observer.h"
#import "ios/web/public/web_state_user_data.h"
// A tab helper that observes WebState and triggers the link to text generation
// Javascript library on it.
class LinkToTextTabHelper : public web::WebStateObserver,
public web::WebStateUserData<LinkToTextTabHelper> {
public:
~LinkToTextTabHelper() override;
static void CreateForWebState(web::WebState* web_state);
// Returns whether the link to text feature should be offered for the current
// user selection
bool ShouldOffer();
// Synchronously calls the JavaScript to generate a URL linking to the current
// selected text. Returns the generated URL along with the selected text.
SharedHighlight GetLinkToSelectedTextAndQuote();
private:
friend class web::WebStateUserData<LinkToTextTabHelper>;
explicit LinkToTextTabHelper(web::WebState* web_state);
// Not copyable or moveable.
LinkToTextTabHelper(const LinkToTextTabHelper&) = delete;
LinkToTextTabHelper& operator=(const LinkToTextTabHelper&) = delete;
// WebStateObserver:
void WebStateDestroyed(web::WebState* web_state) override;
// The WebState this instance is observing. Will be null after
// WebStateDestroyed has been called.
web::WebState* web_state_ = nullptr;
WEB_STATE_USER_DATA_KEY_DECL();
};
#endif // IOS_CHROME_BROWSER_LINK_TO_TEXT_LINK_TO_TEXT_TAB_HELPER_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/link_to_text/link_to_text_tab_helper.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
LinkToTextTabHelper::LinkToTextTabHelper(web::WebState* web_state)
: web_state_(web_state) {
web_state_->AddObserver(this);
}
LinkToTextTabHelper::~LinkToTextTabHelper() {}
// static
void LinkToTextTabHelper::CreateForWebState(web::WebState* web_state) {
DCHECK(web_state);
if (!FromWebState(web_state)) {
web_state->SetUserData(
UserDataKey(), base::WrapUnique(new LinkToTextTabHelper(web_state)));
}
}
bool LinkToTextTabHelper::ShouldOffer() {
// TODO(crbug.com/1134708): add more checks, like text only.
return true;
}
SharedHighlight LinkToTextTabHelper::GetLinkToSelectedTextAndQuote() {
// TODO(crbug.com/1091918): Call into JS to generate the quote and URL.
SharedHighlight highlight(
GURL("http://example.com/#:~:text=You%20may%20use%20this%20domain"),
"You may use this domain");
return highlight;
}
void LinkToTextTabHelper::WebStateDestroyed(web::WebState* web_state) {
DCHECK_EQ(web_state_, web_state);
// The call to RemoveUserData cause the destruction of the current instance,
// so nothing should be done after that point (this is like "delete this;").
// Unregistration as an observer happens in the destructor.
web_state_->RemoveUserData(UserDataKey());
}
WEB_STATE_USER_DATA_KEY_IMPL(LinkToTextTabHelper)
// 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_LINK_TO_TEXT_SHARED_HIGHLIGHT_H_
#define IOS_CHROME_BROWSER_LINK_TO_TEXT_SHARED_HIGHLIGHT_H_
#include "url/gurl.h"
// This struct holds a quote and a URL with a text fragment linking to
// the quote on the web page.
struct SharedHighlight {
SharedHighlight(const GURL& url, std::string quote)
: url(url), quote(quote) {}
GURL url;
std::string quote;
};
#endif // IOS_CHROME_BROWSER_LINK_TO_TEXT_SHARED_HIGHLIGHT_H_
......@@ -71,6 +71,7 @@ source_set("tabs_internal") {
"//ios/chrome/browser/infobars:badge",
"//ios/chrome/browser/infobars/overlays",
"//ios/chrome/browser/itunes_urls",
"//ios/chrome/browser/link_to_text",
"//ios/chrome/browser/main",
"//ios/chrome/browser/metrics",
"//ios/chrome/browser/network_activity:tab_helper",
......
......@@ -41,6 +41,7 @@
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_tab_helper.h"
#import "ios/chrome/browser/infobars/overlays/translate_overlay_tab_helper.h"
#import "ios/chrome/browser/itunes_urls/itunes_urls_handler_tab_helper.h"
#import "ios/chrome/browser/link_to_text/link_to_text_tab_helper.h"
#import "ios/chrome/browser/metrics/pageload_foreground_duration_tab_helper.h"
#import "ios/chrome/browser/network_activity/network_activity_indicator_tab_helper.h"
#import "ios/chrome/browser/ntp/new_tab_page_tab_helper.h"
......@@ -215,4 +216,8 @@ void AttachTabHelpers(web::WebState* web_state, bool for_prerender) {
// Allow the embedder to attach tab helpers.
ios::GetChromeBrowserProvider()->AttachTabHelpers(web_state);
if (base::FeatureList::IsEnabled(kSharedHighlightingIOS)) {
LinkToTextTabHelper::CreateForWebState(web_state);
}
}
......@@ -20,6 +20,7 @@ source_set("browser_container") {
"//ios/chrome/browser/overlays/public/web_content_area",
"//ios/chrome/browser/screen_time:feature_flags",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators",
"//ios/chrome/browser/ui/link_to_text",
"//ios/chrome/browser/ui/overlays",
"//ios/chrome/browser/ui/screen_time",
"//ios/chrome/browser/web_state_list",
......@@ -39,8 +40,12 @@ source_set("ui") {
deps = [
"//base",
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/link_to_text",
"//ios/chrome/browser/ui/util",
"//ios/chrome/common/ui/util",
"//ui/base",
]
}
......
......@@ -12,6 +12,7 @@
#import "ios/chrome/browser/screen_time/features.h"
#import "ios/chrome/browser/ui/browser_container/browser_container_mediator.h"
#import "ios/chrome/browser/ui/browser_container/browser_container_view_controller.h"
#import "ios/chrome/browser/ui/link_to_text/link_to_text_mediator.h"
#import "ios/chrome/browser/ui/overlays/overlay_container_coordinator.h"
#include "url/gurl.h"
......@@ -31,6 +32,8 @@
BrowserContainerViewController* viewController;
// The mediator used to configure the BrowserContainerConsumer.
@property(nonatomic, strong) BrowserContainerMediator* mediator;
// The mediator used for the Link to Text feature.
@property(nonatomic, strong) LinkToTextMediator* linkToTextMediator;
// The overlay container coordinator for OverlayModality::kWebContentArea.
@property(nonatomic, strong)
OverlayContainerCoordinator* webContentAreaOverlayContainerCoordinator;
......@@ -62,6 +65,9 @@
self.mediator = [[BrowserContainerMediator alloc]
initWithWebStateList:self.browser->GetWebStateList()
webContentAreaOverlayPresenter:overlayPresenter];
self.linkToTextMediator = [[LinkToTextMediator alloc]
initWithWebStateList:self.browser->GetWebStateList()];
self.viewController.linkToTextDelegate = self.linkToTextMediator;
self.mediator.consumer = self.viewController;
[self setUpScreenTimeIfEnabled];
......@@ -77,6 +83,7 @@
[self.screenTimeCoordinator stop];
self.viewController = nil;
self.mediator = nil;
self.linkToTextMediator = nil;
[super stop];
}
......
......@@ -9,6 +9,8 @@
#import "ios/chrome/browser/ui/browser_container/browser_container_consumer.h"
@protocol LinkToTextDelegate;
// UIViewController which allows displaying and removing a content view.
@interface BrowserContainerViewController
: UIViewController <BrowserContainerConsumer>
......@@ -22,6 +24,9 @@
@property(nonatomic, strong, readonly)
UIViewController* screenTimeViewController;
// The delegate to handle link to text button selection.
@property(nonatomic, weak) id<LinkToTextDelegate> linkToTextDelegate;
@end
#endif // IOS_CHROME_BROWSER_UI_BROWSER_CONTAINER_BROWSER_CONTAINER_VIEW_CONTROLLER_H_
......@@ -4,8 +4,13 @@
#import "ios/chrome/browser/ui/browser_container/browser_container_view_controller.h"
#include "base/check.h"
#import "base/check.h"
#import "ios/chrome/browser/ui/link_to_text/link_to_text_mediator.h"
#import "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -33,6 +38,8 @@
[super viewDidLoad];
self.view.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addLinkToTextInEditMenu];
}
- (void)viewDidLayoutSubviews {
......@@ -136,6 +143,32 @@
}
}
#pragma mark - Link to Text methods
- (void)addLinkToTextInEditMenu {
if (!base::FeatureList::IsEnabled(kSharedHighlightingIOS)) {
return;
}
NSString* title = l10n_util::GetNSString(IDS_IOS_SHARE_LINK_TO_TEXT);
UIMenuItem* menuItem =
[[UIMenuItem alloc] initWithTitle:title action:@selector(linkToText:)];
RegisterEditMenuItem(menuItem);
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == @selector(linkToText:) && self.linkToTextDelegate) {
return [self.linkToTextDelegate shouldOfferLinkToText];
}
return [super canPerformAction:action withSender:sender];
}
- (void)linkToText:(UIMenuItem*)item {
DCHECK(base::FeatureList::IsEnabled(kSharedHighlightingIOS));
DCHECK(self.linkToTextDelegate);
[self.linkToTextDelegate handleLinkToTextSelection];
}
#pragma mark - Private
// Unloads and nils any any previous content viewControllers if they exist.
......
......@@ -49,6 +49,7 @@ source_set("browser_view") {
"//ios/chrome/browser/geolocation:geolocation_internal",
"//ios/chrome/browser/infobars",
"//ios/chrome/browser/language",
"//ios/chrome/browser/link_to_text",
"//ios/chrome/browser/main",
"//ios/chrome/browser/metrics:metrics_browser_agent",
"//ios/chrome/browser/metrics:metrics_internal",
......
# 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.
source_set("link_to_text") {
sources = [
"link_to_text_delegate.h",
"link_to_text_mediator.h",
"link_to_text_mediator.mm",
]
deps = [
"//ios/chrome/browser/link_to_text",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/web_state_list",
"//ios/web/public",
]
configs += [ "//build/config/compiler:enable_arc" ]
}
// 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_UI_LINK_TO_TEXT_LINK_TO_TEXT_DELEGATE_H_
#define IOS_CHROME_BROWSER_UI_LINK_TO_TEXT_LINK_TO_TEXT_DELEGATE_H_
// Protocol for handling link to text and presenting related UI.
@protocol LinkToTextDelegate
// Returns whether the link to text feature should be offered for the current
// user selection.
- (BOOL)shouldOfferLinkToText;
// Handles the link to text menu item selection.
- (void)handleLinkToTextSelection;
@end
#endif // IOS_CHROME_BROWSER_UI_LINK_TO_TEXT_LINK_TO_TEXT_DELEGATE_H_
\ No newline at end of file
// 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_UI_LINK_TO_TEXT_LINK_TO_TEXT_MEDIATOR_H_
#define IOS_CHROME_BROWSER_UI_LINK_TO_TEXT_LINK_TO_TEXT_MEDIATOR_H_
#import <Foundation/Foundation.h>
#import "ios/chrome/browser/ui/link_to_text/link_to_text_delegate.h"
class WebStateList;
// Mediator that mediates between the browser container views and the
// link_to_text tab helpers.
@interface LinkToTextMediator : NSObject <LinkToTextDelegate>
// Initializer for a mediator. |webStateList| is the WebStateList for the
// Browser whose content is shown within the BrowserContainerConsumer. It must
// be non-null.
- (instancetype)initWithWebStateList:(WebStateList*)webStateList
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
#endif // IOS_CHROME_BROWSER_UI_LINK_TO_TEXT_LINK_TO_TEXT_MEDIATOR_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.
#include "ios/chrome/browser/ui/link_to_text/link_to_text_mediator.h"
#import "ios/chrome/browser/link_to_text/link_to_text_tab_helper.h"
#import "ios/chrome/browser/link_to_text/shared_highlight.h"
#import "ios/chrome/browser/ui/ui_feature_flags.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 LinkToTextMediator ()
// The Browser's WebStateList.
@property(nonatomic, readonly) WebStateList* webStateList;
@end
@implementation LinkToTextMediator
- (instancetype)initWithWebStateList:(WebStateList*)webStateList {
if (self = [super init]) {
DCHECK(webStateList);
_webStateList = webStateList;
}
return self;
}
- (void)dealloc {
if (_webStateList) {
_webStateList = nullptr;
}
}
- (BOOL)shouldOfferLinkToText {
DCHECK(base::FeatureList::IsEnabled(kSharedHighlightingIOS));
return [self getLinkToTextTabHelper]->ShouldOffer();
}
- (void)handleLinkToTextSelection {
DCHECK(base::FeatureList::IsEnabled(kSharedHighlightingIOS));
[self shareLinkToText:[self getLinkToTextTabHelper]
->GetLinkToSelectedTextAndQuote()];
}
- (void)shareLinkToText:(SharedHighlight)sharedHighlight {
// TODO(crbug.com/1134707): Trigger the share sheet.
}
- (LinkToTextTabHelper*)getLinkToTextTabHelper {
web::WebState* web_state = _webStateList->GetActiveWebState();
DCHECK(web_state);
LinkToTextTabHelper* helper = LinkToTextTabHelper::FromWebState(web_state);
DCHECK(helper);
return helper;
}
@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