Diff
Modified: trunk/LayoutTests/ChangeLog (264789 => 264790)
--- trunk/LayoutTests/ChangeLog 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/LayoutTests/ChangeLog 2020-07-23 21:21:21 UTC (rev 264790)
@@ -1,3 +1,18 @@
+2020-07-23 Sihui Liu <[email protected]>
+
+ Allow IndexedDB in third-party frames
+ https://bugs.webkit.org/show_bug.cgi?id=214583
+ <rdar://problem/61278487>
+
+ Reviewed by Geoffrey Garen.
+
+ Update test expectation for new behavior.
+
+ * http/tests/security/cross-origin-indexeddb-expected.txt:
+ * http/tests/security/cross-origin-indexeddb.html:
+ * http/tests/security/cross-origin-worker-indexeddb-expected.txt:
+ * http/tests/security/resources/document-for-cross-origin-worker-indexeddb.html:
+
2020-07-23 Yusuke Suzuki <[email protected]>
Add exception check for WebCore createRejectedPromiseWithTypeError
Modified: trunk/LayoutTests/http/tests/security/cross-origin-indexeddb-expected.txt (264789 => 264790)
--- trunk/LayoutTests/http/tests/security/cross-origin-indexeddb-expected.txt 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/LayoutTests/http/tests/security/cross-origin-indexeddb-expected.txt 2020-07-23 21:21:21 UTC (rev 264790)
@@ -1,4 +1,4 @@
-The first iframe below should return a security error, and the second should successfully open the database.
+Both frames can successfully open the database.
@@ -5,8 +5,8 @@
--------
Frame: '<!--frame1-->'
--------
-window.indexedDB.deleteDatabase() threw an exception: SecurityError
-window.indexedDB.open() threw an exception: SecurityError
+Successfully called window.indexedDB.deleteDatabase().
+Successfully called window.indexedDB.open().
--------
Modified: trunk/LayoutTests/http/tests/security/cross-origin-indexeddb.html (264789 => 264790)
--- trunk/LayoutTests/http/tests/security/cross-origin-indexeddb.html 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/LayoutTests/http/tests/security/cross-origin-indexeddb.html 2020-07-23 21:21:21 UTC (rev 264790)
@@ -17,7 +17,7 @@
</script>
</head>
<body>
- <p>The first iframe below should return a security error, and the second should successfully open the database.</p>
+ <p>Both frames can successfully open the database.</p>
<iframe src="" _onload_="decrement()"></iframe>
<iframe src="" _onload_="decrement()"></iframe>
</body>
Modified: trunk/LayoutTests/http/tests/security/cross-origin-worker-indexeddb-expected.txt (264789 => 264790)
--- trunk/LayoutTests/http/tests/security/cross-origin-worker-indexeddb-expected.txt 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/LayoutTests/http/tests/security/cross-origin-worker-indexeddb-expected.txt 2020-07-23 21:21:21 UTC (rev 264790)
@@ -1,4 +1,4 @@
-The first iframe below should return a security error, and the second should successfully open the database.
+Both frames can successfully open the database.
@@ -5,8 +5,8 @@
--------
Frame: '<!--frame1-->'
--------
-self.indexedDB.deleteDatabase() threw an exception: SecurityError
-self.indexedDB.open() threw an exception: SecurityError
+Successfully called self.indexedDB.deleteDatabase().
+Successfully called self.indexedDB.open().
--------
Modified: trunk/LayoutTests/http/tests/security/resources/document-for-cross-origin-worker-indexeddb.html (264789 => 264790)
--- trunk/LayoutTests/http/tests/security/resources/document-for-cross-origin-worker-indexeddb.html 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/LayoutTests/http/tests/security/resources/document-for-cross-origin-worker-indexeddb.html 2020-07-23 21:21:21 UTC (rev 264790)
@@ -19,7 +19,7 @@
</script>
</head>
<body>
- <p>The first iframe below should return a security error, and the second should successfully open the database.</p>
+ <p>Both frames can successfully open the database.</p>
<iframe src=""
<iframe src=""
</body>
Modified: trunk/Source/WebCore/ChangeLog (264789 => 264790)
--- trunk/Source/WebCore/ChangeLog 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebCore/ChangeLog 2020-07-23 21:21:21 UTC (rev 264790)
@@ -1,3 +1,40 @@
+2020-07-23 Sihui Liu <[email protected]>
+
+ Allow IndexedDB in third-party frames
+ https://bugs.webkit.org/show_bug.cgi?id=214583
+ <rdar://problem/61278487>
+
+ Reviewed by Geoffrey Garen.
+
+ Match IndexedDB's behavior with localStorage. Third-party iframes now have access to IndexedDB with partitioned
+ in-memory storage. The partitioning key is ClientOrigin, which consists of opening origin and top origin.
+
+ API Test: IndexedDB.IndexedDBThirdPartyFrameHasAccess
+ IndexedDB.IndexedDBThirdPartyDataRemoval
+ IndexedDB.IndexedDBThirdPartyWorkerHasAccess
+
+ * Modules/indexeddb/IDBDatabaseIdentifier.cpp:
+ (WebCore::IDBDatabaseIdentifier::IDBDatabaseIdentifier):
+ (WebCore::m_isTransient):
+ (WebCore::IDBDatabaseIdentifier::isolatedCopy const):
+ (WebCore::IDBDatabaseIdentifier::loggingString const):
+ * Modules/indexeddb/IDBDatabaseIdentifier.h:
+ (WebCore::IDBDatabaseIdentifier::hash const):
+ (WebCore::IDBDatabaseIdentifier::operator== const):
+ (WebCore::IDBDatabaseIdentifier::isTransient const):
+ (WebCore::IDBDatabaseIdentifier::encode const):
+ (WebCore::IDBDatabaseIdentifier::decode):
+ * Modules/indexeddb/IDBFactory.cpp:
+ (WebCore::shouldThrowSecurityException):
+ (WebCore::IDBFactory::openInternal):
+ (WebCore::IDBFactory::deleteDatabase):
+ * Modules/indexeddb/server/IDBServer.cpp:
+ (WebCore::IDBServer::IDBServer::createBackingStore):
+ * Modules/webdatabase/DOMWindowWebDatabase.cpp:
+ (WebCore::DOMWindowWebDatabase::openDatabase):
+ * page/SecurityOrigin.h:
+ (WebCore::SecurityOrigin::canAccessDatabase const):
+
2020-07-23 Chris Dumez <[email protected]>
Add support for SVGAElement's rel / relList attributes
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseIdentifier.cpp (264789 => 264790)
--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseIdentifier.cpp 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseIdentifier.cpp 2020-07-23 21:21:21 UTC (rev 264790)
@@ -35,9 +35,10 @@
namespace WebCore {
-IDBDatabaseIdentifier::IDBDatabaseIdentifier(const String& databaseName, SecurityOriginData&& openingOrigin, SecurityOriginData&& mainFrameOrigin)
+IDBDatabaseIdentifier::IDBDatabaseIdentifier(const String& databaseName, SecurityOriginData&& openingOrigin, SecurityOriginData&& mainFrameOrigin, bool isTransient)
: m_databaseName(databaseName)
, m_origin { WTFMove(openingOrigin), WTFMove(mainFrameOrigin) }
+ , m_isTransient(isTransient)
{
// The empty string is a valid database name, but a null string is not.
ASSERT(!databaseName.isNull());
@@ -49,6 +50,7 @@
identifier.m_databaseName = m_databaseName.isolatedCopy();
identifier.m_origin = m_origin.isolatedCopy();
+ identifier.m_isTransient = m_isTransient;
return identifier;
}
@@ -73,7 +75,7 @@
#if !LOG_DISABLED
String IDBDatabaseIdentifier::loggingString() const
{
- return makeString(m_databaseName, "@", m_origin.topOrigin.debugString(), ":", m_origin.clientOrigin.debugString());
+ return makeString(m_databaseName, "@", m_origin.topOrigin.debugString(), ":", m_origin.clientOrigin.debugString(), m_isTransient ? ", transient" : "");
}
#endif
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseIdentifier.h (264789 => 264790)
--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseIdentifier.h 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseIdentifier.h 2020-07-23 21:21:21 UTC (rev 264790)
@@ -44,7 +44,7 @@
{
}
- WEBCORE_EXPORT IDBDatabaseIdentifier(const String& databaseName, SecurityOriginData&& openingOrigin, SecurityOriginData&& mainFrameOrigin);
+ WEBCORE_EXPORT IDBDatabaseIdentifier(const String& databaseName, SecurityOriginData&& openingOrigin, SecurityOriginData&& mainFrameOrigin, bool isTransient = false);
IDBDatabaseIdentifier isolatedCopy() const;
@@ -57,8 +57,9 @@
{
unsigned nameHash = StringHash::hash(m_databaseName);
unsigned originHash = m_origin.hash();
+ unsigned transientHash = m_isTransient;
- unsigned hashCodes[2] = { nameHash, originHash };
+ unsigned hashCodes[3] = { nameHash, originHash, transientHash };
return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}
@@ -75,11 +76,12 @@
bool operator==(const IDBDatabaseIdentifier& other) const
{
- return other.m_databaseName == m_databaseName && other.m_origin == m_origin;
+ return other.m_databaseName == m_databaseName && other.m_origin == m_origin && other.m_isTransient == m_isTransient;
}
const String& databaseName() const { return m_databaseName; }
const ClientOrigin& origin() const { return m_origin; }
+ bool isTransient() const { return m_isTransient; }
String databaseDirectoryRelativeToRoot(const String& rootDirectory, const String& versionString="v1") const;
static String databaseDirectoryRelativeToRoot(const SecurityOriginData& topLevelOrigin, const SecurityOriginData& openingOrigin, const String& rootDirectory, const String& versionString);
@@ -96,6 +98,7 @@
private:
String m_databaseName;
ClientOrigin m_origin;
+ bool m_isTransient { false };
};
struct IDBDatabaseIdentifierHash {
@@ -113,7 +116,7 @@
template<class Encoder>
void IDBDatabaseIdentifier::encode(Encoder& encoder) const
{
- encoder << m_databaseName << m_origin;
+ encoder << m_databaseName << m_origin << m_isTransient;
}
template<class Decoder>
@@ -129,9 +132,15 @@
if (!origin)
return WTF::nullopt;
+ Optional<bool> isTransient;
+ decoder >> isTransient;
+ if (!isTransient)
+ return WTF::nullopt;
+
IDBDatabaseIdentifier identifier;
identifier.m_databaseName = WTFMove(*databaseName); // FIXME: When decoding from IPC, databaseName can be null, and the non-empty constructor asserts that this is not the case.
identifier.m_origin = WTFMove(*origin);
+ identifier.m_isTransient = *isTransient;
return identifier;
}
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBFactory.cpp (264789 => 264790)
--- trunk/Source/WebCore/Modules/indexeddb/IDBFactory.cpp 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBFactory.cpp 2020-07-23 21:21:21 UTC (rev 264790)
@@ -54,7 +54,7 @@
return true;
}
- if (!context.securityOrigin()->canAccessDatabase(context.topOrigin()))
+ if (!context.securityOrigin()->canAccessDatabase(nullptr))
return true;
return false;
@@ -91,7 +91,8 @@
return Exception { SecurityError, "IDBFactory.open() called in an invalid security context"_s };
ASSERT(context.securityOrigin());
- IDBDatabaseIdentifier databaseIdentifier(name, SecurityOriginData { context.securityOrigin()->data() }, SecurityOriginData { context.topOrigin().data() });
+ bool isTransient = !context.securityOrigin()->canAccessDatabase(&context.topOrigin());
+ IDBDatabaseIdentifier databaseIdentifier(name, SecurityOriginData { context.securityOrigin()->data() }, SecurityOriginData { context.topOrigin().data() }, isTransient);
if (!databaseIdentifier.isValid())
return Exception { TypeError, "IDBFactory.open() called with an invalid security origin"_s };
@@ -111,7 +112,8 @@
return Exception { SecurityError, "IDBFactory.deleteDatabase() called in an invalid security context"_s };
ASSERT(context.securityOrigin());
- IDBDatabaseIdentifier databaseIdentifier(name, SecurityOriginData { context.securityOrigin()->data() }, SecurityOriginData { context.topOrigin().data() });
+ bool isTransient = !context.securityOrigin()->canAccessDatabase(&context.topOrigin());
+ IDBDatabaseIdentifier databaseIdentifier(name, SecurityOriginData { context.securityOrigin()->data() }, SecurityOriginData { context.topOrigin().data() }, isTransient);
if (!databaseIdentifier.isValid())
return Exception { TypeError, "IDBFactory.deleteDatabase() called with an invalid security origin"_s };
Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp (264789 => 264790)
--- trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp 2020-07-23 21:21:21 UTC (rev 264790)
@@ -133,6 +133,10 @@
if (databaseDirectoryPath.isEmpty())
return makeUnique<MemoryIDBBackingStore>(m_sessionID, identifier);
+ ASSERT(!m_sessionID.isEphemeral());
+ if (identifier.isTransient())
+ return makeUnique<MemoryIDBBackingStore>(m_sessionID, identifier);
+
return makeUnique<SQLiteIDBBackingStore>(m_sessionID, identifier, databaseDirectoryPath);
}
Modified: trunk/Source/WebCore/Modules/webdatabase/DOMWindowWebDatabase.cpp (264789 => 264790)
--- trunk/Source/WebCore/Modules/webdatabase/DOMWindowWebDatabase.cpp 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebCore/Modules/webdatabase/DOMWindowWebDatabase.cpp 2020-07-23 21:21:21 UTC (rev 264790)
@@ -48,7 +48,7 @@
document->addConsoleMessage(MessageSource::Storage, MessageLevel::Warning, "Web SQL is deprecated. Please use IndexedDB instead.");
auto& securityOrigin = document->securityOrigin();
- if (!securityOrigin.canAccessDatabase(document->topOrigin()))
+ if (!securityOrigin.canAccessDatabase(&document->topOrigin()))
return Exception { SecurityError };
auto result = manager.openDatabase(*window.document(), name, version, displayName, estimatedSize, WTFMove(creationCallback));
if (result.hasException()) {
Modified: trunk/Source/WebCore/page/SecurityOrigin.h (264789 => 264790)
--- trunk/Source/WebCore/page/SecurityOrigin.h 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebCore/page/SecurityOrigin.h 2020-07-23 21:21:21 UTC (rev 264790)
@@ -148,7 +148,7 @@
WEBCORE_EXPORT String domainForCachePartition() const;
- bool canAccessDatabase(const SecurityOrigin& topOrigin) const { return canAccessStorage(&topOrigin); };
+ bool canAccessDatabase(const SecurityOrigin* topOrigin) const { return canAccessStorage(topOrigin); };
bool canAccessSessionStorage(const SecurityOrigin& topOrigin) const { return canAccessStorage(&topOrigin, AlwaysAllowFromThirdParty); }
bool canAccessLocalStorage(const SecurityOrigin* topOrigin) const { return canAccessStorage(topOrigin); };
bool canAccessPluginStorage(const SecurityOrigin& topOrigin) const { return canAccessStorage(&topOrigin); }
Modified: trunk/Source/WebKit/ChangeLog (264789 => 264790)
--- trunk/Source/WebKit/ChangeLog 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebKit/ChangeLog 2020-07-23 21:21:21 UTC (rev 264790)
@@ -1,3 +1,16 @@
+2020-07-23 Sihui Liu <[email protected]>
+
+ Allow IndexedDB in third-party frames
+ https://bugs.webkit.org/show_bug.cgi?id=214583
+ <rdar://problem/61278487>
+
+ Reviewed by Geoffrey Garen.
+
+ Do no append extra space to displayName if host is empty.
+
+ * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+ (WebKit::WebsiteDataStore::fetchDataAndApply):
+
2020-07-23 David Quesada <[email protected]>
Unable to present file upload picker after interactively dismissing a previously opened picker
Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp (264789 => 264790)
--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp 2020-07-23 21:21:21 UTC (rev 264790)
@@ -311,7 +311,8 @@
if (!allowsWebsiteDataRecordsForAllOrigins)
continue;
- displayName = makeString(entry.origin.protocol, " ", entry.origin.host);
+ String hostString = entry.origin.host.isEmpty() ? "" : makeString(" ", entry.origin.host);
+ displayName = makeString(entry.origin.protocol, hostString);
}
auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
Modified: trunk/Tools/ChangeLog (264789 => 264790)
--- trunk/Tools/ChangeLog 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Tools/ChangeLog 2020-07-23 21:21:21 UTC (rev 264790)
@@ -1,3 +1,15 @@
+2020-07-23 Sihui Liu <[email protected]>
+
+ Allow IndexedDB in third-party frames
+ https://bugs.webkit.org/show_bug.cgi?id=214583
+ <rdar://problem/61278487>
+
+ Reviewed by Geoffrey Garen.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/IndexedDBPersistence.mm:
+ (postResult):
+ (catch):
+
2020-07-23 Ryan Haddad <[email protected]>
[ews] Update bot watcher email address
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IndexedDBPersistence.mm (264789 => 264790)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IndexedDBPersistence.mm 2020-07-23 21:05:27 UTC (rev 264789)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IndexedDBPersistence.mm 2020-07-23 21:21:21 UTC (rev 264790)
@@ -27,11 +27,13 @@
#import "PlatformUtilities.h"
#import "Test.h"
+#import "TestURLSchemeHandler.h"
#import <WebKit/WebKit.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKUserContentControllerPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WKWebsiteDataStorePrivate.h>
#import <WebKit/_WKProcessPoolConfiguration.h>
#import <WebKit/_WKUserStyleSheet.h>
#import <wtf/RetainPtr.h>
@@ -179,3 +181,213 @@
}];
TestWebKitAPI::Util::run(&readyToContinue);
}
+
+static NSString *mainFrameString = @"<script> \
+ function postResult(event) { \
+ window.webkit.messageHandlers.testHandler.postMessage(event.data); \
+ } \
+ addEventListener('message', postResult, false); \
+ </script> \
+ <iframe src=''>";
+
+static const char* iframeBytes = R"TESTRESOURCE(
+<script>
+function postResult(result) {
+ if (window.parent != window.top) {
+ parent.postMessage(result, '*');
+ } else {
+ window.webkit.messageHandlers.testHandler.postMessage(result);
+ }
+}
+
+try {
+ var request = window.indexedDB.open('IndexedDBThirdPartyFrameHasAccess');
+ var db = null;
+ request._onupgradeneeded_ = function(event) {
+ db = event.target.result;
+ var objectStore = db.createObjectStore('TestObjectStore');
+ var putRequest = objectStore.put('TestValue', 'TestKey');
+ putRequest._onsuccess_ = function(event) {
+ postResult('database is created - put item success');
+ }
+ putRequest._onerror_ = function(event) {
+ postResult('database is created - put item error: ' + event.target.error.name + ' - ' + event.target.error.message);
+ }
+ }
+ request._onsuccess_ = function(event) {
+ if (db)
+ return;
+ db = event.target.result;
+ var objectStore = db.transaction(['TestObjectStore']).objectStore('TestObjectStore');
+ var getRequest = objectStore.get('TestKey');
+ getRequest._onsuccess_ = function(event) {
+ postResult('database exists - get item success: ' + event.target.result);
+ }
+ getRequest._onerror_ = function(event) {
+ postResult('database exists - get item error: ' + event.target.error.name + ' - ' + event.target.error.message);
+ }
+ }
+ request._onerror_ = function(event) {
+ if (!db) {
+ postResult('database error: ' + event.target.error.name + ' - ' + event.target.error.message);
+ }
+ }
+} catch(err) {
+ postResult('database error: ' + err.name + ' - ' + err.message);
+}
+</script>
+)TESTRESOURCE";
+
+static void loadTestPageInWebView(WKWebView *webView, NSString *expectedResult)
+{
+ [webView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"http://webkit.org"]];
+ TestWebKitAPI::Util::run(&receivedScriptMessage);
+ receivedScriptMessage = false;
+ EXPECT_WK_STREQ(expectedResult, (NSString *)[lastScriptMessage body]);
+}
+
+TEST(IndexedDB, IndexedDBThirdPartyFrameHasAccess)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto handler = adoptNS([[IndexedDBMessageHandler alloc] init]);
+ [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+ auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
+ [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
+ auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
+ [task didReceiveResponse:response.get()];
+ [task didReceiveData:[NSData dataWithBytes:iframeBytes length:strlen(iframeBytes)]];
+ [task didFinish];
+ }];
+ [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"iframe"];
+
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ loadTestPageInWebView(webView.get(), @"database is created - put item success");
+
+ auto secondWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ loadTestPageInWebView(secondWebView.get(), @"database exists - get item success: TestValue");
+
+ webView = nil;
+ secondWebView = nil;
+ [configuration.get().processPool _terminateNetworkProcess];
+
+ // Third-party IDB storage is stored in the memory of network process.
+ auto thirdWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ loadTestPageInWebView(thirdWebView.get(), @"database is created - put item success");
+}
+
+TEST(IndexedDB, IndexedDBThirdPartyDataRemoval)
+{
+ auto websiteDataTypes = adoptNS([[NSSet alloc] initWithArray:@[WKWebsiteDataTypeIndexedDBDatabases]]);
+ readyToContinue = false;
+ [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes.get() modifiedSince:[NSDate distantPast] completionHandler:^() {
+ readyToContinue = true;
+ }];
+ TestWebKitAPI::Util::run(&readyToContinue);
+
+ [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto handler = adoptNS([[IndexedDBMessageHandler alloc] init]);
+ [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+ auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
+ [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
+ auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
+ [task didReceiveResponse:response.get()];
+ [task didReceiveData:[NSData dataWithBytes:iframeBytes length:strlen(iframeBytes)]];
+ [task didFinish];
+ }];
+ [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"iframe"];
+
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ loadTestPageInWebView(webView.get(), @"database is created - put item success");
+
+ auto secondWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ [secondWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"iframe://"]]];
+ TestWebKitAPI::Util::run(&receivedScriptMessage);
+ receivedScriptMessage = false;
+ EXPECT_WK_STREQ( @"database is created - put item success", (NSString *)[lastScriptMessage body]);
+
+ readyToContinue = false;
+ [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:websiteDataTypes.get() completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
+ EXPECT_EQ(1u, dataRecords.count);
+ EXPECT_WK_STREQ("iframe", [[dataRecords firstObject] displayName]);
+ [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes.get() forDataRecords:dataRecords completionHandler:^() {
+ readyToContinue = true;
+ }];
+ }];
+ TestWebKitAPI::Util::run(&readyToContinue);
+
+ auto thirdWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ loadTestPageInWebView(thirdWebView.get(), @"database is created - put item success");
+}
+
+static const char* workerBytes = R"TESTRESOURCE(
+try {
+ var request = indexedDB.open('IndexedDBThirdPartyWorkerHasAccess');
+ var db = null;
+ request._onupgradeneeded_ = function(event) {
+ db = event.target.result;
+ self.postMessage('database is created');
+ }
+ request._onsuccess_ = function(event) {
+ if (db)
+ return;
+ self.postMessage('database exists');
+ }
+ request._onerror_ = function(event) {
+ if (!db) {
+ self.postMessage('database error: ' + event.target.error.name + ' - ' + event.target.error.message);
+ }
+ }
+} catch(err) {
+ self.postMessage('database error: ' + err.name + ' - ' + err.message);
+}
+)TESTRESOURCE";
+
+static const char* workerFrameBytes = R"TESTRESOURCE(
+<script>
+ var worker = new Worker('worker.js');
+ worker._onmessage_ = function(event) {
+ parent.postMessage(event.data, '*');
+ };
+</script>
+)TESTRESOURCE";
+
+TEST(IndexedDB, IndexedDBThirdPartyWorkerHasAccess)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto handler = adoptNS([[IndexedDBMessageHandler alloc] init]);
+ [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+ auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
+ [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
+ RetainPtr<NSURLResponse> response;
+ RetainPtr<NSData> data;
+ NSURL *requestURL = task.request.URL;
+ if ([requestURL.absoluteString isEqualToString:@"iframe://"]) {
+ response = adoptNS([[NSURLResponse alloc] initWithURL:requestURL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
+ data = "" dataWithBytes:workerFrameBytes length:strlen(workerFrameBytes)];
+ } else {
+ EXPECT_WK_STREQ("iframe://worker.js", requestURL.absoluteString);
+ response = adoptNS([[NSURLResponse alloc] initWithURL:requestURL MIMEType:@"text/_javascript_" expectedContentLength:0 textEncodingName:nil]);
+ data = "" dataWithBytes:workerBytes length:strlen(workerBytes)];
+ }
+ [task didReceiveResponse:response.get()];
+ [task didReceiveData:data.get()];
+ [task didFinish];
+ }];
+ [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"iframe"];
+
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ loadTestPageInWebView(webView.get(), @"database is created");
+
+ auto secondWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ loadTestPageInWebView(webView.get(), @"database exists");
+
+ webView = nil;
+ secondWebView = nil;
+ [configuration.get().processPool _terminateNetworkProcess];
+
+ auto thirdWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ loadTestPageInWebView(thirdWebView.get(), @"database is created");
+}
+