Commit 11fe3c86 authored by Eugene But's avatar Eugene But Committed by Commit Bot

Added feature flags for FileDownload and PassKitDownload features.

This CL adds kNewPassKitDownload and kNewFileDownload flags usage
to the web layer. Turning on kNewPassKitDownload flag will disable
CRWPassKitDownloader and webController:didLoadPassKitObject: callback.
Turning on kNewFileDownload will disable
controllerForUnhandledContentAtURL: callback.
Turning either of these flags on will add a logic, which discards
pending item if that item is download.

Both flags are turned off by default and there is no way to enable
them via chrome://flags yet.

This CL slightly changes the code inside WKNavigationDelegate's
webView:decidePolicyForNavigationResponse:decisionHandler: as follows:
 - CRWPassKitDownloader download is moved behind |!allowNavigation|
 - allowNavigation is not set to no if MIME type is PassKit
These are non functional changes because if MIME type is PassKit, then
|allowNavigation| is always NO.

Bug: 780646
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: I948ae3e1f38d266eda8aa7b99900900d8c02fef3
Reviewed-on: https://chromium-review.googlesource.com/783671
Commit-Queue: Eugene But <eugenebut@chromium.org>
Reviewed-by: default avatarGregory Chatzinoff <gchatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#519795}
parent 783ff5e8
......@@ -25,6 +25,7 @@ typedef void (^PassKitCompletionHandler)(NSData*);
// CRWPassKitDownloader downloads PassKit data and passes it to a completion
// handler.
// DEPRECATED - Do not use this class. http://crbug.com/787943
@interface CRWPassKitDownloader : NSObject
// Initializes the CRWPassKitDownloader. |getter| must not be null and
......
......@@ -6,10 +6,12 @@
#include <memory>
#include "base/feature_list.h"
#include "base/mac/scoped_block.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/sys_string_conversions.h"
#include "ios/web/public/features.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
......@@ -97,6 +99,7 @@ class PassKitFetcherDelegate : public URLFetcherDelegate {
- (instancetype)initWithContextGetter:(net::URLRequestContextGetter*)getter
completionHandler:(web::PassKitCompletionHandler)handler {
DCHECK(!base::FeatureList::IsEnabled(web::features::kNewPassKitDownload));
self = [super init];
if (self) {
DCHECK(getter);
......
......@@ -16,6 +16,7 @@
#include "base/callback.h"
#include "base/containers/mru_cache.h"
#include "base/feature_list.h"
#import "base/ios/block_types.h"
#include "base/ios/ios_util.h"
#import "base/ios/ns_error_util.h"
......@@ -49,6 +50,7 @@
#include "ios/web/public/browser_state.h"
#import "ios/web/public/download/download_controller.h"
#include "ios/web/public/favicon_url.h"
#include "ios/web/public/features.h"
#import "ios/web/public/java_script_dialog_presenter.h"
#import "ios/web/public/navigation_item.h"
#import "ios/web/public/navigation_manager.h"
......@@ -429,6 +431,7 @@ NSError* WKWebViewErrorWithSource(NSError* error, WKWebViewErrorSource source) {
// changed.
@property(weak, nonatomic, readonly) NSDictionary* WKWebViewObservers;
// Downloader for PassKit files. Lazy initialized.
// DEPRECATED - Do not use this property. http://crbug.com/787943
@property(weak, nonatomic, readonly) CRWPassKitDownloader* passKitDownloader;
// The web view's view of the current URL. During page transitions
......@@ -1941,7 +1944,9 @@ registerLoadRequestForURL:(const GURL&)requestURL
}
- (void)loadCancelled {
[_passKitDownloader cancelPendingDownload];
if (!base::FeatureList::IsEnabled(web::features::kNewPassKitDownload)) {
[_passKitDownloader cancelPendingDownload];
}
if (_loadPhase != web::PAGE_LOADED) {
_loadPhase = web::PAGE_LOADED;
if (!_isHalted) {
......@@ -2123,6 +2128,7 @@ registerLoadRequestForURL:(const GURL&)requestURL
}
- (CRWPassKitDownloader*)passKitDownloader {
DCHECK(!base::FeatureList::IsEnabled(web::features::kNewPassKitDownload));
if (_passKitDownloader) {
return _passKitDownloader;
}
......@@ -2908,8 +2914,10 @@ registerLoadRequestForURL:(const GURL&)requestURL
- (void)handleLoadError:(NSError*)error
forNavigation:(WKNavigation*)navigation {
NSString* MIMEType = [_pendingNavigationInfo MIMEType];
if ([_passKitDownloader isMIMETypePassKitType:MIMEType])
if (!base::FeatureList::IsEnabled(web::features::kNewPassKitDownload) &&
[_passKitDownloader isMIMETypePassKitType:MIMEType]) {
return;
}
if ([error code] == NSURLErrorUnsupportedURL)
return;
// In cases where a Plug-in handles the load do not take any further action.
......@@ -2936,34 +2944,47 @@ registerLoadRequestForURL:(const GURL&)requestURL
[_navigationStates contextForNavigation:navigation];
navigationContext->SetError(error);
// Handles Frame Load Interrupted errors from WebView.
if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] &&
error.code == web::kWebKitErrorFrameLoadInterruptedByPolicyChange) {
// Handle Frame Load Interrupted errors from WebView. This block is executed
// when web controller rejected the load inside
// decidePolicyForNavigationAction: or decidePolicyForNavigationResponse:.
// Load rejection may happen if embedder denied the load via
// WebStatePolicyDecider or the navigation was a download navigation.
NSString* errorURLSpec = error.userInfo[NSURLErrorFailingURLStringErrorKey];
NSURL* errorURL = [NSURL URLWithString:errorURLSpec];
const GURL errorGURL = net::GURLWithNSURL(errorURL);
// See if the delegate wants to handle this case.
if (errorGURL.is_valid() &&
[_delegate
respondsToSelector:@selector(
controllerForUnhandledContentAtURL:)]) {
id<CRWNativeContent> controller =
[_delegate controllerForUnhandledContentAtURL:errorGURL];
if (controller) {
[self loadCompleteWithSuccess:NO forNavigation:navigation];
[self removeWebView];
[self setNativeController:controller];
[self loadNativeViewWithSuccess:YES
navigationContext:navigationContext];
return;
if (!base::FeatureList::IsEnabled(web::features::kNewFileDownload) &&
![MIMEType isEqualToString:@"application/vnd.apple.pkpass"]) {
// This block is executed to handle legacy download navigation.
const GURL errorGURL = net::GURLWithNSURL(errorURL);
if (errorGURL.is_valid() &&
[_delegate respondsToSelector:@selector
(controllerForUnhandledContentAtURL:)]) {
id<CRWNativeContent> controller =
[_delegate controllerForUnhandledContentAtURL:errorGURL];
if (controller) {
[self loadCompleteWithSuccess:NO forNavigation:navigation];
[self removeWebView];
[self setNativeController:controller];
[self loadNativeViewWithSuccess:YES
navigationContext:navigationContext];
return;
}
}
}
// Ignore errors that originate from URLs that are opened in external apps.
// The load was rejected, because embedder launched an external application.
if ([_openedApplicationURL containsObject:errorURL])
return;
if (base::FeatureList::IsEnabled(web::features::kNewPassKitDownload) ||
base::FeatureList::IsEnabled(web::features::kNewFileDownload)) {
// This navigation was a download navigation and embedder now has a chance
// to start the download task.
_webStateImpl->SetIsLoading(false);
return;
}
// The wrapper error uses the URL of the error and not the requested URL
// (which can be different in case of a redirect) to match desktop Chrome
// behavior.
......@@ -4285,24 +4306,32 @@ registerLoadRequestForURL:(const GURL&)requestURL
->CreateDownloadTask(_webStateImpl, [NSUUID UUID].UUIDString,
responseURL, contentDisposition, contentLength,
base::SysNSStringToUTF8(MIMEType));
}
if ([self.passKitDownloader isMIMETypePassKitType:MIMEType]) {
[self.passKitDownloader downloadPassKitFileWithURL:responseURL];
allowNavigation = NO;
// Discard the pending PassKit entry to ensure that the current URL is not
// different from what is displayed on the view. If there is no previous
// committed URL, which can happen when a link is opened in a new tab via a
// context menu or window.open, the pending entry should not be
// discarded so that the NavigationManager is never empty. Also, URLs loaded
// in a native view should be excluded to avoid an ugly animation where the
// web view is inserted and quickly removed.
GURL lastCommittedURL = self.webState->GetLastCommittedURL();
BOOL isFirstLoad = lastCommittedURL.is_empty();
BOOL previousItemWasLoadedInNativeView =
[self shouldLoadURLInNativeView:lastCommittedURL];
if (!isFirstLoad && !previousItemWasLoadedInNativeView)
self.navigationManagerImpl->DiscardNonCommittedItems();
BOOL downloadItem =
(base::FeatureList::IsEnabled(web::features::kNewPassKitDownload) ||
base::FeatureList::IsEnabled(web::features::kNewFileDownload));
if (!base::FeatureList::IsEnabled(web::features::kNewPassKitDownload) &&
[self.passKitDownloader isMIMETypePassKitType:MIMEType]) {
[self.passKitDownloader downloadPassKitFileWithURL:responseURL];
downloadItem = YES;
}
if (downloadItem) {
// Discard the pending item to ensure that the current URL is not
// different from what is displayed on the view. If there is no previous
// committed URL, which can happen when a link is opened in a new tab via
// a context menu or window.open, the pending entry should not be
// discarded so that the NavigationManager is never empty. Also, URLs
// loaded in a native view should be excluded to avoid an ugly animation
// where the web view is inserted and quickly removed.
GURL lastCommittedURL = self.webState->GetLastCommittedURL();
BOOL isFirstLoad = lastCommittedURL.is_empty();
BOOL previousItemWasLoadedInNativeView =
[self shouldLoadURLInNativeView:lastCommittedURL];
if (!isFirstLoad && !previousItemWasLoadedInNativeView)
self.navigationManagerImpl->DiscardNonCommittedItems();
}
}
handler(allowNavigation ? WKNavigationResponsePolicyAllow
......
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