Title: [274022] trunk/Source
Revision
274022
Author
cdu...@apple.com
Date
2021-03-05 17:23:53 -0800 (Fri, 05 Mar 2021)

Log Message

Update ApplicationCacheStorage::originsWithCache() to return a HashSet<SecurityOriginData> instead of a Vector<Ref<SecurityOrigin>>
https://bugs.webkit.org/show_bug.cgi?id=222828

Reviewed by Darin Adler.

Update ApplicationCacheStorage::originsWithCache() to return a HashSet<SecurityOriginData> instead of a Vector<Ref<SecurityOrigin>>.
Using a HashSet makes sure we do not return duplicates (which do occur as per ApplicationCacheStorage implementation) and makes typing
more consistent with other similar storage functions. Using SecurityOriginData is more lightweight and sufficient for our use cases.
It also takes care of a FIXME comment in WebsiteDataStore::fetchDataAndApply about switching to SecurityOriginData.

Source/WebCore:

* loader/appcache/ApplicationCacheStorage.cpp:
(WebCore::ApplicationCacheStorage::calculateUsageForOrigin):
(WebCore::ApplicationCacheStorage::originsWithCache):
(WebCore::ApplicationCacheStorage::deleteCacheForOrigin):
(WebCore::ApplicationCacheStorage::diskUsageForOrigin):
* loader/appcache/ApplicationCacheStorage.h:

Source/WebKit:

This patch also updates WebsiteDataStore::fetchDataAndApply() to crossThreadCopy() the securityOriginData before sending them from
the data store queue to the main thread. The previous code as sending SecurityOrigins and WebsiteData to the main thread without
any isolated copy, which was fragile and would not have been thread-safe if ApplicationCacheStorage::originsWithCache() had cached
the origins it returned for example.

Also update WebsiteDataStore::removeData() to make sure we crossThreadCopy() the origins before sending them from the main thread
to the data store queue. This code did not look thread-safe.

* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::fetchDataAndApply):
(WebKit::WebsiteDataStore::removeData):
* WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
(WKBundlePageClearApplicationCacheForOrigin):
(WKBundlePageGetAppCacheUsageForOrigin):
(WKBundlePageCopyOriginsWithApplicationCache):

Source/WebKitLegacy/mac:

* WebCoreSupport/WebApplicationCache.mm:
(+[WebApplicationCache diskUsageForOrigin:]):
(+[WebApplicationCache deleteCacheForOrigin:]):
(+[WebApplicationCache originsWithCache]):
* WebCoreSupport/WebApplicationCacheQuotaManager.mm:
(-[WebApplicationCacheQuotaManager usage]):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (274021 => 274022)


--- trunk/Source/WebCore/ChangeLog	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebCore/ChangeLog	2021-03-06 01:23:53 UTC (rev 274022)
@@ -1,5 +1,24 @@
 2021-03-05  Chris Dumez  <cdu...@apple.com>
 
+        Update ApplicationCacheStorage::originsWithCache() to return a HashSet<SecurityOriginData> instead of a Vector<Ref<SecurityOrigin>>
+        https://bugs.webkit.org/show_bug.cgi?id=222828
+
+        Reviewed by Darin Adler.
+
+        Update ApplicationCacheStorage::originsWithCache() to return a HashSet<SecurityOriginData> instead of a Vector<Ref<SecurityOrigin>>.
+        Using a HashSet makes sure we do not return duplicates (which do occur as per ApplicationCacheStorage implementation) and makes typing
+        more consistent with other similar storage functions. Using SecurityOriginData is more lightweight and sufficient for our use cases.
+        It also takes care of a FIXME comment in WebsiteDataStore::fetchDataAndApply about switching to SecurityOriginData.
+
+        * loader/appcache/ApplicationCacheStorage.cpp:
+        (WebCore::ApplicationCacheStorage::calculateUsageForOrigin):
+        (WebCore::ApplicationCacheStorage::originsWithCache):
+        (WebCore::ApplicationCacheStorage::deleteCacheForOrigin):
+        (WebCore::ApplicationCacheStorage::diskUsageForOrigin):
+        * loader/appcache/ApplicationCacheStorage.h:
+
+2021-03-05  Chris Dumez  <cdu...@apple.com>
+
         Make HTMLMediaElement::clearMediaCacheForOrigins() take in SecurityOriginData objects
         https://bugs.webkit.org/show_bug.cgi?id=222832
 

Modified: trunk/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp (274021 => 274022)


--- trunk/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp	2021-03-06 01:23:53 UTC (rev 274022)
@@ -434,7 +434,7 @@
     return false;
 }
 
-bool ApplicationCacheStorage::calculateUsageForOrigin(const SecurityOrigin* origin, int64_t& usage)
+bool ApplicationCacheStorage::calculateUsageForOrigin(const SecurityOriginData& origin, int64_t& usage)
 {
     SQLiteTransactionInProgressAutoCounter transactionCounter;
 
@@ -448,7 +448,7 @@
     if (statement.prepare() != SQLITE_OK)
         return false;
 
-    statement.bindText(1, origin->data().databaseIdentifier());
+    statement.bindText(1, origin.databaseIdentifier());
     int result = statement.step();
 
     if (result == SQLITE_ROW) {
@@ -1467,7 +1467,7 @@
     return totalSize;
 }
 
-Vector<Ref<SecurityOrigin>> ApplicationCacheStorage::originsWithCache()
+HashSet<SecurityOriginData> ApplicationCacheStorage::originsWithCache()
 {
     auto urls = manifestURLs();
     if (!urls)
@@ -1475,10 +1475,9 @@
 
     // Multiple manifest URLs might share the same SecurityOrigin, so we might be creating extra, wasted origins here.
     // The current schema doesn't allow for a more efficient way of building this list.
-    Vector<Ref<SecurityOrigin>> origins;
-    origins.reserveInitialCapacity(urls->size());
+    HashSet<SecurityOriginData> origins;
     for (auto& url : *urls)
-        origins.uncheckedAppend(SecurityOrigin::create(url));
+        origins.add(SecurityOriginData::fromURL(url));
     return origins;
 }
 
@@ -1497,7 +1496,7 @@
     vacuumDatabaseFile();
 }
 
-void ApplicationCacheStorage::deleteCacheForOrigin(const SecurityOrigin& securityOrigin)
+void ApplicationCacheStorage::deleteCacheForOrigin(const SecurityOriginData& securityOrigin)
 {
     auto urls = manifestURLs();
     if (!urls) {
@@ -1518,10 +1517,10 @@
     }
 }
 
-int64_t ApplicationCacheStorage::diskUsageForOrigin(const SecurityOrigin& securityOrigin)
+int64_t ApplicationCacheStorage::diskUsageForOrigin(const SecurityOriginData& securityOrigin)
 {
     int64_t usage = 0;
-    calculateUsageForOrigin(&securityOrigin, usage);
+    calculateUsageForOrigin(securityOrigin, usage);
     return usage;
 }
 

Modified: trunk/Source/WebCore/loader/appcache/ApplicationCacheStorage.h (274021 => 274022)


--- trunk/Source/WebCore/loader/appcache/ApplicationCacheStorage.h	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebCore/loader/appcache/ApplicationCacheStorage.h	2021-03-06 01:23:53 UTC (rev 274022)
@@ -63,7 +63,7 @@
 
     int64_t defaultOriginQuota() const { return m_defaultOriginQuota; }
     WEBCORE_EXPORT void setDefaultOriginQuota(int64_t quota);
-    WEBCORE_EXPORT bool calculateUsageForOrigin(const SecurityOrigin*, int64_t& usage);
+    WEBCORE_EXPORT bool calculateUsageForOrigin(const SecurityOriginData&, int64_t& usage);
     WEBCORE_EXPORT bool calculateQuotaForOrigin(const SecurityOrigin&, int64_t& quota);
     bool calculateRemainingSizeForOriginExcludingCache(const SecurityOrigin&, ApplicationCache*, int64_t& remainingSize);
     WEBCORE_EXPORT bool storeUpdatedQuotaForOrigin(const SecurityOrigin*, int64_t quota);
@@ -86,7 +86,7 @@
 
     WEBCORE_EXPORT void empty();
 
-    WEBCORE_EXPORT Vector<Ref<SecurityOrigin>> originsWithCache();
+    WEBCORE_EXPORT HashSet<SecurityOriginData> originsWithCache();
     WEBCORE_EXPORT void deleteAllEntries();
 
     // FIXME: This should be consolidated with deleteAllEntries().
@@ -93,10 +93,10 @@
     WEBCORE_EXPORT void deleteAllCaches();
 
     // FIXME: This should be consolidated with deleteCacheGroup().
-    WEBCORE_EXPORT void deleteCacheForOrigin(const SecurityOrigin&);
+    WEBCORE_EXPORT void deleteCacheForOrigin(const SecurityOriginData&);
 
     // FIXME: This should be consolidated with calculateUsageForOrigin().
-    WEBCORE_EXPORT int64_t diskUsageForOrigin(const SecurityOrigin&);
+    WEBCORE_EXPORT int64_t diskUsageForOrigin(const SecurityOriginData&);
 
     static int64_t unknownQuota() { return -1; }
     static int64_t noQuota() { return std::numeric_limits<int64_t>::max(); }

Modified: trunk/Source/WebKit/ChangeLog (274021 => 274022)


--- trunk/Source/WebKit/ChangeLog	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebKit/ChangeLog	2021-03-06 01:23:53 UTC (rev 274022)
@@ -1,5 +1,33 @@
 2021-03-05  Chris Dumez  <cdu...@apple.com>
 
+        Update ApplicationCacheStorage::originsWithCache() to return a HashSet<SecurityOriginData> instead of a Vector<Ref<SecurityOrigin>>
+        https://bugs.webkit.org/show_bug.cgi?id=222828
+
+        Reviewed by Darin Adler.
+
+        Update ApplicationCacheStorage::originsWithCache() to return a HashSet<SecurityOriginData> instead of a Vector<Ref<SecurityOrigin>>.
+        Using a HashSet makes sure we do not return duplicates (which do occur as per ApplicationCacheStorage implementation) and makes typing
+        more consistent with other similar storage functions. Using SecurityOriginData is more lightweight and sufficient for our use cases.
+        It also takes care of a FIXME comment in WebsiteDataStore::fetchDataAndApply about switching to SecurityOriginData.
+
+        This patch also updates WebsiteDataStore::fetchDataAndApply() to crossThreadCopy() the securityOriginData before sending them from
+        the data store queue to the main thread. The previous code as sending SecurityOrigins and WebsiteData to the main thread without
+        any isolated copy, which was fragile and would not have been thread-safe if ApplicationCacheStorage::originsWithCache() had cached
+        the origins it returned for example.
+
+        Also update WebsiteDataStore::removeData() to make sure we crossThreadCopy() the origins before sending them from the main thread
+        to the data store queue. This code did not look thread-safe.
+
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::fetchDataAndApply):
+        (WebKit::WebsiteDataStore::removeData):
+        * WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
+        (WKBundlePageClearApplicationCacheForOrigin):
+        (WKBundlePageGetAppCacheUsageForOrigin):
+        (WKBundlePageCopyOriginsWithApplicationCache):
+
+2021-03-05  Chris Dumez  <cdu...@apple.com>
+
         Make HTMLMediaElement::clearMediaCacheForOrigins() take in SecurityOriginData objects
         https://bugs.webkit.org/show_bug.cgi?id=222832
 

Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp (274021 => 274022)


--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp	2021-03-06 01:23:53 UTC (rev 274022)
@@ -526,20 +526,12 @@
 
         m_queue->dispatch([fetchOptions, applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
-
             WebsiteData websiteData;
-
-            // FIXME: getOriginsWithCache should return a collection of SecurityOriginDatas.
-            auto origins = storage->originsWithCache();
-
-            for (auto& origin : origins) {
+            for (auto& origin : storage->originsWithCache()) {
                 uint64_t size = fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes) ? storage->diskUsageForOrigin(origin) : 0;
-                WebsiteData::Entry entry { origin->data(), WebsiteDataType::OfflineWebApplicationCache, size };
-
-                websiteData.entries.append(WTFMove(entry));
+                websiteData.entries.append(WebsiteData::Entry { crossThreadCopy(origin), WebsiteDataType::OfflineWebApplicationCache, size });
             }
-
-            RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins), websiteData = WTFMove(websiteData)]() mutable {
+            RunLoop::main().dispatch([callbackAggregator, websiteData = WTFMove(websiteData)]() mutable {
                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
             });
         });
@@ -974,7 +966,7 @@
         HashSet<WebCore::SecurityOriginData> origins;
         for (const auto& dataRecord : dataRecords) {
             for (const auto& origin : dataRecord.origins)
-                origins.add(origin);
+                origins.add(crossThreadCopy(origin));
         }
         
 #if ENABLE(VIDEO)
@@ -1063,16 +1055,14 @@
         HashSet<WebCore::SecurityOriginData> origins;
         for (const auto& dataRecord : dataRecords) {
             for (const auto& origin : dataRecord.origins)
-                origins.add(origin);
+                origins.add(crossThreadCopy(origin));
         }
 
         callbackAggregator->addPendingCallback();
         m_queue->dispatch([origins = WTFMove(origins), applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
-
             for (const auto& origin : origins)
-                storage->deleteCacheForOrigin(origin.securityOrigin());
-
+                storage->deleteCacheForOrigin(origin);
             WTF::RunLoop::main().dispatch([callbackAggregator] {
                 callbackAggregator->removePendingCallback();
             });
@@ -1083,7 +1073,7 @@
         HashSet<WebCore::SecurityOriginData> origins;
         for (const auto& dataRecord : dataRecords) {
             for (const auto& origin : dataRecord.origins)
-                origins.add(origin);
+                origins.add(crossThreadCopy(origin));
         }
 
         callbackAggregator->addPendingCallback();
@@ -1101,7 +1091,7 @@
         HashSet<WebCore::SecurityOriginData> origins;
         for (const auto& dataRecord : dataRecords) {
             for (const auto& origin : dataRecord.origins)
-                origins.add(origin);
+                origins.add(crossThreadCopy(origin));
         }
 
         callbackAggregator->addPendingCallback();

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp (274021 => 274022)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp	2021-03-06 01:23:53 UTC (rev 274022)
@@ -819,7 +819,7 @@
 
 void WKBundlePageClearApplicationCacheForOrigin(WKBundlePageRef page, WKStringRef origin)
 {
-    WebKit::toImpl(page)->corePage()->applicationCacheStorage().deleteCacheForOrigin(WebCore::SecurityOrigin::createFromString(WebKit::toImpl(origin)->string()));
+    WebKit::toImpl(page)->corePage()->applicationCacheStorage().deleteCacheForOrigin(WebCore::SecurityOriginData::fromURL(URL(URL(), WebKit::toImpl(origin)->string())));
 }
 
 void WKBundlePageSetAppCacheMaximumSize(WKBundlePageRef page, uint64_t size)
@@ -829,7 +829,7 @@
 
 uint64_t WKBundlePageGetAppCacheUsageForOrigin(WKBundlePageRef page, WKStringRef origin)
 {
-    return WebKit::toImpl(page)->corePage()->applicationCacheStorage().diskUsageForOrigin(WebCore::SecurityOrigin::createFromString(WebKit::toImpl(origin)->string()));
+    return WebKit::toImpl(page)->corePage()->applicationCacheStorage().diskUsageForOrigin(WebCore::SecurityOriginData::fromURL(URL(URL(), WebKit::toImpl(origin)->string())));
 }
 
 void WKBundlePageSetApplicationCacheOriginQuota(WKBundlePageRef page, WKStringRef origin, uint64_t bytes)
@@ -850,7 +850,7 @@
     originIdentifiers.reserveInitialCapacity(origins.size());
 
     for (const auto& origin : origins)
-        originIdentifiers.uncheckedAppend(API::String::create(origin->data().databaseIdentifier()));
+        originIdentifiers.uncheckedAppend(API::String::create(origin.databaseIdentifier()));
 
     return WebKit::toAPI(&API::Array::create(WTFMove(originIdentifiers)).leakRef());
 }

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (274021 => 274022)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2021-03-06 01:23:53 UTC (rev 274022)
@@ -1,5 +1,24 @@
 2021-03-05  Chris Dumez  <cdu...@apple.com>
 
+        Update ApplicationCacheStorage::originsWithCache() to return a HashSet<SecurityOriginData> instead of a Vector<Ref<SecurityOrigin>>
+        https://bugs.webkit.org/show_bug.cgi?id=222828
+
+        Reviewed by Darin Adler.
+
+        Update ApplicationCacheStorage::originsWithCache() to return a HashSet<SecurityOriginData> instead of a Vector<Ref<SecurityOrigin>>.
+        Using a HashSet makes sure we do not return duplicates (which do occur as per ApplicationCacheStorage implementation) and makes typing
+        more consistent with other similar storage functions. Using SecurityOriginData is more lightweight and sufficient for our use cases.
+        It also takes care of a FIXME comment in WebsiteDataStore::fetchDataAndApply about switching to SecurityOriginData.
+
+        * WebCoreSupport/WebApplicationCache.mm:
+        (+[WebApplicationCache diskUsageForOrigin:]):
+        (+[WebApplicationCache deleteCacheForOrigin:]):
+        (+[WebApplicationCache originsWithCache]):
+        * WebCoreSupport/WebApplicationCacheQuotaManager.mm:
+        (-[WebApplicationCacheQuotaManager usage]):
+
+2021-03-05  Chris Dumez  <cdu...@apple.com>
+
         Reduce use of CFRetain() / CFRelease() / CFAutoRelease() in WebKit
         https://bugs.webkit.org/show_bug.cgi?id=222760
 

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebApplicationCache.mm (274021 => 274022)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebApplicationCache.mm	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebApplicationCache.mm	2021-03-06 01:23:53 UTC (rev 274022)
@@ -111,7 +111,7 @@
 
 + (long long)diskUsageForOrigin:(WebSecurityOrigin *)origin
 {
-    return webApplicationCacheStorage().diskUsageForOrigin(*[origin _core]);
+    return webApplicationCacheStorage().diskUsageForOrigin([origin _core]->data());
 }
 
 + (void)deleteAllApplicationCaches
@@ -121,13 +121,13 @@
 
 + (void)deleteCacheForOrigin:(WebSecurityOrigin *)origin
 {
-    webApplicationCacheStorage().deleteCacheForOrigin(*[origin _core]);
+    webApplicationCacheStorage().deleteCacheForOrigin([origin _core]->data());
 }
 
 + (NSArray *)originsWithCache
 {
     return createNSArray(webApplicationCacheStorage().originsWithCache(), [] (auto& origin) {
-        return adoptNS([[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin.ptr()]);
+        return adoptNS([[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin.securityOrigin().ptr()]);
     }).autorelease();
 }
 

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebApplicationCacheQuotaManager.mm (274021 => 274022)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebApplicationCacheQuotaManager.mm	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebApplicationCacheQuotaManager.mm	2021-03-06 01:23:53 UTC (rev 274022)
@@ -49,7 +49,7 @@
 - (unsigned long long)usage
 {
     long long usage;
-    if (webApplicationCacheStorage().calculateUsageForOrigin([_origin _core], usage))
+    if (webApplicationCacheStorage().calculateUsageForOrigin([_origin _core]->data(), usage))
         return usage;
     return 0;
 }

Modified: trunk/Source/WebKitLegacy/win/WebApplicationCache.cpp (274021 => 274022)


--- trunk/Source/WebKitLegacy/win/WebApplicationCache.cpp	2021-03-06 01:03:23 UTC (rev 274021)
+++ trunk/Source/WebKitLegacy/win/WebApplicationCache.cpp	2021-03-06 01:23:53 UTC (rev 274022)
@@ -160,7 +160,7 @@
     if (!webSecurityOrigin)
         return E_FAIL;
 
-    *size = storage().diskUsageForOrigin(*webSecurityOrigin->securityOrigin());
+    *size = storage().diskUsageForOrigin(webSecurityOrigin->securityOrigin()->data());
     return S_OK;
 }
 
@@ -180,7 +180,7 @@
     if (!webSecurityOrigin)
         return E_FAIL;
 
-    storage().deleteCacheForOrigin(*webSecurityOrigin->securityOrigin());
+    storage().deleteCacheForOrigin(webSecurityOrigin->securityOrigin()->data());
     return S_OK;
 }
 
@@ -195,7 +195,7 @@
     RetainPtr<CFMutableArrayRef> arrayItem = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, coreOrigins.size(), &MarshallingHelpers::kIUnknownArrayCallBacks));
 
     for (auto& coreOrigin : coreOrigins)
-        CFArrayAppendValue(arrayItem.get(), reinterpret_cast<void*>(WebSecurityOrigin::createInstance(coreOrigin.ptr())));
+        CFArrayAppendValue(arrayItem.get(), reinterpret_cast<void*>(WebSecurityOrigin::createInstance(coreOrigin.securityOrigin().ptr())));
 
     RetainPtr<CFMutableDictionaryRef> dictionary = adoptCF(
         CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to