Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Unified Diff: ios/web/web_state/ui/crw_wk_web_view_web_controller.mm

Issue 1375023002: Adds support for POST request with bodies on WKWebView. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: missing file Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 c680bac819c6c8de6d660337a0b4c3c270862794..e22a14b9ef5b83e69a27bcd51d56f98045c3b037 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
@@ -10,7 +10,7 @@
#include "base/ios/ios_util.h"
#include "base/ios/weak_nsobject.h"
#include "base/json/json_reader.h"
-#include "base/mac/objc_property_releaser.h"
+#import "base/mac/objc_property_releaser.h"
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
@@ -39,6 +39,7 @@
#import "ios/web/web_state/crw_pass_kit_downloader.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/ui/crw_web_controller+protected.h"
#import "ios/web/web_state/ui/crw_wk_script_message_router.h"
@@ -152,6 +153,8 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
#pragma mark -
@interface CRWWKWebViewWebController ()<WKNavigationDelegate, WKUIDelegate> {
+ base::mac::ObjCPropertyReleaser _propertyReleaser_CRWWKWebViewWebController;
Eugene But (OOO till 7-30) 2015/12/02 17:06:16 Please don't use property releaser here. All memor
stkhapugin 2015/12/03 15:43:02 Done.
+
// The WKWebView managed by this instance.
base::scoped_nsobject<WKWebView> _wkWebView;
@@ -217,6 +220,9 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
BOOL _webProcessIsDead;
}
+// 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
@@ -233,6 +239,16 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
// Downloader for PassKit files. Lazy initialized.
@property(nonatomic, readonly) CRWPassKitDownloader* passKitDownloader;
+// Loads POST request with body in |_wkWebView| by constructing an HTML page
+// that executes the request through javascript and replaces document with the
+// 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/12/02 17:06:16 Word before argument should describe argument. How
stkhapugin 2015/12/03 15:43:02 Done.
+
// Returns the WKWebViewConfigurationProvider associated with the web
// controller's BrowserState.
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider;
@@ -379,6 +395,7 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
@end
@implementation CRWWKWebViewWebController
+@synthesize POSTRequestLoader = _POSTRequestLoader;
#pragma mark CRWWebController public methods
@@ -387,6 +404,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]);
_certVerificationErrors.reset(
@@ -557,25 +576,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
@@ -592,12 +620,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;
@@ -605,6 +647,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
@@ -715,6 +758,25 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
return self.webStateImpl->GetRequestTracker()->identifier();
}
+- (void)loadPOSTRequestWithBody:(NSMutableURLRequest*)request {
+ if (!self.POSTRequestLoader) {
Eugene But (OOO till 7-30) 2015/12/02 17:06:16 s/self.POSTRequestLoader/_POSTRequestLoader
stkhapugin 2015/12/03 15:43:02 Done.
+ _POSTRequestLoader = [[CRWJSPOSTRequestLoader alloc] init];
+ }
+
+ CRWWKScriptMessageRouter* messageRouter =
+ [self webViewConfigurationProvider].GetScriptMessageRouter();
+
+ [self.POSTRequestLoader loadPOSTRequest:request
+ inWebView:_wkWebView
Eugene But (OOO till 7-30) 2015/12/02 17:06:16 This is not correct formatting. Di you run git cl
stkhapugin 2015/12/03 15:43:02 Done. git cl format doesn't format some things for
+ messageRouter:messageRouter
+ errorBlock:^(NSError* loadError) {
+ [self handleLoadError:loadError inMainFrame:YES];
+ }
+ successBlock:^{
+ self.webStateImpl->SetContentsMimeType("text/html");
+ }];
+}
+
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider {
DCHECK(self.webStateImpl);
web::BrowserState* browserState = self.webStateImpl->GetBrowserState();
@@ -850,19 +912,12 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
web::WKBackForwardListItemHolder* holder =
[self currentBackForwardListItemHolder];
-
WKNavigationType navigationType =
_pendingNavigationInfo ? [_pendingNavigationInfo navigationType]
: WKNavigationTypeOther;
- holder->set_back_forward_list_item([_wkWebView backForwardList].currentItem);
- holder->set_navigation_type(navigationType);
-
- // Only update the MIME type in the holder if there was MIME type information
- // as part of this pending load. It will be nil when doing a fast
- // back/forward navigation, for instance, because the callback that would
- // populate it is not called in that flow.
- if ([_pendingNavigationInfo MIMEType])
- holder->set_mime_type([_pendingNavigationInfo MIMEType]);
+ holder->set_back_forward_list_item(
+ [_wkWebView backForwardList].currentItem);
+ holder->set_navigation_type(navigationType);
}
- (BOOL)isBackForwardListItemValid:(WKBackForwardListItem*)item {
@@ -1542,15 +1597,10 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
return;
}
GURL jsURL([result UTF8String]);
- // Make sure that the window location is as expected,
- // and re-check the origin and web view URL to prevent
- // race conditions.
- // TODO(crbug.com/563568): The third check may drop same
- // document URL changes if pending URL change occurs
- // immediately after. Revisit heuristics to prevent this.
+ // Make sure that the URL is as expected, and re-check
+ // the origin to prevent race conditions.
if (jsURL == url &&
- _documentURL.GetOrigin() == url.GetOrigin() &&
- net::GURLWithNSURL([_wkWebView URL]) == url) {
+ _documentURL.GetOrigin() == url.GetOrigin()) {
[self URLDidChangeWithoutDocumentChange:url];
}
}];
@@ -1714,17 +1764,6 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
DCHECK(_documentURL == self.lastRegisteredRequestURL);
self.webStateImpl->OnNavigationCommitted(_documentURL);
[self commitPendingNavigationInfo];
- if ([self currentBackForwardListItemHolder]->navigation_type() ==
- WKNavigationTypeBackForward) {
- // A fast back/forward won't call decidePolicyForNavigationResponse, so
- // the MIME type needs to be updated explicitly.
- NSString* storedMIMEType =
- [self currentBackForwardListItemHolder]->mime_type();
- if (storedMIMEType) {
- self.webStateImpl->SetContentsMimeType(
- base::SysNSStringToUTF8(storedMIMEType));
- }
- }
[self webPageChanged];
[self updateSSLStatusForCurrentNavigationItem];

Powered by Google App Engine
This is Rietveld 408576698