Commit 9ceff819 authored by Tommy Martino's avatar Tommy Martino Committed by Commit Bot

[SH iOS] Adding hooks for Text Fragments during navigation

This CL adds a new file, text_fragment_utils, which will provide logic
for handling text fragments (the URL specifiers which power the
scroll-to-text feature). It invokes those utils at the last possible
moment of navigation.

I've implemented the basic guard logic that checks the preconditions
for completing such a navigation; actually performing the scroll to text
will be added in a follow-up CL.

Bug: 1099268

Change-Id: I522119abe28cc0bd323bdf230a1ca8951c157835
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2333044Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Commit-Queue: Tommy Martino <tmartino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#794687}
parent 48d91511
......@@ -271,6 +271,7 @@ source_set("ios_web_navigation_unittests") {
"navigation/navigation_manager_util_unittest.mm",
"navigation/nscoder_util_unittest.mm",
"navigation/session_storage_builder_unittest.mm",
"navigation/text_fragment_utils_unittest.mm",
"navigation/wk_back_forward_list_item_holder_unittest.mm",
"navigation/wk_based_navigation_manager_impl_unittest.mm",
"navigation/wk_navigation_action_policy_util_unittest.mm",
......
......@@ -61,6 +61,8 @@ source_set("navigation") {
"serializable_user_data_manager_impl.mm",
"session_storage_builder.h",
"session_storage_builder.mm",
"text_fragment_utils.h",
"text_fragment_utils.mm",
"time_smoother.cc",
"time_smoother.h",
"url_schemes.mm",
......
// 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_WEB_NAVIGATION_TEXT_FRAGMENT_UTILS_H_
#define IOS_WEB_NAVIGATION_TEXT_FRAGMENT_UTILS_H_
namespace web {
class NavigationContext;
// This file contains helper functions relating to Text Fragments, which are
// appended to the reference fragment in the URL and instruct the user agent
// to highlight a given snippet of text and the page and scroll it into view.
// See also: https://wicg.github.io/scroll-to-text-fragment/
// Checks if product and security requirements permit the use of Text Fragments.
// Does not guarantee that the URL contains a Text Fragment or that the matching
// text will be found on the page.
bool AreTextFragmentsAllowed(NavigationContext* context);
// Checks the destination URL for Text Fragments. If found, searches the DOM for
// matching text, highlights the text, and scrolls the first into view.
void HandleTextFragments(NavigationContext* context);
} // namespace web
#endif // IOS_WEB_NAVIGATION_TEXT_FRAGMENT_UTILS_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/web/navigation/text_fragment_utils.h"
#include "ios/web/common/features.h"
#import "ios/web/public/navigation/navigation_context.h"
#import "ios/web/public/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace web {
bool AreTextFragmentsAllowed(NavigationContext* context) {
if (!base::FeatureList::IsEnabled(features::kScrollToTextIOS))
return false;
WebState* web_state = context->GetWebState();
if (web_state->HasOpener()) {
// TODO(crbug.com/1099268): Loosen this restriction if the opener has the
// same domain.
return false;
}
return context->HasUserGesture() && !context->IsSameDocument();
}
void HandleTextFragments(NavigationContext* context) {
// TODO(crbug.com/1099268): Parse URL fragment, execute JS using passed
// params.
}
} // namespace web
// 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/web/navigation/text_fragment_utils.h"
#include <memory>
#include "base/test/scoped_feature_list.h"
#include "ios/web/common/features.h"
#import "ios/web/public/test/fakes/fake_navigation_context.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace web {
typedef PlatformTest TextFragmentUtilsTest;
TEST_F(TextFragmentUtilsTest, AreTextFragmentsAllowed) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(features::kScrollToTextIOS);
std::unique_ptr<TestWebState> web_state = std::make_unique<TestWebState>();
TestWebState* web_state_ptr = web_state.get();
FakeNavigationContext context;
context.SetWebState(std::move(web_state));
// Working case: no opener, has user gesture, not same document
web_state_ptr->SetHasOpener(false);
context.SetHasUserGesture(true);
context.SetIsSameDocument(false);
EXPECT_TRUE(AreTextFragmentsAllowed(&context));
// Blocking case #1: WebState has an opener
web_state_ptr->SetHasOpener(true);
context.SetHasUserGesture(true);
context.SetIsSameDocument(false);
EXPECT_FALSE(AreTextFragmentsAllowed(&context));
// Blocking case #2: No user gesture
web_state_ptr->SetHasOpener(false);
context.SetHasUserGesture(false);
context.SetIsSameDocument(false);
EXPECT_FALSE(AreTextFragmentsAllowed(&context));
// Blocking case #3: Same-document navigation
web_state_ptr->SetHasOpener(false);
context.SetHasUserGesture(true);
context.SetIsSameDocument(true);
EXPECT_FALSE(AreTextFragmentsAllowed(&context));
}
} // namespace web
......@@ -20,6 +20,7 @@
#import "ios/web/navigation/navigation_context_impl.h"
#import "ios/web/navigation/navigation_item_impl.h"
#import "ios/web/navigation/session_storage_builder.h"
#import "ios/web/navigation/text_fragment_utils.h"
#import "ios/web/navigation/wk_based_navigation_manager_impl.h"
#import "ios/web/navigation/wk_navigation_util.h"
#include "ios/web/public/browser_state.h"
......@@ -858,6 +859,10 @@ void WebStateImpl::OnNavigationFinished(web::NavigationContextImpl* context) {
observer.FaviconUrlUpdated(this, cached_favicon_urls_);
}
}
if (AreTextFragmentsAllowed(context)) {
HandleTextFragments(context);
}
}
#pragma mark - NavigationManagerDelegate implementation
......
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