Commit 10d316d8 authored by Mike Dougherty's avatar Mike Dougherty Committed by Commit Bot

Prevent universal link from opening native application in off the record.

Tapping a universal link while in off the record mode should not open a
native application because it shares the private state with the launched
app.

Bug: 861752

Change-Id: I578caf10e6ea0cf3978d1d7177ec01c71631e5ce
Reviewed-on: https://chromium-review.googlesource.com/c/1436489
Commit-Queue: Mike Dougherty <michaeldo@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Reviewed-by: default avatarPeter Lee <pkl@chromium.org>
Cr-Commit-Position: refs/heads/master@{#632841}
parent 150f8669
......@@ -7,4 +7,8 @@ declare_args() {
# components/cronet/tools/cr_cronet.py as cronet requires specific
# gn args to build correctly).
is_cronet_build = false
# Controls whether universal links are blocked from opening native apps
# when the user is browsing in off the record mode.
block_universal_links_in_off_the_record_mode = true
}
......@@ -490,6 +490,7 @@ source_set("ios_web_web_state_ui_unittests") {
"//ios/web/web_state:wk_web_view_security_util",
"//ios/web/web_state/js",
"//ios/web/web_state/js:script_util",
"//ios/web/web_state/ui:block_universal_links_buildflags",
"//ios/web/web_state/ui:crw_context_menu_controller",
"//ios/web/web_state/ui:crw_wk_script_message_router",
"//ios/web/web_state/ui:favicon_util",
......@@ -513,6 +514,7 @@ source_set("ios_web_web_state_ui_unittests") {
"web_state/ui/html_element_fetch_request_unittest.mm",
"web_state/ui/web_view_js_utils_unittest.mm",
"web_state/ui/wk_back_forward_list_item_holder_unittest.mm",
"web_state/ui/wk_navigation_action_policy_util_unittest.mm",
"web_state/ui/wk_navigation_action_util_unittest.mm",
"web_state/ui/wk_web_view_configuration_provider_unittest.mm",
]
......
......@@ -30,5 +30,8 @@ const base::Feature kOutOfWebFullscreen{"OutOfWebFullscreen",
const base::Feature kHistoryClobberWorkaround{
"WKWebViewHistoryClobberWorkaround", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kBlockUniversalLinksInOffTheRecordMode{
"BlockUniversalLinksInOffTheRecord", base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features
} // namespace web
......@@ -36,6 +36,10 @@ extern const base::Feature kOutOfWebFullscreen;
// (crbug.com/887497).
extern const base::Feature kHistoryClobberWorkaround;
// Used to prevent native apps from being opened when a universal link is tapped
// and the user is browsing in off the record mode.
extern const base::Feature kBlockUniversalLinksInOffTheRecordMode;
} // namespace features
} // namespace web
......
......@@ -2,10 +2,18 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/buildflag_header.gni")
import("//ios/build/config.gni")
import("//ios/features.gni")
buildflag_header("block_universal_links_buildflags") {
header = "block_universal_links_buildflags.h"
flags = [ "BLOCK_UNIVERSAL_LINKS_IN_OFF_THE_RECORD_MODE=$block_universal_links_in_off_the_record_mode" ]
}
source_set("ui") {
deps = [
":block_universal_links_buildflags",
":crw_context_menu_controller",
":crw_web_view_navigation_proxy",
":crw_wk_script_message_router",
......@@ -57,6 +65,8 @@ source_set("ui") {
"web_kit_constants.h",
"wk_back_forward_list_item_holder.h",
"wk_back_forward_list_item_holder.mm",
"wk_navigation_action_policy_util.h",
"wk_navigation_action_policy_util.mm",
"wk_navigation_action_util.h",
"wk_navigation_action_util.mm",
]
......
......@@ -102,6 +102,7 @@
#import "ios/web/web_state/ui/favicon_util.h"
#include "ios/web/web_state/ui/web_kit_constants.h"
#import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h"
#import "ios/web/web_state/ui/wk_navigation_action_policy_util.h"
#import "ios/web/web_state/ui/wk_navigation_action_util.h"
#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
#import "ios/web/web_state/web_frame_impl.h"
......@@ -4701,8 +4702,9 @@ GURL URLEscapedForHistory(const GURL& url) {
}));
}
decisionHandler(allowLoad ? WKNavigationActionPolicyAllow
: WKNavigationActionPolicyCancel);
WKNavigationActionPolicy allowPolicy = web::GetAllowNavigationActionPolicy(
self.webState->GetBrowserState()->IsOffTheRecord());
decisionHandler(allowLoad ? allowPolicy : WKNavigationActionPolicyCancel);
}
- (void)webView:(WKWebView*)webView
......
......@@ -26,6 +26,7 @@
#include "ios/web/public/features.h"
#include "ios/web/public/referrer.h"
#include "ios/web/public/test/fakes/fake_download_controller_delegate.h"
#include "ios/web/public/test/fakes/test_browser_state.h"
#import "ios/web/public/test/fakes/test_native_content.h"
#import "ios/web/public/test/fakes/test_native_content_provider.h"
#import "ios/web/public/test/fakes/test_web_client.h"
......@@ -45,8 +46,10 @@
#include "ios/web/test/test_url_constants.h"
#import "ios/web/test/web_test_with_web_controller.h"
#import "ios/web/test/wk_web_view_crash_utils.h"
#include "ios/web/web_state/ui/block_universal_links_buildflags.h"
#import "ios/web/web_state/ui/crw_web_controller_container_view.h"
#import "ios/web/web_state/ui/web_view_js_utils.h"
#import "ios/web/web_state/ui/wk_navigation_action_policy_util.h"
#import "ios/web/web_state/web_state_impl.h"
#import "ios/web/web_state/wk_web_view_security_util.h"
#import "net/base/mac/url_conversions.h"
......@@ -782,6 +785,11 @@ class CRWWebControllerPolicyDeciderTest : public CRWWebControllerTest {
});
return policy_match;
}
// Return an owned BrowserState in order to set off the record state.
BrowserState* GetBrowserState() override { return &browser_state_; }
TestBrowserState browser_state_;
};
// Tests that App specific URLs in iframes are allowed if the main frame is App
......@@ -798,6 +806,44 @@ TEST_P(CRWWebControllerPolicyDeciderTest,
app_url_request, WKNavigationActionPolicyAllow));
}
// Tests that URL is allowed in OffTheRecord mode when the
// |kBlockUniversalLinksInOffTheRecordMode| feature is disabled.
TEST_P(CRWWebControllerPolicyDeciderTest, AllowOffTheRecordNavigation) {
browser_state_.SetOffTheRecord(true);
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
web::features::kBlockUniversalLinksInOffTheRecordMode);
NSURL* url = [NSURL URLWithString:@(kTestURLString)];
NSMutableURLRequest* url_request = [NSMutableURLRequest requestWithURL:url];
url_request.mainDocumentURL = url;
EXPECT_TRUE(VerifyDecidePolicyForNavigationAction(
url_request, WKNavigationActionPolicyAllow));
}
// Tests that URL is allowed in OffTheRecord mode and that universal links are
// blocked when the |kBlockUniversalLinksInOffTheRecordMode| feature is enabled
// and the BLOCK_UNIVERSAL_LINKS_IN_OFF_THE_RECORD_MODE buildflag is set.
TEST_P(CRWWebControllerPolicyDeciderTest,
AllowOffTheRecordNavigationBlockUniversalLinks) {
browser_state_.SetOffTheRecord(true);
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
web::features::kBlockUniversalLinksInOffTheRecordMode);
NSURL* url = [NSURL URLWithString:@(kTestURLString)];
NSMutableURLRequest* url_request = [NSMutableURLRequest requestWithURL:url];
url_request.mainDocumentURL = url;
WKNavigationActionPolicy expected_policy = WKNavigationActionPolicyAllow;
#if BUILDFLAG(BLOCK_UNIVERSAL_LINKS_IN_OFF_THE_RECORD_MODE)
expected_policy = kNavigationActionPolicyAllowAndBlockUniversalLinks;
#endif // BUILDFLAG(BLOCK_UNIVERSAL_LINKS_IN_OFF_THE_RECORD_MODE)
EXPECT_TRUE(
VerifyDecidePolicyForNavigationAction(url_request, expected_policy));
}
// Tests that App specific URLs in iframes are not allowed if the main frame is
// not App specific URL.
TEST_P(CRWWebControllerPolicyDeciderTest,
......
// Copyright 2019 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_WEB_STATE_UI_WK_NAVIGATION_ACTION_POLICY_UTIL_H_
#define IOS_WEB_WEB_STATE_UI_WK_NAVIGATION_ACTION_POLICY_UTIL_H_
#import <WebKit/WebKit.h>
namespace web {
// Navigation action policy which allows the load but prevents opening universal
// links in native applications.
extern const WKNavigationActionPolicy
kNavigationActionPolicyAllowAndBlockUniversalLinks;
// Returns the WKNavigationActionPolicy for allowing navigations given the
// |off_the_record| state for the associated BrowserState.
WKNavigationActionPolicy GetAllowNavigationActionPolicy(bool off_the_record);
} // namespace web
#endif // IOS_WEB_WEB_STATE_UI_WK_NAVIGATION_ACTION_POLICY_UTIL_H_
// Copyright 2019 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/web_state/ui/wk_navigation_action_policy_util.h"
#include "base/feature_list.h"
#include "ios/web/public/features.h"
#include "ios/web/web_state/ui/block_universal_links_buildflags.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace web {
const WKNavigationActionPolicy
kNavigationActionPolicyAllowAndBlockUniversalLinks =
static_cast<WKNavigationActionPolicy>(WKNavigationActionPolicyAllow +
2);
WKNavigationActionPolicy GetAllowNavigationActionPolicy(bool off_the_record) {
// When both the |block_universal_links_in_off_the_record| gn arg and the
// |web::features::kBlockUniversalLinksInOffTheRecordMode| feature flag are
// enabled, the returned value will block opening native applications if
// |off_the_record| is true to prevent sharing off the record state.
#if BUILDFLAG(BLOCK_UNIVERSAL_LINKS_IN_OFF_THE_RECORD_MODE)
bool block_universal_links_enabled = base::FeatureList::IsEnabled(
web::features::kBlockUniversalLinksInOffTheRecordMode);
if (off_the_record && block_universal_links_enabled) {
return kNavigationActionPolicyAllowAndBlockUniversalLinks;
}
#endif // BUILDFLAG(BLOCK_UNIVERSAL_LINKS_IN_OFF_THE_RECORD_MODE)
return WKNavigationActionPolicyAllow;
}
} // namespace web
// Copyright 2019 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/web_state/ui/wk_navigation_action_policy_util.h"
#import <WebKit/WebKit.h>
#include "base/test/scoped_feature_list.h"
#include "ios/web/public/features.h"
#include "ios/web/web_state/ui/block_universal_links_buildflags.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 {
using WKNavigationActionPolicyUtilTest = PlatformTest;
// Tests GetAllowNavigationActionPolicy for normal browsing mode.
TEST_F(WKNavigationActionPolicyUtilTest, AllowNavigationActionPolicy) {
WKNavigationActionPolicy policy = GetAllowNavigationActionPolicy(false);
EXPECT_EQ(WKNavigationActionPolicyAllow, policy);
}
// Tests GetAllowNavigationActionPolicy for off the record browsing mode with
// the |kBlockUniversalLinksInOffTheRecordMode| feature disabled.
TEST_F(WKNavigationActionPolicyUtilTest,
AllowNavigationActionPolicyForOffTheRecord) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
web::features::kBlockUniversalLinksInOffTheRecordMode);
WKNavigationActionPolicy policy = GetAllowNavigationActionPolicy(true);
EXPECT_EQ(WKNavigationActionPolicyAllow, policy);
}
// Tests GetAllowNavigationActionPolicy for off the record browsing mode with
// the |kBlockUniversalLinksInOffTheRecordMode| feature enabled.
TEST_F(WKNavigationActionPolicyUtilTest, BlockUniversalLinksForOffTheRecord) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
web::features::kBlockUniversalLinksInOffTheRecordMode);
WKNavigationActionPolicy expected_policy = WKNavigationActionPolicyAllow;
#if BUILDFLAG(BLOCK_UNIVERSAL_LINKS_IN_OFF_THE_RECORD_MODE)
expected_policy = kNavigationActionPolicyAllowAndBlockUniversalLinks;
#endif // BUILDFLAG(BLOCK_UNIVERSAL_LINKS_IN_OFF_THE_RECORD_MODE)
EXPECT_EQ(expected_policy, GetAllowNavigationActionPolicy(true));
}
} // namespace web
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