Changeset 246569 in webkit
- Timestamp:
- Jun 18, 2019 2:40:27 PM (5 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r246568 r246569 1 2019-06-18 Alex Christensen <achristensen@webkit.org> 2 3 NetworkSession::networkStorageSession can return null 4 https://bugs.webkit.org/show_bug.cgi?id=198947 5 <rdar://problem/51394449> 6 7 Reviewed by Youenn Fablet. 8 9 We are seeing evidence of crashes from the map owning NetworkSessions and the map owning NetworkStorageSessions becoming out of sync 10 because NetworkSession is refcounted but NetworkStorageSession is not. I started the complete fix in https://bugs.webkit.org/show_bug.cgi?id=194926 11 but for now let's add less risky null checks to prevent fallout. 12 13 * NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp: 14 (WebKit::ResourceLoadStatisticsStore::updateClientSideCookiesAgeCap): 15 * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp: 16 (WebKit::WebResourceLoadStatisticsStore::hasStorageAccessForFrame): 17 (WebKit::WebResourceLoadStatisticsStore::callHasStorageAccessForFrameHandler): 18 (WebKit::WebResourceLoadStatisticsStore::grantStorageAccess): 19 (WebKit::WebResourceLoadStatisticsStore::removeAllStorageAccess): 20 (WebKit::WebResourceLoadStatisticsStore::setCacheMaxAgeCap): 21 (WebKit::WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler): 22 (WebKit::WebResourceLoadStatisticsStore::removePrevalentDomains): 23 * NetworkProcess/NetworkProcess.cpp: 24 (WebKit::NetworkProcess::initializeNetworkProcess): 25 * NetworkProcess/NetworkSession.cpp: 26 (WebKit::NetworkSession::networkStorageSession const): 27 * NetworkProcess/NetworkSession.h: 28 * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm: 29 (WebKit::NetworkDataTaskCocoa::applyCookieBlockingPolicy): 30 (WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa): 31 (WebKit::NetworkDataTaskCocoa::willPerformHTTPRedirection): 32 (WebKit::NetworkDataTaskCocoa::tryPasswordBasedAuthentication): 33 1 34 2019-06-18 Brady Eidson <beidson@apple.com> 2 35 -
trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp
r246561 r246569 384 384 #if ENABLE(RESOURCE_LOAD_STATISTICS) 385 385 RunLoop::main().dispatch([store = makeRef(m_store), seconds = m_parameters.clientSideCookiesAgeCapTime] () { 386 if (auto* networkSession = store->networkSession()) 387 networkSession->networkStorageSession().setAgeCapForClientSideCookies(seconds); 386 if (auto* networkSession = store->networkSession()) { 387 if (auto* storageSession = networkSession->networkStorageSession()) 388 storageSession->setAgeCapForClientSideCookies(seconds); 389 } 388 390 }); 389 391 #endif -
trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp
r246449 r246569 301 301 bool WebResourceLoadStatisticsStore::hasStorageAccessForFrame(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, uint64_t frameID, PageIdentifier pageID) 302 302 { 303 return m_networkSession ? m_networkSession->networkStorageSession().hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID) : false; 303 if (m_networkSession) { 304 if (auto* storageSession = m_networkSession->networkStorageSession()) 305 return storageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID); 306 } 307 return false; 304 308 } 305 309 … … 309 313 310 314 if (m_networkSession) { 311 callback(m_networkSession->networkStorageSession().hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID)); 312 return; 315 if (auto* storageSession = m_networkSession->networkStorageSession()) { 316 callback(storageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID)); 317 return; 318 } 313 319 } 314 320 … … 402 408 403 409 if (m_networkSession) { 404 m_networkSession->networkStorageSession().grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID); 405 ASSERT(m_networkSession->networkStorageSession().hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID)); 406 isStorageGranted = true; 410 if (auto* storageSession = m_networkSession->networkStorageSession()) { 411 storageSession->grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID); 412 ASSERT(storageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID)); 413 isStorageGranted = true; 414 } 407 415 } 408 416 … … 432 440 ASSERT(RunLoop::isMain()); 433 441 434 if (m_networkSession) 435 m_networkSession->networkStorageSession().removeAllStorageAccess(); 442 if (m_networkSession) { 443 if (auto* storageSession = m_networkSession->networkStorageSession()) 444 storageSession->removeAllStorageAccess(); 445 } 436 446 437 447 completionHandler(); … … 937 947 ASSERT(seconds >= 0_s); 938 948 939 if (m_networkSession) 940 m_networkSession->networkStorageSession().setCacheMaxAgeCapForPrevalentResources(seconds); 949 if (m_networkSession) { 950 if (auto* storageSession = m_networkSession->networkStorageSession()) 951 storageSession->setCacheMaxAgeCapForPrevalentResources(seconds); 952 } 941 953 942 954 completionHandler(); … … 947 959 ASSERT(RunLoop::isMain()); 948 960 949 if (m_networkSession) 950 m_networkSession->networkStorageSession().setPrevalentDomainsToBlockCookiesFor(domainsToBlock); 961 if (m_networkSession) { 962 if (auto* storageSession = m_networkSession->networkStorageSession()) 963 storageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock); 964 } 951 965 952 966 completionHandler(); … … 955 969 void WebResourceLoadStatisticsStore::removePrevalentDomains(const Vector<RegistrableDomain>& domains) 956 970 { 957 if (m_networkSession) 958 m_networkSession->networkStorageSession().removePrevalentDomains(domains); 971 if (m_networkSession) { 972 if (auto* storageSession = m_networkSession->networkStorageSession()) 973 storageSession->removePrevalentDomains(domains); 974 } 959 975 } 960 976 -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp
r246530 r246569 336 336 337 337 auto* defaultSession = networkSession(PAL::SessionID::defaultSessionID()); 338 auto* defaultStorageSession = defaultSession->networkStorageSession(); 338 339 for (const auto& cookie : parameters.defaultDataStoreParameters.pendingCookies) 339 defaultS ession->networkStorageSession().setCookie(cookie);340 defaultStorageSession->setCookie(cookie); 340 341 341 342 for (auto& supplement : m_supplements.values()) -
trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp
r246449 r246569 69 69 } 70 70 71 NetworkStorageSession& NetworkSession::networkStorageSession() const 72 { 71 NetworkStorageSession* NetworkSession::networkStorageSession() const 72 { 73 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=194926 NetworkSession should own NetworkStorageSession 74 // instead of having separate maps with the same key and different management. 73 75 auto* storageSession = m_networkProcess->storageSession(m_sessionID); 74 RELEASE_ASSERT(storageSession);75 return *storageSession;76 ASSERT(storageSession); 77 return storageSession; 76 78 } 77 79 -
trunk/Source/WebKit/NetworkProcess/NetworkSession.h
r246449 r246569 73 73 PAL::SessionID sessionID() const { return m_sessionID; } 74 74 NetworkProcess& networkProcess() { return m_networkProcess; } 75 WebCore::NetworkStorageSession &networkStorageSession() const;75 WebCore::NetworkStorageSession* networkStorageSession() const; 76 76 77 77 void registerNetworkDataTask(NetworkDataTask& task) { m_dataTaskSet.add(&task); } -
trunk/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm
r245979 r246569 139 139 return; 140 140 141 NSHTTPCookieStorage *storage = shouldBlock ? statelessCookieStorage() : m_session->networkStorageSession().nsCookieStorage(); 142 [m_task _setExplicitCookieStorage:storage._cookieStorage]; 143 m_hasBeenSetToUseStatelessCookieStorage = shouldBlock; 141 NSHTTPCookieStorage *storage = nil; 142 if (shouldBlock) 143 storage = statelessCookieStorage(); 144 else if (auto* storageSession = m_session->networkStorageSession()) 145 storage = storageSession->nsCookieStorage(); 146 if (storage) { 147 [m_task _setExplicitCookieStorage:storage._cookieStorage]; 148 m_hasBeenSetToUseStatelessCookieStorage = shouldBlock; 149 } 144 150 } 145 151 #endif … … 181 187 182 188 #if USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION) 183 if (m_user.isEmpty() && m_password.isEmpty()) 184 m_initialCredential = m_session->networkStorageSession().credentialStorage().get(m_partition, url); 185 else 186 m_session->networkStorageSession().credentialStorage().set(m_partition, WebCore::Credential(m_user, m_password, WebCore::CredentialPersistenceNone), url); 189 if (auto* storageSession = m_session->networkStorageSession()) { 190 if (m_user.isEmpty() && m_password.isEmpty()) 191 m_initialCredential = storageSession->credentialStorage().get(m_partition, url); 192 else 193 storageSession->credentialStorage().set(m_partition, WebCore::Credential(m_user, m_password, WebCore::CredentialPersistenceNone), url); 194 } 187 195 #endif 188 196 } … … 197 205 bool shouldBlockCookies = false; 198 206 #if ENABLE(RESOURCE_LOAD_STATISTICS) 199 shouldBlockCookies = storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless || session.networkStorageSession().shouldBlockCookies(request, frameID, pageID); 207 shouldBlockCookies = storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless 208 || (session.networkStorageSession() && session.networkStorageSession()->shouldBlockCookies(request, frameID, pageID)); 200 209 #endif 201 210 restrictRequestReferrerToOriginIfNeeded(request, shouldBlockCookies); … … 352 361 // URL didn't include credentials of its own. 353 362 if (m_user.isEmpty() && m_password.isEmpty() && !redirectResponse.isNull()) { 354 auto credential = m_session->networkStorageSession() .credentialStorage().get(m_partition, request.url());363 auto credential = m_session->networkStorageSession() ? m_session->networkStorageSession()->credentialStorage().get(m_partition, request.url()) : WebCore::Credential(); 355 364 if (!credential.isEmpty()) { 356 365 m_initialCredential = credential; … … 367 376 368 377 #if ENABLE(RESOURCE_LOAD_STATISTICS) 369 bool shouldBlockCookies = m_storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless || m_session->networkStorageSession().shouldBlockCookies(request, m_frameID, m_pageID); 378 bool shouldBlockCookies = m_storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless 379 || (m_session->networkStorageSession() && m_session->networkStorageSession()->shouldBlockCookies(request, m_frameID, m_pageID)); 370 380 #if !RELEASE_LOG_DISABLED 371 381 if (m_session->shouldLogCookieInformation()) … … 398 408 if (!request.isNull()) { 399 409 #if ENABLE(RESOURCE_LOAD_STATISTICS) 400 bool shouldBlockCookies = m_session->networkStorageSession() .shouldBlockCookies(request, m_frameID, m_pageID);410 bool shouldBlockCookies = m_session->networkStorageSession() && m_session->networkStorageSession()->shouldBlockCookies(request, m_frameID, m_pageID); 401 411 #else 402 412 bool shouldBlockCookies = false; … … 446 456 // There is a race condition here, since a different credential might have already been stored by another ResourceHandle, 447 457 // but the observable effect should be very minor, if any. 448 m_session->networkStorageSession().credentialStorage().remove(m_partition, challenge.protectionSpace()); 458 if (auto* storageSession = m_session->networkStorageSession()) 459 storageSession->credentialStorage().remove(m_partition, challenge.protectionSpace()); 449 460 } 450 461 451 462 if (!challenge.previousFailureCount()) { 452 auto credential = m_session->networkStorageSession() .credentialStorage().get(m_partition, challenge.protectionSpace());463 auto credential = m_session->networkStorageSession() ? m_session->networkStorageSession()->credentialStorage().get(m_partition, challenge.protectionSpace()) : WebCore::Credential(); 453 464 if (!credential.isEmpty() && credential != m_initialCredential) { 454 465 ASSERT(credential.persistence() == WebCore::CredentialPersistenceNone); 455 466 if (challenge.failureResponse().httpStatusCode() == 401) { 456 467 // Store the credential back, possibly adding it as a default for this directory. 457 m_session->networkStorageSession().credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url()); 468 if (auto* storageSession = m_session->networkStorageSession()) 469 storageSession->credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url()); 458 470 } 459 471 completionHandler(AuthenticationChallengeDisposition::UseCredential, credential); -
trunk/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp
r246401 r246569 60 60 61 61 if (m_user.isEmpty() && m_password.isEmpty()) 62 m_initialCredential = m_session->networkStorageSession() .credentialStorage().get(m_partition, request.url());62 m_initialCredential = m_session->networkStorageSession()->credentialStorage().get(m_partition, request.url()); 63 63 else 64 m_session->networkStorageSession() .credentialStorage().set(m_partition, Credential(m_user, m_password, CredentialPersistenceNone), request.url());64 m_session->networkStorageSession()->credentialStorage().set(m_partition, Credential(m_user, m_password, CredentialPersistenceNone), request.url()); 65 65 } 66 66 } … … 288 288 // URL didn't include credentials of its own. 289 289 if (m_user.isEmpty() && m_password.isEmpty()) { 290 auto credential = m_session->networkStorageSession() .credentialStorage().get(m_partition, request.url());290 auto credential = m_session->networkStorageSession()->credentialStorage().get(m_partition, request.url()); 291 291 if (!credential.isEmpty()) { 292 292 m_initialCredential = credential; … … 338 338 // here, since a different credential might have already been stored by another 339 339 // NetworkDataTask, but the observable effect should be very minor, if any. 340 m_session->networkStorageSession() .credentialStorage().remove(m_partition, challenge.protectionSpace());340 m_session->networkStorageSession()->credentialStorage().remove(m_partition, challenge.protectionSpace()); 341 341 } 342 342 343 343 if (!challenge.previousFailureCount()) { 344 auto credential = m_session->networkStorageSession() .credentialStorage().get(m_partition, challenge.protectionSpace());344 auto credential = m_session->networkStorageSession()->credentialStorage().get(m_partition, challenge.protectionSpace()); 345 345 if (!credential.isEmpty() && credential != m_initialCredential) { 346 346 ASSERT(credential.persistence() == CredentialPersistenceNone); 347 347 if (challenge.failureResponse().isUnauthorized()) { 348 348 // Store the credential back, possibly adding it as a default for this directory. 349 m_session->networkStorageSession() .credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url());349 m_session->networkStorageSession()->credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url()); 350 350 } 351 351 restartWithCredential(challenge.protectionSpace(), credential); … … 368 368 if (m_storedCredentialsPolicy == StoredCredentialsPolicy::Use) { 369 369 if (credential.persistence() == CredentialPersistenceForSession || credential.persistence() == CredentialPersistencePermanent) 370 m_session->networkStorageSession() .credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url());370 m_session->networkStorageSession()->credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url()); 371 371 } 372 372 … … 445 445 void NetworkDataTaskCurl::appendCookieHeader(WebCore::ResourceRequest& request) 446 446 { 447 const auto &storageSession = m_session->networkStorageSession();448 const auto& cookieJar = storageSession .cookieStorage();447 const auto* storageSession = m_session->networkStorageSession(); 448 const auto& cookieJar = storageSession->cookieStorage(); 449 449 auto includeSecureCookies = request.url().protocolIs("https") ? IncludeSecureCookies::Yes : IncludeSecureCookies::No; 450 auto cookieHeaderField = cookieJar.cookieRequestHeaderFieldValue( storageSession, request.firstPartyForCookies(), WebCore::SameSiteInfo::create(request), request.url(), WTF::nullopt, WTF::nullopt, includeSecureCookies).first;450 auto cookieHeaderField = cookieJar.cookieRequestHeaderFieldValue(*storageSession, request.firstPartyForCookies(), WebCore::SameSiteInfo::create(request), request.url(), WTF::nullopt, WTF::nullopt, includeSecureCookies).first; 451 451 if (!cookieHeaderField.isEmpty()) 452 452 request.addHTTPHeaderField(HTTPHeaderName::Cookie, cookieHeaderField); … … 457 457 static const auto setCookieHeader = "set-cookie: "; 458 458 459 const auto &storageSession = m_session->networkStorageSession();460 const auto& cookieJar = storageSession .cookieStorage();459 const auto* storageSession = m_session->networkStorageSession(); 460 const auto& cookieJar = storageSession->cookieStorage(); 461 461 for (auto header : response.headers) { 462 462 if (header.startsWithIgnoringASCIICase(setCookieHeader)) { 463 463 String setCookieString = header.right(header.length() - strlen(setCookieHeader)); 464 cookieJar.setCookiesFromHTTPResponse( storageSession, request.firstPartyForCookies(), response.url, setCookieString);464 cookieJar.setCookiesFromHTTPResponse(*storageSession, request.firstPartyForCookies(), response.url, setCookieString); 465 465 } 466 466 } -
trunk/Source/WebKit/NetworkProcess/curl/NetworkSessionCurl.cpp
r245540 r246569 42 42 { 43 43 if (!parameters.cookiePersistentStorageFile.isEmpty()) 44 networkStorageSession() .setCookieDatabase(makeUniqueRef<CookieJarDB>(parameters.cookiePersistentStorageFile));45 networkStorageSession() .setProxySettings(WTFMove(parameters.proxySettings));44 networkStorageSession()->setCookieDatabase(makeUniqueRef<CookieJarDB>(parameters.cookiePersistentStorageFile)); 45 networkStorageSession()->setProxySettings(WTFMove(parameters.proxySettings)); 46 46 } 47 47 -
trunk/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp
r241317 r246569 69 69 70 70 if (m_user.isEmpty() && m_password.isEmpty()) 71 m_initialCredential = m_session->networkStorageSession() .credentialStorage().get(m_partition, request.url());71 m_initialCredential = m_session->networkStorageSession()->credentialStorage().get(m_partition, request.url()); 72 72 else 73 m_session->networkStorageSession() .credentialStorage().set(m_partition, Credential(m_user, m_password, CredentialPersistenceNone), request.url());73 m_session->networkStorageSession()->credentialStorage().set(m_partition, Credential(m_user, m_password, CredentialPersistenceNone), request.url()); 74 74 } 75 75 applyAuthenticationToRequest(request); … … 471 471 // here, since a different credential might have already been stored by another 472 472 // NetworkDataTask, but the observable effect should be very minor, if any. 473 m_session->networkStorageSession() .credentialStorage().remove(m_partition, challenge.protectionSpace());473 m_session->networkStorageSession()->credentialStorage().remove(m_partition, challenge.protectionSpace()); 474 474 } 475 475 476 476 if (!challenge.previousFailureCount()) { 477 auto credential = m_session->networkStorageSession() .credentialStorage().get(m_partition, challenge.protectionSpace());477 auto credential = m_session->networkStorageSession()->credentialStorage().get(m_partition, challenge.protectionSpace()); 478 478 if (!credential.isEmpty() && credential != m_initialCredential) { 479 479 ASSERT(credential.persistence() == CredentialPersistenceNone); … … 481 481 if (isAuthenticationFailureStatusCode(challenge.failureResponse().httpStatusCode())) { 482 482 // Store the credential back, possibly adding it as a default for this directory. 483 m_session->networkStorageSession() .credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url());483 m_session->networkStorageSession()->credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url()); 484 484 } 485 485 soup_auth_authenticate(challenge.soupAuth(), credential.user().utf8().data(), credential.password().utf8().data()); … … 497 497 if (m_storedCredentialsPolicy == StoredCredentialsPolicy::Use) { 498 498 auto protectionSpace = challenge.protectionSpace(); 499 m_session->networkStorageSession() .getCredentialFromPersistentStorage(protectionSpace, m_cancellable.get(),499 m_session->networkStorageSession()->getCredentialFromPersistentStorage(protectionSpace, m_cancellable.get(), 500 500 [this, protectedThis = makeRef(*this), authChallenge = WTFMove(challenge)] (Credential&& credential) mutable { 501 501 if (m_state == State::Canceling || m_state == State::Completed || !m_client) { … … 532 532 // this protection space. 533 533 if (credential.persistence() == CredentialPersistenceForSession || credential.persistence() == CredentialPersistencePermanent) 534 m_session->networkStorageSession() .credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url());534 m_session->networkStorageSession()->credentialStorage().set(m_partition, credential, challenge.protectionSpace(), challenge.failureResponse().url()); 535 535 536 536 if (credential.persistence() == CredentialPersistencePermanent) { … … 664 664 } else if (url.protocolIsInHTTPFamily() && m_storedCredentialsPolicy == StoredCredentialsPolicy::Use) { 665 665 if (m_user.isEmpty() && m_password.isEmpty()) { 666 auto credential = m_session->networkStorageSession() .credentialStorage().get(m_partition, request.url());666 auto credential = m_session->networkStorageSession()->credentialStorage().get(m_partition, request.url()); 667 667 if (!credential.isEmpty()) 668 668 m_initialCredential = credential; … … 831 831 // incorrect credentials or polluting the keychain with invalid credentials. 832 832 if (!isAuthenticationFailureStatusCode(m_soupMessage->status_code) && m_soupMessage->status_code < 500) { 833 m_session->networkStorageSession() .saveCredentialToPersistentStorage(m_protectionSpaceForPersistentStorage, m_credentialForPersistentStorage);833 m_session->networkStorageSession()->saveCredentialToPersistentStorage(m_protectionSpaceForPersistentStorage, m_credentialForPersistentStorage); 834 834 m_protectionSpaceForPersistentStorage = ProtectionSpace(); 835 835 m_credentialForPersistentStorage = Credential(); -
trunk/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp
r245540 r246569 40 40 : NetworkSession(networkProcess, parameters.sessionID, parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle) 41 41 { 42 networkStorageSession() .setCookieObserverHandler([this] {42 networkStorageSession()->setCookieObserverHandler([this] { 43 43 this->networkProcess().supplement<WebCookieManager>()->notifyCookiesDidChange(m_sessionID); 44 44 }); … … 56 56 SoupSession* NetworkSessionSoup::soupSession() const 57 57 { 58 return networkStorageSession() .soupNetworkSession().soupSession();58 return networkStorageSession()->soupNetworkSession().soupSession(); 59 59 } 60 60
Note: See TracChangeset
for help on using the changeset viewer.