国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

干貨:深入理解 WKWebView -- 探究 WebKit 緩存

共 20120字,需瀏覽 41分鐘

 ·

2022-01-08 18:20

1. 前言

緩存可以減少冗余的數(shù)據(jù)傳輸,解決網(wǎng)絡(luò)瓶頸問(wèn)題,降低服務(wù)端壓力,提升頁(yè)面加載速度。高效利用緩存可大幅提升頁(yè)面加載速度,提升用戶的瀏覽體驗(yàn)。WKWebView 使用緩存技術(shù)存儲(chǔ)前后端資源,用戶提高頁(yè)面性能和用戶體驗(yàn)。因?yàn)?WKWebView 的封閉性,我們無(wú)法針對(duì)原生 WKWebView 做較深度化的定制,但對(duì)于 WebKit 緩存源碼的探究,將幫助我們更好的使用和理解緩存。本文將延續(xù) 《iOS 端 webkit 源碼調(diào)試與分析》的思路,結(jié)合源碼枚舉 WKWebView 中的各類緩存,并重點(diǎn)講述其中的 HTTP 協(xié)議緩存,幫助讀者更好的理解 WebKit 中緩存的設(shè)計(jì)思路。


2. 緩存簡(jiǎn)介


2.1 緩存類型


2.1.1 WebKit 標(biāo)準(zhǔn)緩存類型

// HTTP 磁盤緩存。WKWebsiteDataTypeDiskCache,
// html離線Web應(yīng)用程序緩存。WKWebsiteDataTypeOfflineWebApplicationCache,
// HTTP 內(nèi)存緩存。WKWebsiteDataTypeMemoryCache,
//?會(huì)話存儲(chǔ):存儲(chǔ)對(duì)數(shù)據(jù)只有在同一個(gè)會(huì)話中的頁(yè)面才能訪問(wèn)并且當(dāng)會(huì)話結(jié)束后數(shù)據(jù)也隨之銷毀。//?因此sessionStorage不是一種持久化的本地存儲(chǔ),僅僅是會(huì)話級(jí)別的存儲(chǔ)WKWebsiteDataTypeSessionStorage,
//?本地存儲(chǔ):localStorage 類似 sessionStorage,但其區(qū)別在于,存儲(chǔ)在 localStorage 的數(shù)據(jù)可以長(zhǎng)期保留.WKWebsiteDataTypeLocalStorage,
// Cookies存儲(chǔ):存儲(chǔ)所有的cookie數(shù)據(jù) WKWebsiteDataTypeCookies,
// IndexedDB數(shù)據(jù)庫(kù):IndexedDB是WebSQL數(shù)據(jù)庫(kù)的取代品。IndexedDB是key-value型數(shù)據(jù)庫(kù),操作簡(jiǎn)單。WKWebsiteDataTypeIndexedDBDatabases,
// webSQL數(shù)據(jù)庫(kù):W3C組織在2010年11月18日廢棄了webSql 數(shù)據(jù)庫(kù),該數(shù)據(jù)庫(kù)接口操組復(fù)雜,對(duì)用戶不友好。WKWebsiteDataTypeWebSQLDatabases

通過(guò)數(shù)據(jù)分析,主要是 indexedDB 與 NetworkCache 占據(jù)較大比例,可達(dá)80%以上。WebKit 磁盤緩存分布如下表:

磁盤文件目錄
緩存類型
Library/WebKit

IndexedDB?

LocalStorage

MediaKeys

ResourceLoadStatistics

Library/Caches/WebKit

CacheStorage

NetworkCache

offlineWebApplicationCache

ServiceWorkers


2.1.2 前進(jìn)后退緩存 –?pageCache

在 WebKit 中,pageCache 其實(shí)就是對(duì) WebBackForwardCache –?前進(jìn)后退緩存的封裝,本質(zhì)上是瀏覽歷史的一種記錄,不屬于上述標(biāo)準(zhǔn)緩存。前進(jìn)后退緩存,將整個(gè)頁(yè)面快照存入到內(nèi)存中,下一次使用的時(shí)候,不用進(jìn)行各類資源加載,甚至不用進(jìn)行渲染工作。

通過(guò)源碼查看,pageCache 大小會(huì)隨著可使用內(nèi)存大小動(dòng)態(tài)變化:

手機(jī)可用內(nèi)存a
可緩存page頁(yè)數(shù)
a?>= 512M2
512M >?a >= 256M1
other0

緩存策略源碼如下所示:

//?back/forward cache capacity (in pages)if (memorySize >= 512)    backForwardCacheCapacity = 2;else if (memorySize >= 256)    backForwardCacheCapacity = 1;else    backForwardCacheCapacity = 0;

資源的過(guò)期時(shí)間默認(rèn)為30分鐘。通過(guò)定時(shí)器觸發(fā)任務(wù),30分鐘后自動(dòng)清理過(guò)期的 page。源碼如下:

static const Seconds expirationDelay { 30_min }; //通過(guò)定時(shí)器觸發(fā),到過(guò)期時(shí)間后,進(jìn)行資源清理 void WebBackForwardCacheEntry::expirationTimerFired() {    RELEASE_LOG(BackForwardCache, "%p - WebBackForwardCacheEntry::expirationTimerFired backForwardItemID=%s, hasSuspendedPage=%d", this, m_backForwardItemID.string().utf8().data(), !!m_suspendedPage);    ASSERT(m_backForwardItemID);    auto* item = WebBackForwardListItem::itemForID(m_backForwardItemID);????ASSERT(item);????m_backForwardCache.removeEntry(*item);?//?Will?destroy?|this|.}


因 pageCache 存儲(chǔ)頁(yè)面數(shù)量有限,因此當(dāng)超出頁(yè)面緩存上限時(shí),需要通過(guò)如下 LRU 算法進(jìn)行替換:

void BackForwardCache::prune(PruningReason pruningReason) {    while (pageCount() > maxSize()) {         auto oldestItem = m_items.takeFirst();         oldestItem->setCachedPage(nullptr);         oldestItem->m_pruningReason = pruningReason; ????????RELEASE_LOG(BackForwardCache,?"BackForwardCache::prune?removing?item:?%s,?size:?%u?/?%u",?oldestItem->identifier().string().utf8().data(),?pageCount(),?maxSize());    }}


緩存時(shí)機(jī)源碼如下:

bool?WebPageProxy::suspendCurrentPageIfPossible(...)?{    ...    // If the source and the destination back / forward list items are the same, then this is a client-side redirect. In this case,     // there is no need to suspend the previous page as there will be no way to get back to it.     if (fromItem && fromItem == m_backForwardList->currentItem()) {         RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because this is a client-side redirect", m_process->processIdentifier()); ????????return?false;    }    ...    //創(chuàng)建 SuspendedPageProxy 變量,此時(shí) m_suspendedPageCount 的值會(huì)加一     auto suspendedPage = makeUnique(*this, m_process.copyRef(), *mainFrameID, shouldDelayClosingUntilFirstLayerFlush);     m_lastSuspendedPage = makeWeakPtr(*suspendedPage);     ...    //添加進(jìn)歷史棧緩存     backForwardCache().addEntry(*fromItem, WTFMove(suspendedPage));     ...}

可以看到,如果 WKWebView 切換頁(yè)面時(shí),發(fā)生 cross-site 且為 client-side redirect 時(shí)會(huì)清理當(dāng)前 WebProgressProxy 關(guān)聯(lián)的所有歷史棧緩存,后續(xù)切換到這些歷史棧時(shí)都需要重新請(qǐng)求網(wǎng)絡(luò)。而其他類型都會(huì)正常存儲(chǔ),因此可以基于前進(jìn)后退相關(guān)操作的頁(yè)面性能考慮,可以減少前端重定向,多依賴后端進(jìn)行重定向功能。

2.2 緩存清理方式

處于內(nèi)存中的緩存,會(huì)隨著進(jìn)程的結(jié)束而消亡。而處于磁盤中的緩存,則可以通過(guò)如下方法進(jìn)行手動(dòng)清理,避免磁盤占用增長(zhǎng)過(guò)大。

2.2.1 文件目錄清理方式

webkit磁盤中的較多數(shù)據(jù)都是通過(guò)域名做為文件名的一部分,因此也可以通過(guò)域名、日期等方式匹配,進(jìn)行文件刪除:

 NSString *libraryDir = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask, YES)[0]; NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; NSString *webkitFolderInLib = [NSString stringWithFormat:@"%@/WebKit",libraryDir]; NSString *webKitFolderInCaches = [NSString stringWithFormat:@"%@/Caches/%@/WebKit",libraryDir,bundleId]; NSError *error; [[NSFileManager defaultManager] removeItemAtPath:webKitFolderInCaches error:&error]; [[NSFileManager defaultManager] removeItemAtPath:webkitFolderInLib error:nil];

localStorage 存儲(chǔ)文件樣例

2.2.2 緩存類型清理方式

iOS 9.0以后 , WebKit 清除緩存的API,測(cè)試來(lái)看必須在主線程進(jìn)行操作。

NSSet *websiteDataTypes = [NSSet setWithArray:@[ WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeOfflineWebApplicationCache, WKWebsiteDataTypeLocalStorage, WKWebsiteDataTypeCookies, WKWebsiteDataTypeSessionStorage, WKWebsiteDataTypeIndexedDBDatabases, WKWebsiteDataTypeWebSQLDatabases ]];NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0]; //dataTypes: 指定刪除的網(wǎng)站數(shù)據(jù)類型,date: 在此日期之后修改的所有網(wǎng)站數(shù)據(jù)將被刪除,completionHandler: 當(dāng)網(wǎng)站數(shù)據(jù)被刪除時(shí)調(diào)用的block。[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{ // 結(jié)束回調(diào) }];


3. HTTP 內(nèi)存緩存


WKWebView 與 app 處于不同進(jìn)程中,且內(nèi)存與磁盤緩存也在不同進(jìn)程中,其中,內(nèi)存緩存位于 WebContentProcess 進(jìn)程中,而磁盤緩存位于 NetworkProcess 進(jìn)程中。且每個(gè)memoryCache 對(duì)應(yīng)一個(gè) webContent 進(jìn)程,如圖所示。





如上圖所示,一個(gè)頁(yè)面對(duì)應(yīng)一個(gè)WebContentProcess 進(jìn)程,當(dāng)頁(yè)面銷毀時(shí),其對(duì)應(yīng)的內(nèi)存緩存也被銷毀。

3.1 內(nèi)存緩存大小

雖然 WebKit 進(jìn)程獨(dú)立與 app 進(jìn)程,但內(nèi)存占用過(guò)大依舊會(huì)影響到 app 進(jìn)程的性能,因此內(nèi)存緩存根據(jù)手機(jī)當(dāng)前緩存大小進(jìn)行分配。

手機(jī)可用內(nèi)存a
頁(yè)面內(nèi)存分配
a >= 2G128M
2G > a >= 1.5G96M
1.5G > a >= 1G64M
1G > a >= 0.5G32M
other16M

緩存大小計(jì)算策略源碼如下:

case CacheModel::PrimaryWebBrowser: {     // back/forward cache capacity (in pages)     if (memorySize >= 512)         backForwardCacheCapacity = 2;     else if (memorySize >= 256)         backForwardCacheCapacity = 1;     else         backForwardCacheCapacity = 0;     // Object cache capacities (in bytes)     // (Testing indicates that value / MB depends heavily on content and     // browsing pattern. Even growth above 128MB can have substantial     // value / MB for some content / browsing patterns.)     if (memorySize >= 2048)         cacheTotalCapacity = 128 * MB;     else if (memorySize >= 1536)         cacheTotalCapacity = 96 * MB;     else if (memorySize >= 1024)         cacheTotalCapacity = 64 * MB;     else if (memorySize >= 512)         cacheTotalCapacity = 32 * MB;     else         cacheTotalCapacity = 16 * MB;     cacheMinDeadCapacity = cacheTotalCapacity / 4;     cacheMaxDeadCapacity = cacheTotalCapacity / 2;     // This code is here to avoid a PLT regression. We can remove it if we     // can prove that the overall system gain would justify the regression.     cacheMaxDeadCapacity = std::max(24u, cacheMaxDeadCapacity);     deadDecodedDataDeletionInterval = 60_s;     break; }


3.2?內(nèi)存緩存策略

使用 map 字典,在內(nèi)存中使用 url 為 key,resource 資源為 value,對(duì)當(dāng)前頁(yè)面的所有 HTTP 網(wǎng)絡(luò)請(qǐng)求資源進(jìn)行存儲(chǔ)。

3.2.1 內(nèi)存緩存添加

bool?MemoryCache::add(CachedResource&?resource) {    if (disabled())         return false;     if (resource.resourceRequest().httpMethod() != "GET")         return false;     ASSERT(WTF::isMainThread());     auto key = std::make_pair(resource.url(), resource.cachePartition());     ensureSessionResourceMap(resource.sessionID()).set(key, &resource);     resource.setInCache(true);     resourceAccessed(resource);     LOG(ResourceLoading, "MemoryCache::add Added '%.255s', resource %p\n", resource.url().string().latin1().data(), &resource);     return true; }

3.2.2 內(nèi)存緩存讀取

CachedResource* MemoryCache::resourceForRequest(const ResourceRequest& request, PAL::SessionID sessionID) {    // FIXME: Change all clients to make sure HTTP(s) URLs have no fragment identifiers before calling here.     // CachedResourceLoader is now doing this. Add an assertion once all other clients are doing it too.     auto* resources = sessionResourceMap(sessionID);     if (!resources)         return nullptr;     return resourceForRequestImpl(request, *resources); }
CachedResource* MemoryCache::resourceForRequestImpl(const ResourceRequest& request, CachedResourceMap& resources) { ASSERT(WTF::isMainThread()); URL url = removeFragmentIdentifierIfNeeded(request.url()); auto key = std::make_pair(url, request.cachePartition()); return resources.get(key); }

3.2.3 HTTP 內(nèi)存緩存讀取策略

HTTP 內(nèi)存緩存讀取時(shí)機(jī)不同于磁盤緩存,它并不完全遵守 HTTP 標(biāo)準(zhǔn)協(xié)議,而是根據(jù)瀏覽器所加載的資源策略來(lái)進(jìn)行的。例如:

  1. 前進(jìn)后退歷史中的頁(yè)面的資源請(qǐng)求,可以直接讀取內(nèi)存緩存。

  2. 圖片資源使用同一 url 加載的時(shí)候,后續(xù)的資源會(huì) block 住,等待首個(gè)圖片資源的返回,直接使用緩存。

  3. preload 資源可直接讀取緩存,不必進(jìn)行任何判斷。

// 網(wǎng)絡(luò)請(qǐng)求加載是否使用內(nèi)存緩存有如下策略:enum RevalidationPolicy { Use, // 直接使用Revalidate, // 需要經(jīng)過(guò) HTTP 緩存協(xié)議校驗(yàn)Reload, // 重新加載,清理內(nèi)存緩存,并重新請(qǐng)求Load // 直接從網(wǎng)絡(luò)加載};
RevalidationPolicy policy = determineRevalidationPolicy(type, request, resource.get(), forPreload, imageLoading);


4. HTTP 磁盤緩存


磁盤緩存的設(shè)計(jì)完全遵循 HTTP 標(biāo)準(zhǔn)緩存協(xié)議。所有的網(wǎng)絡(luò)請(qǐng)求都經(jīng)過(guò) NetWorkProcess 進(jìn)程發(fā)出,請(qǐng)求在發(fā)出之前,則會(huì)經(jīng)過(guò)緩存協(xié)議檢驗(yàn),根據(jù) HTTP 協(xié)議進(jìn)行相應(yīng)操作(讀取緩存/協(xié)商檢驗(yàn)/不使用緩存等)。當(dāng)服務(wù)端返回請(qǐng)求內(nèi)容后,NetworkProcess 模塊也會(huì)做出對(duì)應(yīng)的判斷,決定內(nèi)容是否進(jìn)行緩存或更新,如下所示。

4.1 HTTP?緩存處理流程圖




4.2?HTTP?磁盤緩存大小

磁盤緩存存入到指定的文件目錄中,其中默認(rèn)為:Library/Caches/WebKit/NetworkCache??梢酝ㄟ^(guò)如下方法進(jìn)行指定:

case?CacheModel::PrimaryWebBrowser:?{ 
// Disk cache capacity (in bytes) if (diskFreeSize >= 16384) urlCacheDiskCapacity = 1 * GB; else if (diskFreeSize >= 8192) urlCacheDiskCapacity = 500 * MB; else if (diskFreeSize >= 4096) urlCacheDiskCapacity = 250 * MB; else if (diskFreeSize >= 2048) urlCacheDiskCapacity = 200 * MB; else if (diskFreeSize >= 1024) urlCacheDiskCapacity = 150 * MB; else urlCacheDiskCapacity = 100 * MB;
break; } default: ASSERT_NOT_REACHED(); };


4.3?HTTP?存入緩存校驗(yàn)

本部分主要根據(jù)請(qǐng)求和響應(yīng)來(lái)判斷是否需要存儲(chǔ)到緩存中。主要判斷 scheme、method 以及資源的緩存策略。

// WebKit/Source/WebKit/NetworkProcess/cache/NetworkCache.cppstatic StoreDecision makeStoreDecision(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response, size_t bodySize){    if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isInHTTPFamily())        return StoreDecision::NoDueToProtocol;

if (originalRequest.httpMethod() != "GET") return StoreDecision::NoDueToHTTPMethod;

auto requestDirectives = WebCore::parseCacheControlDirectives(originalRequest.httpHeaderFields()); if (requestDirectives.noStore) return StoreDecision::NoDueToNoStoreRequest;

if (response.cacheControlContainsNoStore()) return StoreDecision::NoDueToNoStoreResponse;

if (!WebCore::isStatusCodeCacheableByDefault(response.httpStatusCode())) { // http://tools.ietf.org/html/rfc7234#section-4.3.2 bool hasExpirationHeaders = response.expires() || response.cacheControlMaxAge(); bool expirationHeadersAllowCaching = WebCore::isStatusCodePotentiallyCacheable(response.httpStatusCode()) && hasExpirationHeaders; if (!expirationHeadersAllowCaching) return StoreDecision::NoDueToHTTPStatusCode; }

bool isMainResource = originalRequest.requester() == WebCore::ResourceRequest::Requester::Main; bool storeUnconditionallyForHistoryNavigation = isMainResource || originalRequest.priority() == WebCore::ResourceLoadPriority::VeryHigh; if (!storeUnconditionallyForHistoryNavigation) { auto now = WallTime::now(); Seconds allowedStale { 0_ms };#if ENABLE(NETWORK_CACHE_STALE_WHILE_REVALIDATE) if (auto value = response.cacheControlStaleWhileRevalidate()) allowedStale = value.value();#endif bool hasNonZeroLifetime = !response.cacheControlContainsNoCache() && (WebCore::computeFreshnessLifetimeForHTTPFamily(response, now) > 0_ms || allowedStale > 0_ms); bool possiblyReusable = response.hasCacheValidatorFields() || hasNonZeroLifetime; if (!possiblyReusable) return StoreDecision::NoDueToUnlikelyToReuse; }

// Media loaded via XHR is likely being used for MSE streaming (YouTube and Netflix for example). // Streaming media fills the cache quickly and is unlikely to be reused. // FIXME: We should introduce a separate media cache partition that doesn't affect other resources. // FIXME: We should also make sure make the MSE paths are copy-free so we can use mapped buffers from disk effectively. auto requester = originalRequest.requester(); bool isDefinitelyStreamingMedia = requester == WebCore::ResourceRequest::Requester::Media; bool isLikelyStreamingMedia = requester == WebCore::ResourceRequest::Requester::XHR && isMediaMIMEType(response.mimeType()); if (isLikelyStreamingMedia || isDefinitelyStreamingMedia) return StoreDecision::NoDueToStreamingMedia;

return StoreDecision::Yes;}


4.4?HTTP?讀取緩存校驗(yàn)

本部分主要根據(jù)請(qǐng)求來(lái)判斷是否去緩存中讀取緩存。主要判斷 scheme、method 以及資源的緩存策略。

// WebKit/Source/WebKit/NetworkProcess/cache/NetworkCache.cpp static RetrieveDecision makeRetrieveDecision(const WebCore::ResourceRequest& request) {    ASSERT(request.cachePolicy() != WebCore::ResourceRequestCachePolicy::DoNotUseAnyCache); 

// FIXME: Support HEAD requests. if (request.httpMethod() != "GET") return RetrieveDecision::NoDueToHTTPMethod; if (request.cachePolicy() == WebCore::ResourceRequestCachePolicy::ReloadIgnoringCacheData && !request.isConditional()) return RetrieveDecision::NoDueToReloadIgnoringCache;

return RetrieveDecision::Yes; }


4.5?HTTP?使用緩存校驗(yàn)

本部分主要根據(jù)請(qǐng)求和響應(yīng)來(lái)判斷緩存是否可以直接使用。主要根據(jù)緩存字段計(jì)算當(dāng)前的資源是否過(guò)期。

// WebKit/Source/WebKit/NetworkProcess/cache/NetworkCache.cpp static UseDecision makeUseDecision(NetworkProcess& networkProcess, const PAL::SessionID& sessionID, const Entry& entry, const WebCore::ResourceRequest& request) {    // The request is conditional so we force revalidation from the network. We merely check the disk cache     // so we can update the cache entry.     // 條件請(qǐng)求判斷 | bool ResourceRequestBase::isConditional     if (request.isConditional() && !entry.redirectRequest())         return UseDecision::Validate; 

// 校驗(yàn)變化的請(qǐng)求頭 | verifyVaryingRequestHeaders if (!WebCore::verifyVaryingRequestHeaders(networkProcess.storageSession(sessionID), entry.varyingRequestHeaders(), request)) return UseDecision::NoDueToVaryingHeaderMismatch;

// We never revalidate in the case of a history navigation. // 校驗(yàn)緩存是否過(guò)期 | cachePolicyAllowsExpired if (cachePolicyAllowsExpired(request.cachePolicy())) ????????return?UseDecision::Use;

// 驗(yàn)證請(qǐng)求是否過(guò)期 auto decision = responseNeedsRevalidation(*networkProcess.networkSession(sessionID), entry.response(), request, entry.timeStamp()); if (decision != UseDecision::Validate) return decision;

// 驗(yàn)證緩存有效字端(Etag等) | bool ResourceResponseBase::hasCacheValidatorFields() if (!entry.response().hasCacheValidatorFields()) return UseDecision::NoDueToMissingValidatorFields;

return entry.redirectRequest() ? UseDecision::NoDueToExpiredRedirect : UseDecision::Validate; }

4.5.1?HTTP 緩存新鮮度計(jì)算

本部分主要根據(jù)緩存字段計(jì)算當(dāng)前的資源的新鮮度。

// WebKit/Source/WebCore/platform/network/CacheValidation.cpp Seconds computeFreshnessLifetimeForHTTPFamily(const ResourceResponse& response, WallTime responseTime) {    if (!response.url().protocolIsInHTTPFamily())        return 0_us; 

// Freshness Lifetime: // http://tools.ietf.org/html/rfc7234#section-4.2.1 ????auto?maxAge?=?response.cacheControlMaxAge(); if (maxAge) return *maxAge;

auto date = response.date(); auto effectiveDate = date.valueOr(responseTime); if (auto expires = response.expires()) return *expires - effectiveDate;

// Implicit lifetime. switch (response.httpStatusCode()) { case 301: // Moved Permanently case 410: // Gone // These are semantically permanent and so get long implicit lifetime. return 24_h * 365; default: // Heuristic Freshness: // http://tools.ietf.org/html/rfc7234#section-4.2.2 if (auto lastModified = response.lastModified()) return (effectiveDate - *lastModified) * 0.1; return 0_us; }}

4.5.2??HTTP 緩存新鮮度計(jì)算

本部分主要根據(jù)緩存字段計(jì)算當(dāng)前的資源是否過(guò)期。

// WebKit/Source/WebKit/NetworkProcess/cache/NetworkCache.cpp static UseDecision responseNeedsRevalidation(NetworkSession& networkSession, const WebCore::ResourceResponse& response, WallTime timestamp, Optional maxStale) {    if (response.cacheControlContainsNoCache())         return UseDecision::Validate; 

// 當(dāng)前過(guò)去的時(shí)間 = 當(dāng)前時(shí)間 - 資源時(shí)間 | computeCurrentAge auto age = WebCore::computeCurrentAge(response, timestamp); // 調(diào)用資源有效時(shí)間計(jì)算 | computeFreshnessLifetimeForHTTPFamily auto lifetime = WebCore::computeFreshnessLifetimeForHTTPFamily(response, timestamp);

// 資源允許過(guò)期時(shí)間 auto maximumStaleness = maxStale ? maxStale.value() : 0_ms; // qy6_detail 資源是否超期 | 當(dāng)前過(guò)去的時(shí)間 - 資源有效時(shí)間 - 允許過(guò)期時(shí)間 > 0 => 資源過(guò)期了 bool hasExpired = age - lifetime > maximumStaleness; #if ENABLE(NETWORK_CACHE_STALE_WHILE_REVALIDATE) if (hasExpired && !maxStale && networkSession.isStaleWhileRevalidateEnabled()) { auto responseMaxStaleness = response.cacheControlStaleWhileRevalidate(); maximumStaleness += responseMaxStaleness ? responseMaxStaleness.value() : 0_ms; bool inResponseStaleness = age - lifetime < maximumStaleness; if (inResponseStaleness) return UseDecision::AsyncRevalidate; }#endif

if (hasExpired) { #ifndef LOG_DISABLED LOG(NetworkCache, "(NetworkProcess) needsRevalidation hasExpired age=%f lifetime=%f max-staleness=%f", age, lifetime, maximumStaleness); #endif return UseDecision::Validate; }

return UseDecision::Use; }

4.6?HTTP?服務(wù)器資源校驗(yàn)

過(guò)期資源需要從服務(wù)器判斷是否可用,需要構(gòu)造一個(gè)條件請(qǐng)求去服務(wù)端驗(yàn)證當(dāng)前過(guò)期資源是否可用。

// WebKit/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp void NetworkResourceLoader::validateCacheEntry(std::unique_ptr entry) {    RELEASE_LOG_IF_ALLOWED("validateCacheEntry:");     ASSERT(!m_networkLoad); 

// If the request is already conditional then the revalidation was not triggered by the disk cache // and we should not overwrite the existing conditional headers. // 如果請(qǐng)求為條件請(qǐng)求,不修改 HEADER 中條件請(qǐng)求屬性 ResourceRequest revalidationRequest = originalRequest(); if (!revalidationRequest.isConditional()) { String eTag = entry->response().httpHeaderField(HTTPHeaderName::ETag); String lastModified = entry->response().httpHeaderField(HTTPHeaderName::LastModified); // qy6_detail 新增緩存校驗(yàn)請(qǐng)求頭,IfNoneMatch 和 IfModifiedSince if (!eTag.isEmpty()) revalidationRequest.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag); if (!lastModified.isEmpty()) revalidationRequest.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified); }

m_cacheEntryForValidation = WTFMove(entry);

// qy6_detail 發(fā)起請(qǐng)求 startNetworkLoad(WTFMove(revalidationRequest), FirstLoad::Yes); }


4.7?HTTP?緩存資源更新?

當(dāng)服務(wù)器驗(yàn)證通過(guò)后,需要對(duì)現(xiàn)有的緩存資源進(jìn)行更新,緩存資源更新后返回給客戶端。

// WebKit/Source/WebCore/platform/network/CacheValidation.cpp void updateResponseHeadersAfterRevalidation(ResourceResponse& response, const ResourceResponse& validatingResponse) {    // Freshening stored response upon validation:     // http://tools.ietf.org/html/rfc7234#section-4.3.4     for (const auto& header : validatingResponse.httpHeaderFields()) {         // Entity headers should not be sent by servers when generating a 304         // response; misconfigured servers send them anyway. We shouldn't allow         // such headers to update the original request. We'll base this on the         // list defined by RFC2616 7.1, with a few additions for extension headers         // we care about.         // 是否應(yīng)該更新請(qǐng)求頭         if (!shouldUpdateHeaderAfterRevalidation(header.key))             continue;         response.setHTTPHeaderField(header.key, header.value);     }}



參考資料


1. 《HTTP 權(quán)威指南》

2. "HTTP 緩存 - HTTP | MDN"?

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching_FAQ

3. "Cache-Control - HTTP | MDN"?

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control

4.? "Message Syntax and Routing"?

https://tools.ietf.org/html/rfc7230

5.? "Semantics and Content"?

https://tools.ietf.org/html/rfc7231

6.? "Conditional Requests"?

https://tools.ietf.org/html/rfc7232

7.? "Range Requests"

https://tools.ietf.org/html/rfc7233

8.? "Caching"?

https://tools.ietf.org/html/rfc7234

9.? "Authentication"?

https://tools.ietf.org/html/rfc7235

瀏覽 111
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評(píng)論
圖片
表情
推薦
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 日批视频| 大香蕉在线伊人| 91精品国产三级| 男女啪啪免费| 亚洲欧美高清视频| 欧美性区| 中出在线| 吴梦梦《女教师时间暂停》| 亚洲综合片| 97无码精品人妻一区二区三区| 人人妻人人操人人| 做爱激情视频网站| 国产18禁网站| 日韩a级片| 日韩AV在线免费观看| 伊人黄色网| 丁香激情五月少妇| 欧美一级片在线| 四川少妇BBB凸凸凸BBB安慰我 | 久草不卡| 搡BBBB搡BBB搡我瞎了| 成人国产片女人爽到高潮| 国产香蕉视频在线播放| 学生妹一级片| 99久久99久国产黄毛片| 国产熟女在线| 高清无码操逼| 国产毛片一照区| 亚洲AV无码乱码国产精品黑人| www.狠狠干| 欧美成人A片| 激情视频小说| 亚洲高清无码在线播放| 大鸡吧成人视频| 免费无码婬片AAAA片在线蜜芽| 精品乱子伦一区二区三区免费播放 | 乱伦五月天| 成年人免费公开视频| 蜜桃av无码一区二区三区| 日韩精品成人| 国产精品国产三级囯产普通话2 | 97国产成人| 国产特级毛片| 激情五月丁香花| 十八禁黄网站| 伊人色女操穴综合网| 中文无码不卡| 无码人妻丰满熟妇区毛片视频| 日韩中文字幕成人| 亚洲天堂无码高清| 日韩字幕久久| 四川BBB搡BBB爽爽爽电影| 日韩高清无码中文字幕| 国产主播一区二区| 午夜性爱剧场| 国产亚洲99久久精品| 操逼电影网站| 国产精品视频| 激情婷婷网| www.麻豆网91成人久久久| 欧美一级高清片免费一级a| 欧美日韩第一页| 中文字幕视频一区| 午夜伦理福利| 久久久噜噜噜久久中文字幕色伊伊 | 天天操夜夜操狠狠操| 亚洲日韩欧美一区二区天天天| 天堂亚洲AV无码精品成人| 无码在线免费观看视频| 国产超级无码高清在线视频观看| 亚洲成人AV在线观看| 国产精品外围| 成人高清无码视频| 久久免费看视频| 国产精品秘久久久久久1-~/\v7-/ 囯产精品一区二区三区线一牛影视1 | 丰满人妻-区二区三区| 久久男人天堂| 国产字幕在线观看| 岛国AV免费看| 国产精品免费久久| 不卡AV在线| AV成人无码| 激情网五月天| 91原创国产内射| 乱婬妺妺躁爽A片| 蜜臀久久精品久久久久| 婷婷综合视频| 大香蕉午夜视频| 大香蕉久久久| av资源在线看| 亚洲va在线∨a天堂va欧美va | 香蕉成人网站| 在线免费看黄色| 四虎操逼| 91大神在线免费看| 亚洲美女免费视频| 影音先锋女人资源| 亚洲AV男人天堂| 99免费热视频| 午夜天堂精品久久久久| 麻豆精品传媒2021md| 国产中文| 亚州高清无码视频| 91精品国产人妻| 北条麻妃无码精品AV| 午夜资源站| 中文天堂| 77777精品成人免费A片| 免费视频一区二区| 黄片无码免费观看| 一级a爱视频| 先锋影音AV资源网| 国产三级一区二区| 法国《少女日记》电影| 91精品电影| AAA一区二区三区| 亚洲免费高清视频| 五月停亭六月,六月停亭的英语| 人妻精品一卡二卡| 欧美性爱五月天| 亚洲高清毛片一区二区| 国产AV天堂| 日本欧美在线视频| 蜜桃av无码| 国产成人精品无码免费| 九九韩剧网最新电视剧免费观看| 欧美性爱操逼视频| 亚洲视频免费完整版在线播放| 欧美成a| 91国产做爱| 最新中文字幕免费MV第一季歌词| 国产农村乱婬片A片AAA图片| 免费AV在线| 无码人妻精品一区二区三区蜜桃91 | 久久亚洲AV成人无码国产野外| 97精品人妻| 国产美女啪啪视频| 免费看黄色的网站| 国产精品不卡| www.99视频| 亚洲第一成人久久网站| 午夜无码鲁丝午夜免费| 青青草亚洲| 亚洲男女网站| 日韩操逼图| 狠狠操狠狠撸| 日韩在线你懂的| 日韩高清无码免费看| 国产视频无码| 偷拍精品视频| 欧美色图1| 亚洲高清无码免费| 成人一级黄片| 中文字幕AV第一页| 久月婷婷| 亚洲成人一区二区| 国产欧美成人| 91操b| 欧美爱爱试看| 欧美中文字幕在线| 免费操B视频| 亚洲午夜久久久久久久久| 久久青草影院| 婷婷激情综合| 免费黄色成人视频| 亚洲色图片区| 无码国产99精品久久久久网站| 成人片成人网久久蜜桃臀| 操老女人的逼| 亚洲免费观看高清完整版在线观 | 91干穴穴在线观看| 91九九九| 欧美亚洲日韩成人| 大伊香蕉视频| 亚洲中文无码在线观看| 亚洲AV无码成人精品区天堂小说 | 亚洲人成免费| 国产精品国产精品国产专区不52 | 日韩欧美综合| 香蕉久久a毛片| 狠狠色婷婷777| 欧美午夜性爱视频| 无码视频免费播放| 伊人网站| 伊人久久大| 亚洲日本高清| 国产麻豆精品成人免费视频| 老女人肏屄视频| 国产人妻人伦精品一区| 爱爱中文字幕| 亚洲视屏| 高清国产mv在线观看| 京熱大亂交无碼大亂交| 国产成人免费观看视频| 免费人成年激情视频在线观看 | 国产欧美一级片| 欧美午夜福利| 亚洲精品在线视频| 人人肏人人摸| 五月婷婷六月色| 国产精品美女毛片j酒店| 免费无码国产在线| 狠狠色噜噜狠狠狠7777米奇网| 色多多毛片| 黄色片一级| 欧美成人黄色小说| 无码人妻一区二区三区免水牛视频| 日一区二区| 亚洲天堂网2025| 波多野结衣vs黑人巨大| 丁香婷婷男人天堂| 大香蕉精品在线| 天天干天天操天天干| 香蕉网址| 欧美丰满老熟妇XXXXX性| AV网站在线免费观看| 99精品国自产在线| 蜜臀AV在线观看| 大香蕉久久精品| 亚洲中文字幕无码在线观看| 六月丁香久久| 亚洲视频456| 日本天堂Tv视频在线观看| 免费黄色大片| 日本免费爱爱视频| 亚洲狠狠操| 日韩精品网| 亚洲无码一区二区在线观看| 狼友精品| 日本不卡在线视频| 日韩黄色无码视频| 成人a片在线观看| 亚洲综合久| 成年人黄色电影| 狠狠躁18三区二区一区免费人| 高清无码第一页| 大香蕉偷拍视频| 日韩久久网站| 精品免费国产一区二区三区四区 | 国产欧美一区二区三区特黄手机版| 影音先锋男人天堂| 小明成人免费视频| 青青草免费观看视频| 久久男人网| 国产三级网站| 国产精品视频瘾无码| 免费视频久久久| 青青草原成人视频| 内射视频免费观看| 西西人体WW大胆无码| 日本一级按摩片免费观看| 岛国av片| 一插菊花网| 风流老熟女一区二区三区| 好男人WWW一区二区三区| 大鸡巴久久久| 天堂一区| 欧美51精品| 日韩AV无码成人精品| 北条麻妃无码精品| 四虎精品一区二区三区| 97中文在线| 欧美成a| 口爆AV| 无码免费婬AV片在线观看| 抽插视频欧美| 无码欧美人XXXXX日本无码| 丁香激情五月少妇| 一级色情片| 三级视频在线观看| 青青草在线观看免费| 成人免费网站在线| 中文字幕精品亚洲熟女| 国产日韩欧美在线| 日韩中文字幕一区二区| 大香蕉色伊人| 蜜臀久久99精品久久久兰草影视 | 欧美一级婬片A片免费软件| 操杨幂| 天天做天天日| 欧美国产日韩在线观看| 大香蕉久久草| 韩国一区二区三区在线观看| 色天天干| 日韩拍拍| 久久这里有精品视频| 青青草视频偷拍| AV在线资源网| 精品一区二区三区四区| 18禁网站在线播放| 亚洲av动漫| 色中文字幕| 在线观看中文字幕视频| 人人干天天操| 高清国产AV| 性欧美丰满熟妇XXXX性久久久 | 黄页网站在线免费观看| 中文无码Av| 午夜福利站| 91精品丝袜久久久久久久久久粉嫩| av操逼网| 91精品成人电影| 无码A区| 国产毛片欧美毛片高潮| 波多野结衣一二三区| 国产女人在线观看| 欧美成人精品A片免费一区99| 亚洲无码视频看看| 欧美黄色一级视频| 中国熟睡妇BBwBBw| 国产中文视频| 中文字幕操逼网站| 午夜h片| 日本黄色大片| 日韩三级一区二区| 翔田千里无码播放| 大香蕉一区| 好男人一区二区三区在线观看 | 2025AV天堂网| 精品乱码一区| 欧美性猛交XXXX乱大交HD| 国内自拍视频在线观看| 97色色视频| 免费无码在线| 久久午夜无码鲁片午夜精品男男| 国产A片电影| 日韩中文字幕无码| 久久久伊人网| 专业操老外| 五月婷婷日韩| 亚洲中文字幕在| 操逼的视频| 亚洲www视频| 中国老女人操逼| 不卡无码中文字幕| 免费精品视频| 亚洲视频三区| 欧美丰满人妻| 最新久欠一区二区免费看| 超碰在线人人| 欧美日韩视频| 特级西西444WWW高清| 91在线资源| 久久亚洲精品视频| 日韩人妻无码一区二区| 精品秘一区性综合三区| 欧美拍拍视频| 自拍偷拍1| 91资源在线观看| 亚洲一区色| 国产三级国产三级国产| 三级国产网站| 无码国产一区二区三区四区五区| 香蕉av在线播放| 日韩欧美V| 中文字字幕中文字幕乱码| 人人操人人操人人操人人| 美国一级A片草草视频| 日本成人一区二区| 大荫蒂hd大荫蒂视频| 激情五月色五月| 视频二区中文字幕| 日韩人妻精品一区二区| 国产午夜无码视频在线观看| 亚洲精品成人无码熟妇在线| 中文字幕精品在线观看| 无码欧美人XXXXX日本无码 | 爱爱视频欧美| 久久久久久久久成人| 亚洲欧美日韩一区二区| 欧美成人网址在线观看| 黄片免费看| 亚洲最大网站| 欧美日韩视频在线| 免费A在线观看| 性爱AV在线观看| 日韩黄片免费看| 成年人免费黄色视频| 97激情| 五月激情婷婷网| 亚洲AV无码成人精品| 操操片| 美女大吊,网站视频| 天天摸天天日| 国产尤物在线| 国产一二三| 国产在线观看你懂的| 日韩人妻精品中文字幕| 亚洲色欲av| 大香蕉精品欧美色综合2025| 91精品大屁股白浆自慰久久久| 成人动漫一区| 成人网站视频在线观看| 手机AV在线播放| 人妻无码中文久久久久专区| 伊人福利导航| 91麻豆国产福利在线观看| 五月丁香综合网| 91人妻人人澡人人爽人人爽| 正在播放ADN156松下纱荣子| 三级久久久| 经典三级在线视频| 三级无码| 欧美日逼网站| 久久综合色色| 褒姒AV无玛| 强伦轩一区二区三区四区| AV成人无码| 日韩综合在线| 中文字幕永久在线观看| 无码色网| 午夜黄色视频| 亚洲日本高清| 欧美大鸡巴在线观看| 国产高清av| 欧美午夜三级| 麻豆AV片| 豆花网无码视频观看| 人人爱人人射| 俺去也www俺去也com| 在线观看黄片网站| 成人不卡| 黄片无码免费观看| 日本中文字幕在线免费观看| 人妻无码| 丁香花小说完整视频免费观看| 欧美高潮| 成年人性生活免费视频| 国产熟妇码视频| 精品人妻一区二区三区在线视频不卡 | 久久久久久久久久久久久久久久久久久久| 深爱五月激情网| 人人摸在线视频| 国产熟女一区二区三区五月婷| 特极西西444WWW大胆无码| 久草不卡| 99r6热只有精品免费观看| 大香蕉一区| 亚洲综合另类| 人人爽人人操人人| 四虎影院最新地址| 91探花秘在线播放| 成人亚洲AV日韩AV无码| 国产真人无码| 亚洲口味重一级黄片| 91丨人妻丨偷拍| 人妻精品久久久久中文字幕69| 大荫蒂精品另类| 日韩免费高清在线视频| 丁香五月激情视频| 精品国产三级片| 久久视频在线| 91人妻无码精品| 伊人大香蕉在线| 春色av| 欧美日韩黄色片| 性免费网站| 精品视频在线免费| 婷婷丁香五月激情| 亚洲福利视频网站| 免费在线观看视频a| 欧美性爱高清| 日韩一级免费| 尻屄视频在线观看| 亚洲美女视频在线观看| 亚洲视频无码在线| Www.黄色| 麻豆精品传媒国产剧的特点| 中文字幕婷婷| 加勒比在线| 国产精品免费人成人网站酒店| 免费尻屄视频| 国产极品无码| 日韩性AV| 精品第一页| 婷婷在线观看视频| 成人国产精品在线看| 一级黄色免费看| 国产69精品久久| 国产精品色情A级毛片| 日本最新免费二区| 精品第一页| 久久凹凸视频| 色婷婷视频在线播放| 嫰BBB槡BBBB槡BBBB| 久久久xxx| 婷婷无码成人精品俺来俺去| 五月天激情啪啪| 蝌蚪窝视频在线观看| 青娱乐91| 无码a片| 国产传媒精品| 国产成人亚洲综合AV婷婷| 黑人亚洲娇小videos∞| 操逼地址| 欧美在线日韩在线| 亚洲国产精品一区二区三区| 91丝袜一区二区| 高清一区二区三区| 河南少妇搡BBBB搡BBBB| 日韩av一区二区三区| 国产精品无码天天爽视频| 波多野结衣久久中文字幕| 丁香五月激情在线| 在线观看日韩视频| 啪啪视频在线观看| 人妻操逼视频| 久久撸在线视频| 日韩久操| 亚洲品久久久蜜| 伊人大香蕉网| 69久蜜桃人妻无码精品一区| 国产一级AAAAA片免费| 天天日天天干天天日| 狠狠干狠狠撸| 亚洲欧美成人网| 一级a一级a爱片免费视频| 伊人福利导航| 青青自拍视频| 激情深爱| 中文字幕在线观看网址最新地址| 色婷婷在线无码精品秘人口传媒| 国产精品1区2区| 国产精品蜜| 激情丁香六月| 成人看片| 国产亲子乱XXXXinin| 爱操逼网| 四川少妇BBBB槡BBBB槡| 欧美插穴| 香蕉久久网| 亚洲va国产天堂va久久en | 日屄免费视频| 狼友视频免费| 凸凹翔田千里无码| 日韩综合精品| 99热只有精| 69成人在线电影| 欧美精品乱码99久久蜜桃| 欧美成人AA| 操夜夜操| 91国产在线播放| 岛国av免费看| 操日本逼| 91做爱| 外国一级片| 乱伦91| 天天日天天干天天操| 网络自拍亚洲激情| 黄色大片免费看| 婷婷导航| AA黄色电影| 日韩中文字幕永久| 国产字幕在线观看| 风间由美大荫蒂无码AV| 一级黄色电影免费| 色三区| 欧美色色网站| 日逼免费网站| 水果派AV解说| 一本大道香蕉av久久精东影业| 国产精品久久久久久久久久二区三区| 一本色道久久综合熟妇人妻| 国产精品啪啪啪啪| 成人永久免费视频| 天干夜天干天天天爽视频| 杨门女将婬乱史1—6| 国产在线中文| AV日韩无码| 五月天高清无码| 在线少妇| 久久精品视频免费| 自慰喷水流白浆中文字幕| 日韩一级电影在线| 豆花视频在线播放| 竹菊传媒一区二区三区| 黑人巨大精品欧美| 日本十八禁网站| 欧美一级操逼| 五月天av在线观看| 国产精品欧美激情| 亚州无码精品| 亚洲精品乱码久久久久久| 亚洲无码一区二区在线观看| 四虎精品一区二区三区| 草逼美女| 国产一级特黄大片| 成人激情免费视频| 婷婷五月天网址| 88av在线| 麻豆91网站| 成人高清在线| 狠狠干综合网| 性满足BBWBBWBBW| 国产第二页| 蜜桃网站视频| 91三级片在线观看| 91干干干| 久久精品福利视频| 久久成人A片| 无码国产+白浆| 最近中文字幕在线中文字幕7| 狠狠干狠狠撸| 日本高清版色视频| 精品无人区无码乱码毛片国产| 久久蜜桃视频| 人人天天夜夜| AV日逼网| 手机看片1024你懂的| 亚洲AV无码永久精品| 91久久视频| 视频一视频二在线视频| 亚洲av大片| 激情内射网站| 国产人妖在线| 激情小视频在线| 亚洲AV无码国产精品久久不卡| 免费一级A毛片夜夜看| 婷婷久久久| 91在线无码视频| 精品国产久久久久久| 国产AV黄色| 久久人搡人人玩人妻精AV香蕉| 国产精品在线免费| 超碰免费人妻| 国产成人va| 国产aa| 亚洲AV在线看| 黄片高清无码在线观看| 一二区无码| 欧美日韩视频| 99精品视频免费在线观看| 综合中文字幕| 国产视频久久| 青青草网址| AV在线一区二区| 狼友视频在在观看| 91.n| 蝌蚪窝视频在线| 日韩精品一区二区三区免费观看高清 | 91九色蝌蚪91POR成人| 黑人人妻黑人ThePorn| 中文字幕在线观看完整av| 超碰九一| 中文字幕人妻一区| 亚洲草逼视频| 91麻豆精品国产91久久久久久| 婷婷免费视频| 中文字幕无码一区二区| www.91com| 激情视频网站| 亚洲天堂三级片| 99国产精品免费视频观看8| 美日韩在线观看| 日韩久久高清| 在线无码AV| 撸一撸成人在线做爱视频。| 伊人影院99| 久久男人网| 亚洲无码免费视频在线观看| 久久无码一区二区| 日本黄色A片| 91啦丨熟女露脸| 在线91| 午夜神马51| 亚洲三级片在线| 五月天激情午夜福利| 国产黄色小视频在线观看| 天天干天天干天天日| 一级A毛片| 91九色在线观看| 艹B视频| 韩国精品一区二区三区| 亚洲一区二区三区在线++中国| 亚洲av大全| 操逼网站免费| 成人精品一区日本无码网站suv/| 在线激情| 精品国产123| 特逼视频| 亚洲理论在线| 五月婷婷网站| 俺来也影院| 狠狠色狠狠干| 中文字幕视频在线直播| 中文字幕第10页| 欧美18禁黄免费网站| 免费无码一级A片大黄在线观看| 国产在线一区二区| 国产ts在线观看| 欧美亚洲视频| 先锋久久| 日本无码在线| 中文字幕无码成人| 久色性爱视频| 在线观看中文字幕网站| 先锋影音资源站| 天天舔天天日| 欧美日韩性爰视频| 一区二区免费看| 综合一区二区三区| 99久久婷婷国产综合| 青青操b| 特黄AAAAAAAA片免费直播| 91毛片在线观看| 久久久久久久久国产精品| 欧美操逼的| 91精品在线观看视频| 安微妇搡BBBB搡BBBB| 午夜电影无码| 亚洲艹| 蜜臀在线视频| 亚洲国产一区二区在线| 美日韩一级| 欧美AA级毛片| 日韩免费小视频| 日韩欧美精品一区二区| 亚洲色欲色欲www在线成人网| 天天操网站| 在线观看无码| 亚洲人妻免费视频| 亚洲无码中文字幕视频| 嗯嗯啊啊网站| 深爱激情网五月天| 久久久亚洲熟妇熟女| 精品无码一区二区三| 亚洲AV白浆| 91一区二区在线观看| 91亚洲影院| 久久精品一二三| 伊人成年网| 超碰人人操人人| 麻豆成人91精品二区三区| 少妇高潮av久久久久久| 欧美激情亚洲无码| 色呦呦视频在线观看| 青青草91视频| 亚洲成人性爱网| 日韩无码人妻| 国产三级AV在线观看| 四虎最新地址| 内射熟妇| 欧美日逼网站| 91久久99久久91熟女精品| 高清欧美日韩第一摸| 久久久久久黄片| 日皮网站在线观看| 18AV在线观看| 成人小视频在线观看| 欧美色图15p| 在线观看黄片网站| 午夜亚洲无码| 免费在线黄色视频| 日本A在线| 国产一级黄色| 一区无码视频| 18成人网站在线观看| 在线日韩AV| 91人妻无码精品一区二区| 亚洲av影院| 亚洲北条麻妃一级A片| 日本无码视频在线| 91色秘乱码一区二区| 欧美三级精品| 久草中文在线| 国产人妻精品一区二区三区不卡| 成人三级片网| 日韩在线观看视频网站| 日韩A电影| www.97yy| 亚洲免费观看高清完整| 中文字幕人妻在线中文乱码怎么解决 | 欧美a片在线观看| 精品人妻一区二区免费蜜桃视频| 欧美色综合| 特级西西444www高清大胆免费看| 麻豆一二三区| 日韩中文字幕免费| 亚洲中文字| 久久大伊人| 乱轮视频| 成人av中文字幕| 婷婷五月天社区| av人人| 色婷婷色婷婷| 理论片91| 全国最大成人网站| 大香焦草久| 屁屁影院CCYYCOM国产| 亚洲视频一区二区三区四区娇小视频在线观看视频 | 伊人成人电影| 91牛视频| 在线观看无码高清视频| 最近中文字幕在线| 欧洲激情网| 免费观看一级A片| 人人夜夜人人| 中文字幕不卡视频| 国产精品秘久久久久久免费播放| 亚洲高清视屏| 日日搔AV一区二区三区| 欧美中文在线观看| 欧美日韩视频在线| 日韩性生活| 午夜啪啪视频| 国产精品国产精品国产专区不片| 精品91美女| 中文字幕AV在线免费观看| 网站毛片| 午夜福利黄色| 亚洲无码一区二区三区蜜桃| 亚洲视频大全| 青青操逼视频| 国产成人电影免费在线观看| 欧美老妇另类BBwBBw| 亚洲无套内射| 日韩一二区| 成人黄色在线观看视频| 国产亚洲色婷婷久久99精品| 欧美一级片在线| 在线日韩中文字幕| 国产午夜精品一区二区三区嫩A| 欧美日韩国产精品成人| 日本精品人妻无码77777| 免费69视频| 嘉兴少妇按摩69XX| 婷婷日韩中文字幕| 男女高清无码| 日韩AV乱伦| 性猛交AAAA片免费看蜜桃视频| 午夜AV大片| 97人人爽人人爽人人爽人人爽| 亚洲va视频| 国产精品国产精品国产| 无码欧精品亚洲日韩一区| 久久精品夜色噜噜亚洲A∨| 在线不卡视频| 五月丁香激情四射| 激情综合久久| 亚洲无码激情| 91偷拍与自偷拍精品无码| 四川BBBBBB搡BBBBB| 91九九| 亚洲在线观看网站| 欧美日韩黄色片| 在线视频a| 黃色毛片A片AAAA级20| 69视频免费观看| 午夜A片| av在线小说| 伊人视频在线| 五月天黄色电影| 色播视频在线观看| 婷婷五月天综合| 中国老太卖婬HD播放| P站免费版-永久免费的福利视频平台| 热99re69精品8在线播放| 人人看人人摸| 亚洲精品国产精品国自产A片同性 丰满人妻一区二区三区四区不卡 国产1级a毛a毛1级a毛1级 | 国产香蕉在线观看| 国产欧美一区在线看| 国产成人福利| 五月香婷婷| 人人看人人搞人人摸| 精品国内自产拍在线观看视频| 无码AV一区二区| 中字无码av| 北条麻纪无码视频| 精品国产乱子伦一区二区三区最新章 | 蜜桃视频一区二区| 中国免费看片| 日韩成人免费观看| 久久婷婷国产| 亚洲成人情趣大香蕉| 岛国无码av| 性爱免费视频| 免费人成在线观看视频播放 | 午夜毛片| 超碰在线人妻| 日韩中文字幕有码| 91精品国产人妻| 一级A片亲子乱中文| 日日干夜夜撸| 一区二区三区在线视频观看| 成人免费在线观看| 国产精品无码永久免费A片 | 久久激情视频| www.wuma| 最新无码在线| 天天爽夜夜爽夜夜爽精品视频| 亚洲精品成人AV| AV无码网站| 91精品国产乱码| 热久久这里只有精品| H片在线观看| 性欧美欧美巨大69| 亚洲性爱视频在线观看| 亲子乱婬-一级A片| 成人亚洲A片V一区二区三区蜜月| 国产成人宗合|