Changeset 187691 in webkit


Ignore:
Timestamp:
Jul 31, 2015 4:56:00 PM (9 years ago)
Author:
Chris Dumez
Message:

Source/WebCore:
Coalesce authentication credential requests
https://bugs.webkit.org/show_bug.cgi?id=128006
<rdar://problem/16839069>

Reviewed by Alexey Proskuryakov.

Export symbol for ProtectionSpace::compare() so it can be called from
WebKit2.

  • platform/network/ProtectionSpaceBase.h:

Source/WebKit2:
Coalesce concurrent authentication challenges for the same ProtectionSpace
https://bugs.webkit.org/show_bug.cgi?id=147496
<rdar://problem/16839069>

Reviewed by Alexey Proskuryakov.

Coalesce concurrent authentication challenges for the same ProtectionSpace.
Ideally, this would be done in the network layer but short term, this will
make sure the user no longer gets repeating authentication dialogs for the
same protection space.

This gets rid of a long-standing bug in WebKit / Safari where visiting a
site using HTTP authentication would pop up one authentication dialog for
each subresource being loaded from the network (especially when the main
resource is loaded from the cache).

  • Shared/Authentication/AuthenticationManager.cpp:

(WebKit::canCoalesceChallenge):
(WebKit::AuthenticationManager::addChallengeToChallengeMap):
(WebKit::AuthenticationManager::shouldCoalesceChallenge):
(WebKit::AuthenticationManager::coalesceChallengesMatching):
(WebKit::AuthenticationManager::didReceiveAuthenticationChallenge):
(WebKit::AuthenticationManager::useCredentialForChallenge):
(WebKit::AuthenticationManager::useCredentialForSingleChallenge):
(WebKit::AuthenticationManager::continueWithoutCredentialForChallenge):
(WebKit::AuthenticationManager::continueWithoutCredentialForSingleChallenge):
(WebKit::AuthenticationManager::cancelChallenge):
(WebKit::AuthenticationManager::cancelSingleChallenge):
(WebKit::AuthenticationManager::performDefaultHandling):
(WebKit::AuthenticationManager::performDefaultHandlingForSingleChallenge):
(WebKit::AuthenticationManager::rejectProtectionSpaceAndContinue):
(WebKit::AuthenticationManager::rejectProtectionSpaceAndContinueForSingleChallenge):
(WebKit::AuthenticationManager::AuthenticationManager): Deleted.

  • Shared/Authentication/AuthenticationManager.h:
Location:
trunk/Source
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r187688 r187691  
     12015-07-31  Chris Dumez  <cdumez@apple.com>
     2
     3        Coalesce authentication credential requests
     4        https://bugs.webkit.org/show_bug.cgi?id=128006
     5        <rdar://problem/16839069>
     6
     7        Reviewed by Alexey Proskuryakov.
     8
     9        Export symbol for ProtectionSpace::compare() so it can be called from
     10        WebKit2.
     11
     12        * platform/network/ProtectionSpaceBase.h:
     13
    1142015-07-31  Eric Carlson  <eric.carlson@apple.com>
    215
  • trunk/Source/WebCore/platform/network/ProtectionSpaceBase.h

    r187367 r187691  
    7373    bool encodingRequiresPlatformData() const { return false; }
    7474
    75     static bool compare(const ProtectionSpace& a, const ProtectionSpace& b);
     75    WEBCORE_EXPORT static bool compare(const ProtectionSpace&, const ProtectionSpace&);
    7676
    7777protected:
  • trunk/Source/WebKit2/ChangeLog

    r187682 r187691  
     12015-07-31  Chris Dumez  <cdumez@apple.com>
     2
     3        Coalesce concurrent authentication challenges for the same ProtectionSpace
     4        https://bugs.webkit.org/show_bug.cgi?id=147496
     5        <rdar://problem/16839069>
     6
     7        Reviewed by Alexey Proskuryakov.
     8
     9        Coalesce concurrent authentication challenges for the same ProtectionSpace.
     10        Ideally, this would be done in the network layer but short term, this will
     11        make sure the user no longer gets repeating authentication dialogs for the
     12        same protection space.
     13
     14        This gets rid of a long-standing bug in WebKit / Safari where visiting a
     15        site using HTTP authentication would pop up one authentication dialog for
     16        each subresource being loaded from the network (especially when the main
     17        resource is loaded from the cache).
     18
     19        * Shared/Authentication/AuthenticationManager.cpp:
     20        (WebKit::canCoalesceChallenge):
     21        (WebKit::AuthenticationManager::addChallengeToChallengeMap):
     22        (WebKit::AuthenticationManager::shouldCoalesceChallenge):
     23        (WebKit::AuthenticationManager::coalesceChallengesMatching):
     24        (WebKit::AuthenticationManager::didReceiveAuthenticationChallenge):
     25        (WebKit::AuthenticationManager::useCredentialForChallenge):
     26        (WebKit::AuthenticationManager::useCredentialForSingleChallenge):
     27        (WebKit::AuthenticationManager::continueWithoutCredentialForChallenge):
     28        (WebKit::AuthenticationManager::continueWithoutCredentialForSingleChallenge):
     29        (WebKit::AuthenticationManager::cancelChallenge):
     30        (WebKit::AuthenticationManager::cancelSingleChallenge):
     31        (WebKit::AuthenticationManager::performDefaultHandling):
     32        (WebKit::AuthenticationManager::performDefaultHandlingForSingleChallenge):
     33        (WebKit::AuthenticationManager::rejectProtectionSpaceAndContinue):
     34        (WebKit::AuthenticationManager::rejectProtectionSpaceAndContinueForSingleChallenge):
     35        (WebKit::AuthenticationManager::AuthenticationManager): Deleted.
     36        * Shared/Authentication/AuthenticationManager.h:
     37
    1382015-07-31  Joseph Pecoraro  <pecoraro@apple.com>
    239
  • trunk/Source/WebKit2/Shared/Authentication/AuthenticationManager.cpp

    r183861 r187691  
    5454}
    5555
     56static bool canCoalesceChallenge(const WebCore::AuthenticationChallenge& challenge)
     57{
     58    // Do not coalesce server trust evaluation requests because ProtectionSpace comparison does not evaluate server trust (e.g. certificate).
     59    return challenge.protectionSpace().authenticationScheme() != ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
     60}
     61
    5662const char* AuthenticationManager::supplementName()
    5763{
     
    6571}
    6672
    67 uint64_t AuthenticationManager::establishIdentifierForChallenge(const WebCore::AuthenticationChallenge& authenticationChallenge)
     73uint64_t AuthenticationManager::addChallengeToChallengeMap(const WebCore::AuthenticationChallenge& authenticationChallenge)
    6874{
    6975    ASSERT(RunLoop::isMain());
     
    7480}
    7581
     82bool AuthenticationManager::shouldCoalesceChallenge(uint64_t challengeID, const AuthenticationChallenge& challenge) const
     83{
     84    if (!canCoalesceChallenge(challenge))
     85        return false;
     86
     87    auto end =  m_challenges.end();
     88    for (auto it = m_challenges.begin(); it != end; ++it) {
     89        if (it->key != challengeID && ProtectionSpace::compare(challenge.protectionSpace(), it->value.protectionSpace()))
     90            return true;
     91    }
     92    return false;
     93}
     94
     95Vector<uint64_t> AuthenticationManager::coalesceChallengesMatching(uint64_t challengeID) const
     96{
     97    AuthenticationChallenge challenge = m_challenges.get(challengeID);
     98    ASSERT(!challenge.isNull());
     99
     100    Vector<uint64_t> challengesToCoalesce;
     101    challengesToCoalesce.append(challengeID);
     102
     103    if (!canCoalesceChallenge(challenge))
     104        return challengesToCoalesce;
     105
     106    auto end = m_challenges.end();
     107    for (auto it = m_challenges.begin(); it != end; ++it) {
     108        if (it->key != challengeID && ProtectionSpace::compare(challenge.protectionSpace(), it->value.protectionSpace()))
     109            challengesToCoalesce.append(it->key);
     110    }
     111
     112    return challengesToCoalesce;
     113}
     114
    76115void AuthenticationManager::didReceiveAuthenticationChallenge(WebFrame* frame, const AuthenticationChallenge& authenticationChallenge)
    77116{
    78117    ASSERT(frame);
    79118    ASSERT(frame->page());
    80    
    81     m_process->send(Messages::WebPageProxy::DidReceiveAuthenticationChallenge(frame->frameID(), authenticationChallenge, establishIdentifierForChallenge(authenticationChallenge)), frame->page()->pageID());
     119
     120    uint64_t challengeID = addChallengeToChallengeMap(authenticationChallenge);
     121
     122    // Coalesce challenges in the same protection space.
     123    if (shouldCoalesceChallenge(challengeID, authenticationChallenge))
     124        return;
     125   
     126    m_process->send(Messages::WebPageProxy::DidReceiveAuthenticationChallenge(frame->frameID(), authenticationChallenge, challengeID), frame->page()->pageID());
    82127}
    83128
     
    87132    ASSERT(pageID);
    88133    ASSERT(frameID);
    89    
    90     m_process->send(Messages::NetworkProcessProxy::DidReceiveAuthenticationChallenge(pageID, frameID, authenticationChallenge, establishIdentifierForChallenge(authenticationChallenge)));
     134
     135    uint64_t challengeID = addChallengeToChallengeMap(authenticationChallenge);
     136    if (shouldCoalesceChallenge(challengeID, authenticationChallenge))
     137        return;
     138   
     139    m_process->send(Messages::NetworkProcessProxy::DidReceiveAuthenticationChallenge(pageID, frameID, authenticationChallenge, addChallengeToChallengeMap(authenticationChallenge)));
    91140}
    92141#endif
     
    94143void AuthenticationManager::didReceiveAuthenticationChallenge(Download* download, const AuthenticationChallenge& authenticationChallenge)
    95144{
    96     download->send(Messages::DownloadProxy::DidReceiveAuthenticationChallenge(authenticationChallenge, establishIdentifierForChallenge(authenticationChallenge)));
     145    uint64_t challengeID = addChallengeToChallengeMap(authenticationChallenge);
     146    if (shouldCoalesceChallenge(challengeID, authenticationChallenge))
     147        return;
     148
     149    download->send(Messages::DownloadProxy::DidReceiveAuthenticationChallenge(authenticationChallenge, addChallengeToChallengeMap(authenticationChallenge)));
    97150}
    98151
     
    109162    ASSERT(RunLoop::isMain());
    110163
     164    for (auto& coalescedChallengeID : coalesceChallengesMatching(challengeID))
     165        useCredentialForSingleChallenge(coalescedChallengeID, credential, certificateInfo);
     166}
     167
     168void AuthenticationManager::useCredentialForSingleChallenge(uint64_t challengeID, const Credential& credential, const CertificateInfo& certificateInfo)
     169{
    111170    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    112171    ASSERT(!challenge.isNull());
     
    130189    ASSERT(RunLoop::isMain());
    131190
     191    for (auto& coalescedChallengeID : coalesceChallengesMatching(challengeID))
     192        continueWithoutCredentialForSingleChallenge(coalescedChallengeID);
     193}
     194
     195void AuthenticationManager::continueWithoutCredentialForSingleChallenge(uint64_t challengeID)
     196{
    132197    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    133198    ASSERT(!challenge.isNull());
     
    147212    ASSERT(RunLoop::isMain());
    148213
     214    for (auto& coalescedChallengeID : coalesceChallengesMatching(challengeID))
     215        cancelSingleChallenge(coalescedChallengeID);
     216}
     217
     218void AuthenticationManager::cancelSingleChallenge(uint64_t challengeID)
     219{
    149220    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    150221    ASSERT(!challenge.isNull());
     
    164235    ASSERT(RunLoop::isMain());
    165236
     237    for (auto& coalescedChallengeID : coalesceChallengesMatching(challengeID))
     238        performDefaultHandlingForSingleChallenge(coalescedChallengeID);
     239}
     240
     241void AuthenticationManager::performDefaultHandlingForSingleChallenge(uint64_t challengeID)
     242{
    166243    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    167244    ASSERT(!challenge.isNull());
     
    181258    ASSERT(RunLoop::isMain());
    182259
     260    for (auto& coalescedChallengeID : coalesceChallengesMatching(challengeID))
     261        rejectProtectionSpaceAndContinueForSingleChallenge(coalescedChallengeID);
     262}
     263
     264void AuthenticationManager::rejectProtectionSpaceAndContinueForSingleChallenge(uint64_t challengeID)
     265{
    183266    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    184267    ASSERT(!challenge.isNull());
  • trunk/Source/WebKit2/Shared/Authentication/AuthenticationManager.h

    r177917 r187691  
    7474    bool tryUseCertificateInfoForChallenge(const WebCore::AuthenticationChallenge&, const WebCore::CertificateInfo&);
    7575
    76     uint64_t establishIdentifierForChallenge(const WebCore::AuthenticationChallenge&);
     76    uint64_t addChallengeToChallengeMap(const WebCore::AuthenticationChallenge&);
     77    bool shouldCoalesceChallenge(uint64_t challengeID, const WebCore::AuthenticationChallenge&) const;
     78
     79    void useCredentialForSingleChallenge(uint64_t challengeID, const WebCore::Credential&, const WebCore::CertificateInfo&);
     80    void continueWithoutCredentialForSingleChallenge(uint64_t challengeID);
     81    void cancelSingleChallenge(uint64_t challengeID);
     82    void performDefaultHandlingForSingleChallenge(uint64_t challengeID);
     83    void rejectProtectionSpaceAndContinueForSingleChallenge(uint64_t challengeID);
     84
     85    Vector<uint64_t> coalesceChallengesMatching(uint64_t challengeID) const;
    7786
    7887    ChildProcess* m_process;
Note: See TracChangeset for help on using the changeset viewer.