Changeset 260841 in webkit
- Timestamp:
- Apr 28, 2020 12:40:49 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r260840 r260841 1 2020-04-28 Kate Cheney <katherine_cheney@apple.com> 2 3 Create a mechanism to add missing ITP Database tables when the schema is updated 4 https://bugs.webkit.org/show_bug.cgi?id=211004 5 <rdar://problem/62261187> 6 7 Reviewed by John Wilander. 8 9 This patch updates the ITP database to better handle added tables to 10 the schema. Currently the database store deletes and re-creates the 11 database when any schema change is encountered. This is simple but 12 would result in ITP data loss during schema updates, so this patch 13 searches the schema for missing tables and adds any it finds. 14 15 * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp: 16 (WebKit::createTableQueries): 17 Convert the tables array to a mapping of table names to their 18 respective CREATE TABLE queries so we can add missing tables on the 19 fly. 20 (WebKit::ResourceLoadStatisticsDatabaseStore::ResourceLoadStatisticsDatabaseStore): 21 (WebKit::ResourceLoadStatisticsDatabaseStore::openITPDatabase): 22 Remove call to createSchema() from the constructor. It makes more 23 sense to base this on whether the file is new as opposed to whether 24 one table exists. 25 (WebKit::ResourceLoadStatisticsDatabaseStore::checkForMissingTablesInSchema): 26 (WebKit::ResourceLoadStatisticsDatabaseStore::migrateDataToNewTablesIfNecessary): 27 (WebKit::ResourceLoadStatisticsDatabaseStore::addMissingTablesIfNecessary): 28 Checks for missing tables and adds them using a best-effort approach. 29 Call createUniqueIndices() to call all CREATE UNIQUE INDEX queries, 30 even though we may not need them all. It is much simpler than to 31 associate each query with its table, and it doesn't hurt to call 32 again. 33 34 (WebKit::ResourceLoadStatisticsDatabaseStore::openAndUpdateSchemaIfNecessary): 35 Add missing tables instead of deleting the old database file. Changed 36 the function name to reflect this. Deleted a FIXME which this patch 37 addresses but added a new FIXME for migrating data when adding new 38 columns, which this patch does not address. 39 (WebKit::ResourceLoadStatisticsDatabaseStore::isCorrectTableSchema): Deleted. 40 (WebKit::ResourceLoadStatisticsDatabaseStore::openAndDropOldDatabaseIfNecessary): Deleted. 41 * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h: 42 * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp: 43 (WebKit::WebResourceLoadStatisticsStore::statisticsDatabaseHasAllTables): 44 * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h: 45 * NetworkProcess/NetworkProcess.cpp: 46 (WebKit::NetworkProcess::statisticsDatabaseHasAllTables): 47 * NetworkProcess/NetworkProcess.h: 48 * NetworkProcess/NetworkProcess.messages.in: 49 * UIProcess/API/Cocoa/WKWebsiteDataStore.mm: 50 (-[WKWebsiteDataStore _statisticsDatabaseHasAllTables:]): 51 * UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h: 52 * UIProcess/Network/NetworkProcessProxy.cpp: 53 (WebKit::NetworkProcessProxy::statisticsDatabaseHasAllTables): 54 * UIProcess/Network/NetworkProcessProxy.h: 55 * UIProcess/WebsiteData/WebsiteDataStore.cpp: 56 (WebKit::WebsiteDataStore::statisticsDatabaseHasAllTables): 57 * UIProcess/WebsiteData/WebsiteDataStore.h: 58 Added an SPI call to test that the database schema includes all 59 tables. This tests the database is not dropped when a new 60 table is added upon opening the database. 61 1 62 2020-04-28 Per Arne Vollan <pvollan@apple.com> 2 63 -
trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp
r260668 r260841 147 147 constexpr auto removeAllDataQuery = "DELETE FROM ObservedDomains WHERE domainID = ?"_s; 148 148 149 const char* tables[] = {150 "ObservedDomains",151 "TopLevelDomains",152 "StorageAccessUnderTopFrameDomains",153 "TopFrameUniqueRedirectsTo",154 "TopFrameUniqueRedirectsToSinceSameSiteStrictEnforcement",155 "TopFrameUniqueRedirectsFrom",156 "TopFrameLinkDecorationsFrom",157 "TopFrameLoadedThirdPartyScripts",158 "SubframeUnderTopFrameDomains",159 "SubresourceUnderTopFrameDomains",160 "SubresourceUniqueRedirectsTo",161 "SubresourceUniqueRedirectsFrom"162 };163 164 // CREATE TABLE Queries165 149 constexpr auto createObservedDomain = "CREATE TABLE ObservedDomains (" 166 150 "domainID INTEGER PRIMARY KEY, registrableDomain TEXT NOT NULL UNIQUE ON CONFLICT FAIL, lastSeen REAL NOT NULL, " … … 267 251 return schema.contains("REFERENCES TopLevelDomains"); 268 252 } 253 254 static const HashMap<String, String>& createTableQueries() 255 { 256 static auto createTableQueries = makeNeverDestroyed(HashMap<String, String> { 257 { "ObservedDomains"_s, createObservedDomain}, 258 { "TopLevelDomains"_s, createTopLevelDomains}, 259 { "StorageAccessUnderTopFrameDomains"_s, createStorageAccessUnderTopFrameDomains}, 260 { "TopFrameUniqueRedirectsTo"_s, createTopFrameUniqueRedirectsTo}, 261 { "TopFrameUniqueRedirectsToSinceSameSiteStrictEnforcement"_s, createTopFrameUniqueRedirectsToSinceSameSiteStrictEnforcement}, 262 { "TopFrameUniqueRedirectsFrom"_s, createTopFrameUniqueRedirectsFrom}, 263 { "TopFrameLinkDecorationsFrom"_s, createTopFrameLinkDecorationsFrom}, 264 { "TopFrameLoadedThirdPartyScripts"_s, createTopFrameLoadedThirdPartyScripts}, 265 { "SubframeUnderTopFrameDomains"_s, createSubframeUnderTopFrameDomains}, 266 { "SubresourceUnderTopFrameDomains"_s, createSubresourceUnderTopFrameDomains}, 267 { "SubresourceUniqueRedirectsTo"_s, createSubresourceUniqueRedirectsTo}, 268 { "SubresourceUniqueRedirectsFrom"_s, createSubresourceUniqueRedirectsFrom} 269 }); 270 271 return createTableQueries; 272 } 273 269 274 270 275 ResourceLoadStatisticsDatabaseStore::ResourceLoadStatisticsDatabaseStore(WebResourceLoadStatisticsStore& store, WorkQueue& workQueue, ShouldIncludeLocalhost shouldIncludeLocalhost, const String& storageDirectoryPath, PAL::SessionID sessionID) … … 313 318 ASSERT(!RunLoop::isMain()); 314 319 315 openAnd DropOldDatabaseIfNecessary();320 openAndUpdateSchemaIfNecessary(); 316 321 enableForeignKeys(); 317 322 318 323 // Since we are using a workerQueue, the sequential dispatch blocks may be called by different threads. 319 324 m_database.disableThreadingChecks(); 320 321 if (!m_database.tableExists("ObservedDomains"_s)) { 325 326 if (!m_database.turnOnIncrementalAutoVacuum()) 327 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::turnOnIncrementalAutoVacuum failed, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg()); 328 329 if (!prepareStatements()) { 330 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::prepareStatements failed, error message: %" PUBLIC_LOG_STRING ", database path: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg(), m_storageDirectoryPath.utf8().data()); 331 ASSERT_NOT_REACHED(); 332 return; 333 } 334 335 workQueue.dispatchAfter(5_s, [weakThis = makeWeakPtr(*this)] { 336 if (weakThis) 337 weakThis->calculateAndSubmitTelemetry(); 338 }); 339 } 340 341 void ResourceLoadStatisticsDatabaseStore::openITPDatabase() 342 { 343 if (!FileSystem::fileExists(m_storageDirectoryPath)) 344 m_isNewResourceLoadStatisticsDatabaseFile = true; 345 else 346 m_isNewResourceLoadStatisticsDatabaseFile = false; 347 348 if (!m_database.open(m_storageDirectoryPath)) { 349 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::open failed, error message: %" PUBLIC_LOG_STRING ", database path: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg(), m_storageDirectoryPath.utf8().data()); 350 ASSERT_NOT_REACHED(); 351 } 352 353 if (m_isNewResourceLoadStatisticsDatabaseFile) { 322 354 if (!createSchema()) { 323 355 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::createSchema failed, error message: %" PUBLIC_LOG_STRING ", database path: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg(), m_storageDirectoryPath.utf8().data()); … … 326 358 } 327 359 } 328 329 if (!m_database.turnOnIncrementalAutoVacuum())330 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::turnOnIncrementalAutoVacuum failed, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg());331 332 if (!prepareStatements()) {333 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::prepareStatements failed, error message: %" PUBLIC_LOG_STRING ", database path: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg(), m_storageDirectoryPath.utf8().data());334 ASSERT_NOT_REACHED();335 return;336 }337 338 workQueue.dispatchAfter(5_s, [weakThis = makeWeakPtr(*this)] {339 if (weakThis)340 weakThis->calculateAndSubmitTelemetry();341 });342 }343 344 void ResourceLoadStatisticsDatabaseStore::openITPDatabase()345 {346 if (!FileSystem::fileExists(m_storageDirectoryPath))347 m_isNewResourceLoadStatisticsDatabaseFile = true;348 else349 m_isNewResourceLoadStatisticsDatabaseFile = false;350 351 if (!m_database.open(m_storageDirectoryPath)) {352 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::open failed, error message: %" PUBLIC_LOG_STRING ", database path: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg(), m_storageDirectoryPath.utf8().data());353 ASSERT_NOT_REACHED();354 }355 360 } 356 361 … … 361 366 } 362 367 363 bool ResourceLoadStatisticsDatabaseStore::isCorrectTableSchema() 364 { 368 Optional<Vector<String>> ResourceLoadStatisticsDatabaseStore::checkForMissingTablesInSchema() 369 { 370 Vector<String> missingTables; 365 371 SQLiteStatement statement(m_database, "SELECT 1 from sqlite_master WHERE type='table' and tbl_name=?"); 366 372 if (statement.prepare() != SQLITE_OK) { 367 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::isCorrectTableSchema failed to prepare, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg()); 368 return false; 369 } 370 371 bool hasAllTables = true; 372 for (auto table : tables) { 373 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::checkForMissingTablesInSchema failed to prepare, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg()); 374 return WTF::nullopt; 375 } 376 377 for (auto& table : createTableQueries().keys()) { 373 378 if (statement.bindText(1, table) != SQLITE_OK) { 374 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore:: isCorrectTableSchema failed to bind, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg());375 return false;379 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::checkForMissingTablesInSchema failed to bind, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg()); 380 return WTF::nullopt; 376 381 } 377 382 if (statement.step() != SQLITE_ROW) { 378 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore:: isCorrectTableSchema schema is missing table: %s", this, table);379 hasAllTables = false;383 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::checkForMissingTablesInSchema schema is missing table: %s", this, table.ascii().data()); 384 missingTables.append(String(table)); 380 385 } 381 386 resetStatement(statement); 382 387 } 383 return hasAllTables; 388 if (missingTables.isEmpty()) 389 return WTF::nullopt; 390 391 return missingTables; 384 392 } 385 393 … … 425 433 transaction.begin(); 426 434 427 for (auto& table : tables) {435 for (auto& table : createTableQueries().keys()) { 428 436 auto query = makeString("ALTER TABLE ", table, " RENAME TO _", table); 429 437 SQLiteStatement alterTable(m_database, query); … … 441 449 } 442 450 443 for (auto& table : tables) {451 for (auto& table : createTableQueries().keys()) { 444 452 auto query = makeString("INSERT INTO ", table, " SELECT * FROM _", table); 445 453 SQLiteStatement migrateTableData(m_database, query); … … 468 476 } 469 477 470 void ResourceLoadStatisticsDatabaseStore::openAndDropOldDatabaseIfNecessary() 478 void ResourceLoadStatisticsDatabaseStore::addMissingTablesIfNecessary() 479 { 480 auto missingTables = checkForMissingTablesInSchema(); 481 if (!missingTables) 482 return; 483 484 for (auto& table : *missingTables) { 485 auto createTableQuery = createTableQueries().get(table); 486 if (!m_database.executeCommand(createTableQuery)) 487 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::addMissingTables failed to execute, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg()); 488 } 489 490 if (!createUniqueIndices()) { 491 RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::addMissingTables failed to create unique indices, error message: %{private}s", this, m_database.lastErrorMsg()); 492 ASSERT_NOT_REACHED(); 493 return; 494 } 495 } 496 497 void ResourceLoadStatisticsDatabaseStore::openAndUpdateSchemaIfNecessary() 471 498 { 472 499 openITPDatabase(); 473 474 if (!isCorrectTableSchema()) { 475 m_database.close(); 476 // FIXME: Migrate existing data to new database file instead of deleting it (204482). 477 FileSystem::deleteFile(m_storageDirectoryPath); 478 openITPDatabase(); 479 return; 480 } 500 addMissingTablesIfNecessary(); 481 501 482 502 String currentSchema; … … 504 524 ASSERT(!currentSchema.isEmpty()); 505 525 506 // If the schema in the ResourceLoadStatistics directory is not the current schema, delete the database file. 526 // If the ObservedDomains schema in the ResourceLoadStatistics directory is not the current schema, delete the database file. 527 // FIXME: Migrate old ObservedDomains data to new table schema. 507 528 if (currentSchema != ObservedDomainsTableSchemaV1() && currentSchema != ObservedDomainsTableSchemaV1Alternate()) { 508 529 m_database.close(); -
trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h
r260668 r260841 141 141 void removeDataForDomain(const RegistrableDomain&) override; 142 142 bool domainIDExistsInDatabase(int); 143 Optional<Vector<String>> checkForMissingTablesInSchema(); 143 144 144 145 private: 145 146 void openITPDatabase(); 146 bool isCorrectTableSchema();147 void addMissingTablesIfNecessary(); 147 148 void enableForeignKeys(); 148 149 bool isMigrationNecessary(); … … 150 151 bool hasStorageAccess(const TopFrameDomain&, const SubFrameDomain&) const; 151 152 Vector<WebResourceLoadStatisticsStore::ThirdPartyDataForSpecificFirstParty> getThirdPartyDataForSpecificFirstPartyDomains(unsigned, const RegistrableDomain&) const; 152 void openAnd DropOldDatabaseIfNecessary();153 void openAndUpdateSchemaIfNecessary(); 153 154 String getDomainStringFromDomainID(unsigned) const; 154 155 String getSubStatisticStatement(const String&) const; -
trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp
r260791 r260841 323 323 } 324 324 325 void WebResourceLoadStatisticsStore::statisticsDatabaseHasAllTables(CompletionHandler<void(bool)>&& completionHandler) 326 { 327 ASSERT(RunLoop::isMain()); 328 329 postTask([this, completionHandler = WTFMove(completionHandler)]() mutable { 330 if (!m_statisticsStore || !is<ResourceLoadStatisticsDatabaseStore>(*m_statisticsStore)) { 331 completionHandler(false); 332 ASSERT_NOT_REACHED(); 333 return; 334 } 335 auto missingTables = downcast<ResourceLoadStatisticsDatabaseStore>(*m_statisticsStore).checkForMissingTablesInSchema(); 336 postTaskReply([hasAllTables = missingTables ? false : true, completionHandler = WTFMove(completionHandler)] () mutable { 337 completionHandler(hasAllTables); 338 }); 339 }); 340 } 341 325 342 void WebResourceLoadStatisticsStore::resourceLoadStatisticsUpdated(Vector<ResourceLoadStatistics>&& statistics) 326 343 { -
trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h
r260791 r260841 250 250 void scheduleCookieBlockingUpdateForDomains(const Vector<RegistrableDomain>&, CompletionHandler<void()>&&); 251 251 void scheduleStatisticsAndDataRecordsProcessing(CompletionHandler<void()>&&); 252 void statisticsDatabaseHasAllTables(CompletionHandler<void(bool)>&&); 252 253 void submitTelemetry(CompletionHandler<void()>&&); 253 254 void scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics, CompletionHandler<void()>&&); -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp
r260791 r260841 829 829 } 830 830 831 void NetworkProcess::statisticsDatabaseHasAllTables(PAL::SessionID sessionID, CompletionHandler<void(bool)>&& completionHandler) 832 { 833 if (auto* networkSession = this->networkSession(sessionID)) { 834 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics()) 835 resourceLoadStatistics->statisticsDatabaseHasAllTables(WTFMove(completionHandler)); 836 else 837 completionHandler(false); 838 } else { 839 ASSERT_NOT_REACHED(); 840 completionHandler(false); 841 } 842 } 843 831 844 void NetworkProcess::setNotifyPagesWhenDataRecordsWereScanned(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler) 832 845 { -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.h
r260668 r260841 238 238 void scheduleCookieBlockingUpdate(PAL::SessionID, CompletionHandler<void()>&&); 239 239 void scheduleStatisticsAndDataRecordsProcessing(PAL::SessionID, CompletionHandler<void()>&&); 240 void statisticsDatabaseHasAllTables(PAL::SessionID, CompletionHandler<void(bool)>&&); 240 241 void submitTelemetry(PAL::SessionID, CompletionHandler<void()>&&); 241 242 void setCacheMaxAgeCapForPrevalentResources(PAL::SessionID, Seconds, CompletionHandler<void()>&&); -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
r260668 r260841 112 112 ScheduleCookieBlockingUpdate(PAL::SessionID sessionID) -> () Async 113 113 ScheduleStatisticsAndDataRecordsProcessing(PAL::SessionID sessionID) -> () Async 114 StatisticsDatabaseHasAllTables(PAL::SessionID sessionID) -> (bool hasAllTables) Async 114 115 SubmitTelemetry(PAL::SessionID sessionID) -> () Async 115 116 SetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds) -> () Async -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
r260485 r260841 563 563 } 564 564 565 - (void)_statisticsDatabaseHasAllTables:(void (^)(BOOL))completionHandler 566 { 567 #if ENABLE(RESOURCE_LOAD_STATISTICS) 568 _websiteDataStore->statisticsDatabaseHasAllTables([completionHandler = makeBlockPtr(completionHandler)](bool hasAllTables) { 569 completionHandler(hasAllTables); 570 }); 571 #else 572 completionHandler(NO); 573 #endif 574 } 575 565 576 - (void)_processStatisticsAndDataRecords:(void (^)(void))completionHandler 566 577 { -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h
r260334 r260841 78 78 - (void)_isRegisteredAsSubresourceUnderFirstParty:(NSURL *)firstPartyURL thirdParty:(NSURL *)thirdPartyURL completionHandler:(void (^)(BOOL))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 79 79 - (void)_setThirdPartyCookieBlockingMode:(BOOL)enabled onlyOnSitesWithoutUserInteraction:(BOOL)onlyOnSitesWithoutUserInteraction completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 80 - (void)_statisticsDatabaseHasAllTables:(void (^)(BOOL))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 80 81 - (void)_processStatisticsAndDataRecords:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(10.15), ios(13.0)); 81 82 - (void)_appBoundDomains:(void (^)(NSArray<NSString *> *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); -
trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
r260668 r260841 630 630 } 631 631 632 void NetworkProcessProxy::statisticsDatabaseHasAllTables(PAL::SessionID sessionID, CompletionHandler<void(bool)>&& completionHandler) 633 { 634 if (!canSendMessage()) { 635 completionHandler(false); 636 return; 637 } 638 639 sendWithAsyncReply(Messages::NetworkProcess::StatisticsDatabaseHasAllTables(sessionID), WTFMove(completionHandler)); 640 } 641 632 642 void NetworkProcessProxy::logUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void()>&& completionHandler) 633 643 { -
trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
r260668 r260841 132 132 void setLastSeen(PAL::SessionID, const RegistrableDomain&, Seconds, CompletionHandler<void()>&&); 133 133 void domainIDExistsInDatabase(PAL::SessionID, int domainID, CompletionHandler<void(bool)>&&); 134 void statisticsDatabaseHasAllTables(PAL::SessionID, CompletionHandler<void(bool)>&&); 134 135 void mergeStatisticForTesting(PAL::SessionID, const RegistrableDomain&, const TopFrameDomain& topFrameDomain1, const TopFrameDomain& topFrameDomain2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&&); 135 136 void setAgeCapForClientSideCookies(PAL::SessionID, Optional<Seconds>, CompletionHandler<void()>&&); -
trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
r260668 r260841 1584 1584 } 1585 1585 1586 void WebsiteDataStore::statisticsDatabaseHasAllTables(CompletionHandler<void(bool)>&& completionHandler) 1587 { 1588 ASSERT(RunLoop::isMain()); 1589 1590 for (auto& processPool : processPools()) { 1591 if (auto* process = processPool->networkProcess()) { 1592 process->statisticsDatabaseHasAllTables(m_sessionID, WTFMove(completionHandler)); 1593 return; 1594 } 1595 } 1596 1597 completionHandler(false); 1598 } 1599 1586 1600 void WebsiteDataStore::setLastSeen(const URL& url, Seconds seconds, CompletionHandler<void()>&& completionHandler) 1587 1601 { -
trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
r260668 r260841 169 169 void setLastSeen(const URL&, Seconds, CompletionHandler<void()>&&); 170 170 void domainIDExistsInDatabase(int domainID, CompletionHandler<void(bool)>&&); 171 void statisticsDatabaseHasAllTables(CompletionHandler<void(bool)>&&); 171 172 void mergeStatisticForTesting(const URL&, const URL& topFrameUrl1, const URL& topFrameUrl2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&&); 172 173 void setNotifyPagesWhenDataRecordsWereScanned(bool, CompletionHandler<void()>&&); -
trunk/Tools/ChangeLog
r260840 r260841 1 2020-04-28 Kate Cheney <katherine_cheney@apple.com> 2 3 Create a mechanism to add missing ITP Database tables when the schema is updated 4 https://bugs.webkit.org/show_bug.cgi?id=211004 5 <rdar://problem/62261187> 6 7 Reviewed by John Wilander. 8 9 Add test case which copies a database schema with a missing table into 10 the ITP database file, then ensures the pre-seeded data is 11 migrated over and that the schema now has all tables (including the 12 previously missing one). 13 14 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: 15 * TestWebKitAPI/Tests/WebKitCocoa/ResourceLoadStatistics.mm: 16 (TEST): 17 * TestWebKitAPI/Tests/WebKitCocoa/missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db: Added. 18 * TestWebKitAPI/Tests/WebKitCocoa/missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db-shm: Added. 19 * TestWebKitAPI/Tests/WebKitCocoa/missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db-wal: Added. 20 1 21 2020-04-28 Per Arne Vollan <pvollan@apple.com> 2 22 -
trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
r260769 r260841 257 257 4909EE3A2D09480C88982D56 /* Markable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC79F168BE454E579E417B05 /* Markable.cpp */; }; 258 258 4971B1182451F29A0096994D /* incorrectCreateTableSchema.db in Copy Resources */ = {isa = PBXBuildFile; fileRef = 4971B1172451F2780096994D /* incorrectCreateTableSchema.db */; }; 259 4971B1202453A88C0096994D /* missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db in Copy Resources */ = {isa = PBXBuildFile; fileRef = 4971B11F2453A87F0096994D /* missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db */; }; 259 260 49897D6C241FE9E400ECF153 /* in-app-browser-privacy-local-file.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 49D7FBA7241FDDDA00AB67FA /* in-app-browser-privacy-local-file.html */; }; 260 261 49AEEF6D2407359D00C87E4C /* InAppBrowserPrivacy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49AEEF6B2407358600C87E4C /* InAppBrowserPrivacy.mm */; }; … … 1449 1450 E1220DCA155B28AA0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html in Copy Resources */, 1450 1451 517E7E04151119C100D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.html in Copy Resources */, 1452 4971B1202453A88C0096994D /* missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db in Copy Resources */, 1451 1453 51CD1C721B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html in Copy Resources */, 1452 1454 7A1458FC1AD5C07000E06772 /* mouse-button-listener.html in Copy Resources */, … … 1876 1878 46FACF7323E883EE00A9EBC6 /* beforeunload-slow.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "beforeunload-slow.html"; sourceTree = "<group>"; }; 1877 1879 4971B1172451F2780096994D /* incorrectCreateTableSchema.db */ = {isa = PBXFileReference; lastKnownFileType = file; path = incorrectCreateTableSchema.db; sourceTree = "<group>"; }; 1880 4971B11F2453A87F0096994D /* missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db */ = {isa = PBXFileReference; lastKnownFileType = file; name = missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db; path = Tests/WebKitCocoa/missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db; sourceTree = SOURCE_ROOT; }; 1878 1881 49AEEF682407276F00C87E4C /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 1879 1882 49AEEF6B2407358600C87E4C /* InAppBrowserPrivacy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InAppBrowserPrivacy.mm; sourceTree = "<group>"; }; … … 4076 4079 CD8394DE232AF15E00149495 /* media-loading.html */, 4077 4080 CDC9442B1EF1FBD20059C3C4 /* mediastreamtrack-detached.html */, 4081 4971B11F2453A87F0096994D /* missingTopFrameUniqueRedirectSameSiteStrictTableSchema.db */, 4078 4082 51CD1C711B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html */, 4079 4083 7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */, -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ResourceLoadStatistics.mm
r260594 r260841 1496 1496 TestWebKitAPI::Util::run(&doneFlag); 1497 1497 } 1498 1499 TEST(ResourceLoadStatistics, MigrateDataFromMissingTopFrameUniqueRedirectSameSiteStrictTableSchema) 1500 { 1501 auto *sharedProcessPool = [WKProcessPool _sharedProcessPool]; 1502 1503 auto defaultFileManager = [NSFileManager defaultManager]; 1504 auto *dataStore = [WKWebsiteDataStore defaultDataStore]; 1505 NSURL *itpRootURL = [[dataStore _configuration] _resourceLoadStatisticsDirectory]; 1506 NSURL *fileURL = [itpRootURL URLByAppendingPathComponent:@"observations.db"]; 1507 [defaultFileManager removeItemAtPath:itpRootURL.path error:nil]; 1508 EXPECT_FALSE([defaultFileManager fileExistsAtPath:itpRootURL.path]); 1509 1510 // Load an incorrect database schema with pre-seeded ITP data. 1511 [defaultFileManager createDirectoryAtURL:itpRootURL withIntermediateDirectories:YES attributes:nil error:nil]; 1512 NSURL *newFileURL = [[NSBundle mainBundle] URLForResource:@"missingTopFrameUniqueRedirectSameSiteStrictTableSchema" withExtension:@"db" subdirectory:@"TestWebKitAPI.resources"]; 1513 EXPECT_TRUE([defaultFileManager fileExistsAtPath:newFileURL.path]); 1514 [defaultFileManager copyItemAtPath:newFileURL.path toPath:fileURL.path error:nil]; 1515 EXPECT_TRUE([defaultFileManager fileExistsAtPath:fileURL.path]); 1516 1517 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 1518 [configuration setProcessPool: sharedProcessPool]; 1519 configuration.get().websiteDataStore = dataStore; 1520 1521 // We need an active NetworkProcess to perform ResourceLoadStatistics operations. 1522 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]); 1523 [dataStore _setResourceLoadStatisticsEnabled:YES]; 1524 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]]; 1525 1526 static bool doneFlag; 1527 [dataStore _setUseITPDatabase:true completionHandler: ^(void) { 1528 doneFlag = true; 1529 }]; 1530 1531 TestWebKitAPI::Util::run(&doneFlag); 1532 1533 // Since the database should not be deleted, the pre-seeded data should 1534 // still be there after initializing ITP. 1535 doneFlag = false; 1536 [dataStore _isRegisteredAsSubresourceUnderFirstParty:[NSURL URLWithString:@"http://apple.com"] thirdParty:[NSURL URLWithString:@"http://webkit.org"] completionHandler: ^(BOOL isRegistered) { 1537 EXPECT_TRUE(isRegistered); 1538 doneFlag = true; 1539 }]; 1540 1541 TestWebKitAPI::Util::run(&doneFlag); 1542 1543 // Check to make sure all tables are accounted for. 1544 doneFlag = false; 1545 [dataStore _statisticsDatabaseHasAllTables:^(BOOL hasAllTables) { 1546 EXPECT_TRUE(hasAllTables); 1547 doneFlag = true; 1548 }]; 1549 1550 TestWebKitAPI::Util::run(&doneFlag); 1551 }
Note: See TracChangeset
for help on using the changeset viewer.