diff options
author | kkhorimoto <kkhorimoto@chromium.org> | 2015-05-22 14:32:29 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-22 21:34:00 +0000 |
commit | 1f3dd239b569036e77a75dd9c36657ab18947f96 (patch) | |
tree | 7bc70da852a23b945d2479436ef85830ba3051e9 /ios | |
parent | ac94e41f40bfc5252dc23dd72549d985ca221168 (diff) | |
download | chromium_src-1f3dd239b569036e77a75dd9c36657ab18947f96.zip chromium_src-1f3dd239b569036e77a75dd9c36657ab18947f96.tar.gz chromium_src-1f3dd239b569036e77a75dd9c36657ab18947f96.tar.bz2 |
Created CRWRedirectClient.
This allows CRWUIWebViewWebController to record server redirects as soon
as the redirect response is received by the net layer.
BUG=478848
Review URL: https://codereview.chromium.org/1147393004
Cr-Commit-Position: refs/heads/master@{#331178}
Diffstat (limited to 'ios')
-rw-r--r-- | ios/web/ios_web.gyp | 4 | ||||
-rw-r--r-- | ios/web/navigation/crw_session_controller.mm | 2 | ||||
-rw-r--r-- | ios/web/net/clients/crw_redirect_network_client.h | 35 | ||||
-rw-r--r-- | ios/web/net/clients/crw_redirect_network_client.mm | 52 | ||||
-rw-r--r-- | ios/web/net/clients/crw_redirect_network_client_factory.h | 21 | ||||
-rw-r--r-- | ios/web/net/clients/crw_redirect_network_client_factory.mm | 54 | ||||
-rw-r--r-- | ios/web/web_state/ui/crw_ui_web_view_web_controller.mm | 47 | ||||
-rw-r--r-- | ios/web/web_state/web_state_impl.mm | 1 |
8 files changed, 213 insertions, 3 deletions
diff --git a/ios/web/ios_web.gyp b/ios/web/ios_web.gyp index c8ec30c..0776a10 100644 --- a/ios/web/ios_web.gyp +++ b/ios/web/ios_web.gyp @@ -78,6 +78,10 @@ 'net/clients/crw_passkit_network_client.mm', 'net/clients/crw_passkit_network_client_factory.h', 'net/clients/crw_passkit_network_client_factory.mm', + 'net/clients/crw_redirect_network_client.h', + 'net/clients/crw_redirect_network_client.mm', + 'net/clients/crw_redirect_network_client_factory.h', + 'net/clients/crw_redirect_network_client_factory.mm', 'net/cookie_notification_bridge.h', 'net/cookie_notification_bridge.mm', 'net/crw_request_tracker_delegate.h', diff --git a/ios/web/navigation/crw_session_controller.mm b/ios/web/navigation/crw_session_controller.mm index b86f243..eb8a92a1 100644 --- a/ios/web/navigation/crw_session_controller.mm +++ b/ios/web/navigation/crw_session_controller.mm @@ -434,8 +434,6 @@ NSString* const kXCallbackParametersKey = @"xCallbackParameters"; if (url != item->GetURL()) { item->SetURL(url); item->SetVirtualURL(url); - // Since updates are caused by page redirects, they are renderer-initiated. - item->set_is_renderer_initiated(true); // Redirects (3xx response code), or client side navigation must change // POST requests to GETs. item->SetPostData(nil); diff --git a/ios/web/net/clients/crw_redirect_network_client.h b/ios/web/net/clients/crw_redirect_network_client.h new file mode 100644 index 0000000..41a4c7b --- /dev/null +++ b/ios/web/net/clients/crw_redirect_network_client.h @@ -0,0 +1,35 @@ +// Copyright 2015 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_NET_CLIENTS_CRW_REDIRECT_NETWORK_CLIENT_H_ +#define IOS_WEB_NET_CLIENTS_CRW_REDIRECT_NETWORK_CLIENT_H_ + +#import <Foundation/Foundation.h> + +#include "base/ios/weak_nsobject.h" +#import "ios/net/clients/crn_forwarding_network_client.h" + +@protocol CRWRedirectClientDelegate; + +// The CRWRedirectNetworkClient observes redirects and notifies its delegate +// when they occur. +@interface CRWRedirectNetworkClient : CRNForwardingNetworkClient + +// Designated initializer. +- (instancetype)initWithDelegate: + (base::WeakNSProtocol<id<CRWRedirectClientDelegate>>)delegate; + +@end + +// Delegate for CRWRedirectNetworkClients. +@protocol CRWRedirectClientDelegate<NSObject> + +// Notifies the delegate that the current http request recieved |response| and +// was redirected to |request|. +- (void)wasRedirectedToRequest:(NSURLRequest*)request + redirectResponse:(NSURLResponse*)response; + +@end + +#endif // IOS_WEB_NET_CLIENTS_CRW_REDIRECT_NETWORK_CLIENT_H_ diff --git a/ios/web/net/clients/crw_redirect_network_client.mm b/ios/web/net/clients/crw_redirect_network_client.mm new file mode 100644 index 0000000..2442834 --- /dev/null +++ b/ios/web/net/clients/crw_redirect_network_client.mm @@ -0,0 +1,52 @@ +// Copyright 2015 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/web/net/clients/crw_redirect_network_client.h" + +#include "base/location.h" +#include "base/mac/bind_objc_block.h" +#include "ios/web/public/web_thread.h" + +@interface CRWRedirectNetworkClient () { + // The delegate. + base::WeakNSProtocol<id<CRWRedirectClientDelegate>> delegate_; +} + +@end + +@implementation CRWRedirectNetworkClient + +- (instancetype)init { + NOTREACHED(); + return nil; +} + +- (instancetype)initWithDelegate: + (base::WeakNSProtocol<id<CRWRedirectClientDelegate>>)delegate { + self = [super init]; + if (self) { + // CRWRedirectNetworkClients are created on the IO thread, but due to the + // threading restrictions of WeakNSObjects, |delegate_| may only be + // dereferenced on the UI thread. + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + delegate_ = delegate; + } + return self; +} + +- (void)wasRedirectedToRequest:(NSURLRequest*)request + nativeRequest:(net::URLRequest*)nativeRequest + redirectResponse:(NSURLResponse*)redirectResponse { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + web::WebThread::PostTask(web::WebThread::UI, FROM_HERE, base::BindBlock(^{ + // |delegate_| can only be dereferenced from the UI thread. + [delegate_ wasRedirectedToRequest:request + redirectResponse:redirectResponse]; + })); + [super wasRedirectedToRequest:request + nativeRequest:nativeRequest + redirectResponse:redirectResponse]; +} + +@end diff --git a/ios/web/net/clients/crw_redirect_network_client_factory.h b/ios/web/net/clients/crw_redirect_network_client_factory.h new file mode 100644 index 0000000..68e3c49 --- /dev/null +++ b/ios/web/net/clients/crw_redirect_network_client_factory.h @@ -0,0 +1,21 @@ +// Copyright 2015 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_NET_CLIENTS_CRW_REDIRECT_NETWORK_CLIENT_FACTORY_H_ +#define IOS_WEB_NET_CLIENTS_CRW_REDIRECT_NETWORK_CLIENT_FACTORY_H_ + +#import <Foundation/Foundation.h> + +#import "ios/web/net/clients/crw_redirect_network_client.h" +#import "ios/net/clients/crn_forwarding_network_client_factory.h" + +// Factory that creates CRWRedirectNetworkClient instances. +@interface CRWRedirectNetworkClientFactory : CRNForwardingNetworkClientFactory + +// Designated initializer. |delegate| is expected to be non-nil. +- (instancetype)initWithDelegate:(id<CRWRedirectClientDelegate>)delegate; + +@end + +#endif // IOS_WEB_NET_CLIENTS_CRW_REDIRECT_NETWORK_CLIENT_FACTORY_H_ diff --git a/ios/web/net/clients/crw_redirect_network_client_factory.mm b/ios/web/net/clients/crw_redirect_network_client_factory.mm new file mode 100644 index 0000000..d3ac5da --- /dev/null +++ b/ios/web/net/clients/crw_redirect_network_client_factory.mm @@ -0,0 +1,54 @@ +// Copyright 2015 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/web/net/clients/crw_redirect_network_client_factory.h" + +#include "base/location.h" +#import "base/ios/weak_nsobject.h" +#include "base/mac/bind_objc_block.h" +#include "ios/web/public/web_thread.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/url_request.h" +#include "url/gurl.h" + +@interface CRWRedirectNetworkClientFactory () { + // Delegate passed to each vended CRWRedirectClient. + base::WeakNSProtocol<id<CRWRedirectClientDelegate>> client_delegate_; +} + +@end + +@implementation CRWRedirectNetworkClientFactory + +- (instancetype)init { + NOTREACHED(); + return nil; +} + +- (instancetype)initWithDelegate:(id<CRWRedirectClientDelegate>)delegate { + self = [super init]; + if (self) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + DCHECK(delegate); + client_delegate_.reset(delegate); + } + return self; +} + +#pragma mark - CRNForwardingNetworkClientFactory + +- (Class)clientClass { + return [CRWRedirectNetworkClient class]; +} + +- (CRNForwardingNetworkClient*)clientHandlingRedirect: + (const net::URLRequest&)request + url:(const GURL&)url + response:(NSURLResponse*)response { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + return [[[CRWRedirectNetworkClient alloc] + initWithDelegate:client_delegate_] autorelease]; +} + +@end diff --git a/ios/web/web_state/ui/crw_ui_web_view_web_controller.mm b/ios/web/web_state/ui/crw_ui_web_view_web_controller.mm index bd24193..8a97881 100644 --- a/ios/web/web_state/ui/crw_ui_web_view_web_controller.mm +++ b/ios/web/web_state/ui/crw_ui_web_view_web_controller.mm @@ -19,6 +19,7 @@ #import "ios/net/nsurlrequest_util.h" #import "ios/web/navigation/crw_session_controller.h" #import "ios/web/navigation/crw_session_entry.h" +#include "ios/web/net/clients/crw_redirect_network_client_factory.h" #import "ios/web/net/crw_url_verifying_protocol_handler.h" #include "ios/web/net/request_group_util.h" #include "ios/web/public/url_scheme_util.h" @@ -54,7 +55,8 @@ const int64 kContinuousCheckIntervalMSLow = 3000; } // namespace web -@interface CRWUIWebViewWebController ()<UIWebViewDelegate> { +@interface CRWUIWebViewWebController () <CRWRedirectClientDelegate, + UIWebViewDelegate> { // The UIWebView managed by this instance. base::scoped_nsobject<UIWebView> _uiWebView; @@ -123,6 +125,10 @@ const int64 kContinuousCheckIntervalMSLow = 3000; // Backs the property of the same name. id<CRWRecurringTaskDelegate>_recurringTaskDelegate; + + // Redirect client factory. + base::scoped_nsobject<CRWRedirectNetworkClientFactory> + redirect_client_factory_; } // Whether or not URL caching is enabled. Between enabling and disabling @@ -326,6 +332,30 @@ const size_t kMaxMessageQueueSize = 262144; @"UIMoviePlayerControllerDidExitFullscreenNotification" object:nil]; _recurringTaskDelegate = self; + + // UIWebViews require a redirect network client in order to accurately + // detect server redirects. + redirect_client_factory_.reset( + [[CRWRedirectNetworkClientFactory alloc] initWithDelegate:self]); + // WeakNSObjects cannot be dereferenced outside of the main thread, and + // CRWWebController must be deallocated from the main thread. Keep a + // reference to self on the main thread and release it after successfully + // adding the redirect client factory to the RequestTracker on the IO + // thread. + __block base::scoped_nsobject<CRWUIWebViewWebController> scopedSelf( + [self retain]); + web::WebThread::PostTaskAndReply( + web::WebThread::IO, FROM_HERE, base::BindBlock(^{ + // Only add the factory if there is a valid request tracker. + web::WebStateImpl* webState = [scopedSelf webStateImpl]; + if (webState && webState->GetRequestTracker()) { + webState->GetRequestTracker()->AddNetworkClientFactory( + redirect_client_factory_); + } + }), + base::BindBlock(^{ + scopedSelf.reset(); + })); } return self; } @@ -1318,6 +1348,21 @@ const size_t kMaxMessageQueueSize = 262144; } #pragma mark - +#pragma mark CRWRedirectClientDelegate + +- (void)wasRedirectedToRequest:(NSURLRequest*)request + redirectResponse:(NSURLResponse*)response { + // Register the redirected load request if it originated from the main page + // load. + GURL redirectedURL = net::GURLWithNSURL(response.URL); + if ([self currentNavigationURL] == redirectedURL) { + [self registerLoadRequest:net::GURLWithNSURL(request.URL) + referrer:[self currentReferrer] + transition:ui::PAGE_TRANSITION_SERVER_REDIRECT]; + } +} + +#pragma mark - #pragma mark UIWebViewDelegate Methods // Called when a load begins, and for subsequent subpages. diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm index f35c593..7450809 100644 --- a/ios/web/web_state/web_state_impl.mm +++ b/ios/web/web_state/web_state_impl.mm @@ -341,6 +341,7 @@ void WebStateImpl::ClearWebInterstitialForNavigation() { // interstitial, have the session controller go back one page. [sessionController goBack]; } + [sessionController discardNonCommittedEntries]; interstitial->DontProceed(); } } |