Index: ios/web/web_state/ui/crw_wk_web_view_web_controller.mm |
diff --git a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm |
index 368587eab562249bab292466ff34a608391942d3..8dc33797769a63e33b5e1ebb9df9202da6601acb 100644 |
--- a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm |
+++ b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm |
@@ -9,6 +9,7 @@ |
#include "base/ios/ios_util.h" |
#include "base/ios/weak_nsobject.h" |
#include "base/json/json_reader.h" |
+#import "base/mac/objc_property_releaser.h" |
#import "base/mac/scoped_nsobject.h" |
#include "base/macros.h" |
#include "base/strings/sys_string_conversions.h" |
@@ -31,6 +32,7 @@ |
#include "ios/web/web_state/blocked_popup_info.h" |
#import "ios/web/web_state/error_translation_util.h" |
#include "ios/web/web_state/frame_info.h" |
+#import "ios/web/web_state/js/crw_js_post_request_loader.h" |
#import "ios/web/web_state/js/crw_js_window_id_manager.h" |
#import "ios/web/web_state/js/page_script_util.h" |
#import "ios/web/web_state/ui/crw_web_controller+protected.h" |
@@ -85,6 +87,8 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
@interface CRWWKWebViewWebController () <WKNavigationDelegate, |
WKScriptMessageHandler, |
WKUIDelegate> { |
+ base::mac::ObjCPropertyReleaser _propertyReleaser_CRWWKWebViewWebController; |
Eugene But (OOO till 7-30)
2015/10/08 17:46:33
I would prefer to avoid mixing ObjCPropertyRelease
stkhapugin
2015/12/03 15:43:01
Done.
|
+ |
// The WKWebView managed by this instance. |
base::scoped_nsobject<WKWebView> _wkWebView; |
@@ -150,6 +154,9 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
// Response's MIME type of the last known navigation. |
@property(nonatomic, copy) NSString* documentMIMEType; |
+// Object for loading POST requests with body. |
+@property(nonatomic, retain) CRWJSPOSTRequestLoader* POSTRequestLoader; |
+ |
// Dictionary where keys are the names of WKWebView properties and values are |
// selector names which should be called when a corresponding property has |
// changed. e.g. @{ @"URL" : @"webViewURLDidChange" } means that |
@@ -169,6 +176,16 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
@property(nonatomic, readonly) int certGroupID; |
#endif // #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) |
+// Loads POST request with body in |_wkWebView| by constructing an HTML page |
+// that executes the request through javascript and replaces document with the |
Eugene But (OOO till 7-30)
2015/10/08 17:46:33
NIT: s/javascript/JavaScript
stkhapugin
2015/12/03 15:43:01
Done.
|
+// result. |
+// Note that this approach includes multiple body encodings and decodings, plus |
+// the data is passed to |_wkWebView| on main thread, hence the performance is |
+// expected to be low. |
+// This is necessary because WKWebView ignores POST request body. |
+// Workaround for https://bugs.webkit.org/show_bug.cgi?id=145410 |
+- (void)loadPOSTRequestWithBody:(NSMutableURLRequest*)request; |
Eugene But (OOO till 7-30)
2015/10/08 17:46:33
Word before argument should describe argument. Thi
stkhapugin
2015/12/03 15:43:01
Done.
|
+ |
// Returns the WKWebViewConfigurationProvider associated with the web |
// controller's BrowserState. |
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider; |
@@ -296,6 +313,7 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
@end |
@implementation CRWWKWebViewWebController |
+@synthesize POSTRequestLoader = _POSTRequestLoader; |
#pragma mark CRWWebController public methods |
@@ -304,6 +322,8 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
web::BrowserState* browserState = webState->GetBrowserState(); |
self = [super initWithWebState:webState.Pass()]; |
if (self) { |
+ _propertyReleaser_CRWWKWebViewWebController.Init( |
+ self, [CRWWKWebViewWebController class]); |
_certVerificationController.reset([[CRWCertVerificationController alloc] |
initWithBrowserState:browserState]); |
} |
@@ -477,25 +497,34 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
- (void)loadRequestForCurrentNavigationItem { |
DCHECK(self.webView && !self.nativeController); |
+ DCHECK([self currentSessionEntry]); |
+ |
+ web::WKBackForwardListItemHolder* holder = |
+ [self currentBackForwardListItemHolder]; |
+ BOOL isFormResubmission = |
+ (holder->navigation_type() == WKNavigationTypeFormResubmitted || |
+ holder->navigation_type() == WKNavigationTypeFormSubmitted); |
+ web::NavigationItemImpl* currentItem = |
+ [self currentSessionEntry].navigationItemImpl; |
+ NSData* POSTData = currentItem->GetPostData(); |
+ NSMutableURLRequest* request = [self requestForCurrentNavigationItem]; |
ProceduralBlock defaultNavigationBlock = ^{ |
[self registerLoadRequest:[self currentNavigationURL] |
referrer:[self currentSessionEntryReferrer] |
transition:[self currentTransition]]; |
- [self loadRequest:[self requestForCurrentNavigationItem]]; |
+ [self loadRequest:request]; |
}; |
- // If there is no corresponding WKBackForwardListItem, or the item is not in |
- // the current WKWebView's back-forward list, navigating using WKWebView API |
- // is not possible. In this case, fall back to the default navigation |
- // mechanism. |
- web::WKBackForwardListItemHolder* holder = |
- [self currentBackForwardListItemHolder]; |
- if (!holder->back_forward_list_item() || |
- ![self isBackForwardListItemValid:holder->back_forward_list_item()]) { |
- defaultNavigationBlock(); |
- return; |
- } |
+ ProceduralBlock POSTBlock = ^{ |
+ [request setHTTPMethod:@"POST"]; |
+ [request setHTTPBody:POSTData]; |
+ [request setAllHTTPHeaderFields:[self currentHTTPHeaders]]; |
+ [self registerLoadRequest:[self currentNavigationURL] |
+ referrer:[self currentSessionEntryReferrer] |
+ transition:[self currentTransition]]; |
+ [self loadPOSTRequestWithBody:request]; |
+ }; |
ProceduralBlock webViewNavigationBlock = ^{ |
// If the current navigation URL is the same as the URL of the visible |
@@ -512,12 +541,26 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
} |
}; |
+ // If the request has POST data and is not a form resubmission, configure and |
+ // run the POST request. |
+ if (POSTData.length && !isFormResubmission) { |
+ POSTBlock(); |
+ return; |
+ } |
+ |
+ // If there is no corresponding WKBackForwardListItem, or the item is not in |
+ // the current WKWebView's back-forward list, navigating using WKWebView API |
+ // is not possible. In this case, fall back to the default navigation |
+ // mechanism. |
+ if (!holder->back_forward_list_item() || |
+ ![self isBackForwardListItemValid:holder->back_forward_list_item()]) { |
+ defaultNavigationBlock(); |
+ return; |
+ } |
+ |
// If the request is not a form submission or resubmission, or the user |
// doesn't need to confirm the load, then continue right away. |
- web::NavigationItemImpl* currentItem = |
- [self currentSessionEntry].navigationItemImpl; |
- if ((holder->navigation_type() != WKNavigationTypeFormResubmitted && |
- holder->navigation_type() != WKNavigationTypeFormSubmitted) || |
+ if (!isFormResubmission || |
currentItem->ShouldSkipResubmitDataConfirmation()) { |
webViewNavigationBlock(); |
return; |
@@ -525,6 +568,7 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
// If the request is form submission or resubmission, then prompt the |
// user before proceeding. |
+ DCHECK(isFormResubmission); |
[self.delegate webController:self |
onFormResubmissionForRequest:nil |
continueBlock:webViewNavigationBlock |
@@ -635,6 +679,14 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
} |
#endif |
+- (void)loadPOSTRequestWithBody:(NSMutableURLRequest*)request { |
+ if (!self.POSTRequestLoader) { |
+ _POSTRequestLoader = [[CRWJSPOSTRequestLoader alloc] init]; |
+ } |
+ |
+ [self.POSTRequestLoader loadPOSTRequest:request inWebView:_wkWebView]; |
+} |
+ |
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider { |
DCHECK(self.webStateImpl); |
web::BrowserState* browserState = self.webStateImpl->GetBrowserState(); |