Bug 137302 - location.href is not updated on a redirect with a custom protocol
Summary: location.href is not updated on a redirect with a custom protocol
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit API (show other bugs)
Version: 528+ (Nightly build)
Hardware: iPhone / iPad Other
: P2 Major
Assignee: Nobody
URL: http://m.wikipedia.org
Keywords:
Depends on:
Blocks:
 
Reported: 2014-10-01 07:06 PDT by Daniel
Modified: 2016-09-17 07:03 PDT (History)
8 users (show)

See Also:


Attachments
Automatic test case code (3.88 KB, patch)
2014-10-01 07:10 PDT, Daniel
no flags Details | Formatted Diff | Diff
Patch (11.70 KB, patch)
2014-10-09 05:37 PDT, Daniel
no flags Details | Formatted Diff | Diff
Patch (11.78 KB, patch)
2014-10-10 01:25 PDT, Daniel
no flags Details | Formatted Diff | Diff
Patch (12.46 KB, patch)
2014-10-27 06:12 PDT, Daniel
no flags Details | Formatted Diff | Diff
Patch (13.63 KB, patch)
2014-10-30 06:22 PDT, Daniel
no flags Details | Formatted Diff | Diff
Patch (13.88 KB, patch)
2014-10-31 03:26 PDT, Daniel
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel 2014-10-01 07:06:57 PDT
If there's a custom NSURLProtocol, which is redirecting some page, the web view URL (as reported by javascript location.href) is not updated.
If page p1 redirects to p2, then the final location.href will be p1 (while expected is p2).
This happens only if the protocol is registered using [WKBrowsingContextController registerSchemeForCustomProtocol:], because otherwise the protocol code is bypassed.

Happens on iOS 8.1 [12B401].
I'm providing a test case code for the master branch at 809db5f8edac632ec3332b43dc90795d96914440.

Test case:
https://gist.github.com/anonymous/7fd3352c9f51eea9c4ce
Run it with ./TestWebKitAPI --gtest_filter=WebKit2CustomProtocolsTest.RedirectChangesURL

Manual test case on iOS:
1. go to http://m.wikipedia.org/
2. click a link
Expected results: link loads a page like http://en.m.wikipedia.org/wiki/Deaths_in_2014
Actual results: 404 error, because the link host is "m.wikipedia.org", and was not updated to en.m.wikipedia.org
Comment 1 Daniel 2014-10-01 07:10:43 PDT
Created attachment 239025 [details]
Automatic test case code
Comment 2 Daniel 2014-10-08 07:07:57 PDT
If I understand it right the reason for this is that WKCustomProtocolLoader doesn't forward a redirect event back to the web process. When a redirect happens, "connection:willSendRequest:redirectResponse:" method is called, which should send a message about the redirect to the web process so that it propagates to an URL change.

See:
https://github.com/WebKit/webkit/blob/master/Source/WebKit2/UIProcess/Network/CustomProtocols/mac/CustomProtocolManagerProxyMac.mm#L112

I'm going to make a patch for this.
Comment 3 Daniel 2014-10-09 05:37:38 PDT
Created attachment 239529 [details]
Patch
Comment 4 Darin Adler 2014-10-09 09:24:50 PDT
Comment on attachment 239529 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=239529&action=review

> Source/WebCore/platform/network/CredentialStorage.cpp:128
>      ASSERT(url.isValid());

Why is it OK to assert this? Can’t the redirect be an invalid URL as well as a valid non-HTTP URL?
Comment 5 Daniel 2014-10-10 01:24:57 PDT
Darin, thanks for looking at the patch.
You were right, I've tried to do a test redirect to an URL like "http://[::1", i.e. an URL where a host has an invalid IPv6 format, and it triggered this second ASSERT.
Uploading a fix.
Comment 6 Daniel 2014-10-10 01:25:21 PDT
Created attachment 239608 [details]
Patch
Comment 7 Benjamin Poulain 2014-10-24 17:20:27 PDT
Comment on attachment 239608 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=239608&action=review

Round1: Quick review, mostly style.

> Source/WebCore/ChangeLog:3
> +        Allow non-HTTP or invalid URLs to be passed to findDefaultProtectionSpaceForURL

You should keep the title in sync with the bug report on bugzilla.

This line of explanation should go under the "Reviewed by" line.

> Source/WebCore/ChangeLog:12
> +        No new tests, no behavior change.

You can only use this excuse for tests when you believe there is no observable difference after your change.

In this case, we would crash in Debug due to the assertion so it is observable and should have a test.

> Source/WebKit2/ChangeLog:3
> +        Add CustomProtocolManager::DidRedirect message

Keep the title "location.href is not updated on a redirect with a custom protocol" and have the explanation below.

> Source/WebKit2/ChangeLog:9
> +        The message is received after an HTTP redirect,
> +        and is forwarded to the NSURLProtocol client.

Here you should have an explanation of the bug, why it happens, and how you solved it.

> Source/WebKit2/UIProcess/Network/CustomProtocols/mac/CustomProtocolManagerProxyMac.mm:112
> +    // not a redirect, just continue

Comments should be complete sentences in WebKit, starting with uppercase for the first letter, and ending with a period.

> Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:60
> +    NSMutableURLRequest *request = [self.request mutableCopy];
> +    RetainPtr<NSMutableURLRequest> requestPtr = adoptNS(request);

Let's merge those two lines.

> Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:64
> +    NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:targetURL
> +        statusCode:302 HTTPVersion:@"HTTP/1.0" headerFields:@{ @"Location" : targetURL.absoluteString }];

Objective-C multiline alignment is a bit weird. You should split this with one line per argument and get XCode to align it for you.
Comment 8 Daniel 2014-10-27 06:12:21 PDT
Created attachment 240478 [details]
Patch
Comment 9 WebKit Commit Bot 2014-10-27 06:13:35 PDT
Attachment 240478 [details] did not pass style-queue:


ERROR: Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:64:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
ERROR: Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:65:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 2 in 9 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 10 Daniel 2014-10-27 06:17:26 PDT
> You can only use this excuse for tests when you believe there is no observable difference after your change.
> In this case, we would crash in Debug due to the assertion so it is observable and should have a test.

I couldn't find a place in code where I could put a simple unit test for CredentialStorage::findDefaultProtectionSpaceForURL, so I've just changed the log message.

The rest remarks are fixed.

> Weird number of spaces at line-start
What does it mean?
I did Xcode style indentation there that you've asked there.
Comment 11 Daniel 2014-10-30 06:22:00 PDT
Created attachment 240670 [details]
Patch
Comment 12 Daniel 2014-10-30 06:22:48 PDT
Fixed compiling on Linux.
Comment 13 WebKit Commit Bot 2014-10-30 06:24:06 PDT
Attachment 240670 [details] did not pass style-queue:


ERROR: Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:64:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
ERROR: Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:65:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 2 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 14 Benjamin Poulain 2014-10-30 15:09:07 PDT
Comment on attachment 240670 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=240670&action=review

> > Weird number of spaces at line-start
> What does it mean?
> I did Xcode style indentation there that you've asked there.

Don't worry, the style-checker does not know about Objective-C indentation. A code style "error" is a hint for reviewers.

> Source/WebCore/ChangeLog:13
> +        No new tests, just an ASSERT removal.

(In reply to comment #10)
> > You can only use this excuse for tests when you believe there is no observable difference after your change.
> > In this case, we would crash in Debug due to the assertion so it is observable and should have a test.
> 
> I couldn't find a place in code where I could put a simple unit test for
> CredentialStorage::findDefaultProtectionSpaceForURL, so I've just changed
> the log message.

Honestly I don't understand why you remove the assertion if you cannot find a case that hits it...

> Source/WebKit2/ChangeLog:10
> +        This was happening, because WKCustomProtocolLoader didn't forward

Extra coma "happening, because" -> happening because

> Source/WebKit2/UIProcess/Network/CustomProtocols/mac/CustomProtocolManagerProxyMac.mm:113
> +    if (redirectResponse == nil)

WebKit style is:
    if (!redirectResponse)

> Source/WebKit2/UIProcess/Network/CustomProtocols/mac/CustomProtocolManagerProxyMac.mm:121
> +    // Abandon the current connection, a new protocol connection for "request" will be initiated later.
> +    _customProtocolManagerProxy->stopLoading(_customProtocolID);

It is not clear to me why this is correct. NSURLConnection never calls connectionDidFinishLoading: for redirection? This interface should behave the same.
Comment 15 Daniel 2014-10-31 03:26:30 PDT
Created attachment 240730 [details]
Patch
Comment 16 WebKit Commit Bot 2014-10-31 03:28:43 PDT
Attachment 240730 [details] did not pass style-queue:


ERROR: Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:64:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
ERROR: Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:65:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 2 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 17 Daniel 2014-10-31 03:43:18 PDT
I've made the minor updates you've asked, and added some comments.

> Honestly I don't understand why you remove the assertion if you cannot find a case that hits it...

Of course, my new TC from TestWebKitAPI is affected. I've updated the comment to reflect that. I just thought that a change in WebCore must have a TC in WebCore.

> It is not clear to me why this is correct. NSURLConnection never calls connectionDidFinishLoading: for redirection? This interface should behave the same.

It's not the same. Although NSURLConnection stays on the same instance for doing redirects, it creates a new NSURLProtocol instance under the hood for each redirect. Each redirection gets a new NSURLProtocol in the web process, and makes a new startLoading call to the UI process. In respond to this in the UI process it creates a new instance of WKCustomProtocolLoader, and a new NSURLConnection. So the old NSURLConnection is not reused, which means that after a redirect it needs to be released. This is the purpose of this line.

Keep in mind that we are working with 2 NSURLConnection instances here. One is in the web process (somewhere in the networking code), and that's kept and reused. Another one is in the UI process (a part of WKCustomProtocolLoader), which is released after a redirect and not reused.
Comment 18 Michael Catanzaro 2016-09-17 07:03:07 PDT
Comment on attachment 240730 [details]
Patch

Hi,

Apologies that your patch was not reviewed in a timely manner. Since it's now quite old, I am removing it from the review request queue. Please consider rebasing it on trunk and resubmitting.

To increase the chances of getting a review, consider using 'Tools/Scripts/webkit-patch upload --suggest-reviewers' to CC reviewers who might be interested in this bug.