Changeset 242122 in webkit
- Timestamp:
- Feb 26, 2019, 8:40:48 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/Source/WebKit/ChangeLog ¶
r242113 r242122 1 2019-02-26 Alex Christensen <achristensen@webkit.org> 2 3 Move ephemeral local storage from WebProcess to UIProcess 4 https://bugs.webkit.org/show_bug.cgi?id=195074 5 <rdar://problem/47937975> 6 7 Reviewed by Geoff Garen. 8 9 Before PSON, a page could navigate to another domain that navigates back and still have its local storage. 10 Since PSON makes it unreliable to retain the state in the WebProcess, move it to the process with the rest of the local storage. 11 If it's ephemeral, we obviously can't use the SQLite on-disk storage implementation, so use the same WebCore::StorageMap we used to in the WebProcess. 12 13 * UIProcess/WebStorage/StorageManager.cpp: 14 (WebKit::StorageManager::LocalStorageNamespace::LocalStorageNamespace): 15 (WebKit::StorageManager::StorageManager): 16 (WebKit::StorageManager::createLocalStorageMap): 17 (WebKit::StorageManager::createTransientLocalStorageMap): 18 (WebKit::StorageManager::createSessionStorageMap): 19 (WebKit::StorageManager::destroyStorageMap): 20 (WebKit::StorageManager::getValues): 21 (WebKit::StorageManager::setItem): 22 (WebKit::StorageManager::removeItem): 23 (WebKit::StorageManager::clear): 24 * UIProcess/WebStorage/StorageManager.h: 25 * UIProcess/WebStorage/StorageManager.messages.in: 26 * UIProcess/WebsiteData/WebsiteDataStore.cpp: 27 (WebKit::WebsiteDataStore::WebsiteDataStore): 28 * WebProcess/WebStorage/StorageAreaMap.cpp: 29 (WebKit::StorageAreaMap::StorageAreaMap): 30 (WebKit::StorageAreaMap::setItem): 31 (WebKit::StorageAreaMap::removeItem): 32 (WebKit::StorageAreaMap::clear): 33 (WebKit::StorageAreaMap::loadValuesIfNeeded): 34 * WebProcess/WebStorage/StorageNamespaceImpl.cpp: 35 (WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace): 36 (WebKit::StorageNamespaceImpl::storageArea): 37 (WebKit::StorageNamespaceImpl::copy): 38 (): Deleted. 39 (WebKit::StorageNamespaceImpl::ephemeralLocalStorageArea): Deleted. 40 * WebProcess/WebStorage/StorageNamespaceImpl.h: 41 1 42 2019-02-20 Jer Noble <jer.noble@apple.com> 2 43 -
TabularUnified trunk/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.cpp ¶
r240437 r242122 49 49 , m_localStorageDirectory(localStorageDirectory.isolatedCopy()) 50 50 { 51 ASSERT(!m_localStorageDirectory.isEmpty());52 53 51 // Make sure the encoding is initialized before we start dispatching things to the queue. 54 52 UTF8Encoding(); -
TabularUnified trunk/Source/WebKit/UIProcess/WebStorage/StorageManager.cpp ¶
r241595 r242122 108 108 }; 109 109 110 // Suggested by https://www.w3.org/TR/webstorage/#disk-space 111 const unsigned localStorageDatabaseQuotaInBytes = 5 * 1024 * 1024; 112 110 113 class StorageManager::TransientLocalStorageNamespace : public ThreadSafeRefCounted<TransientLocalStorageNamespace> { 111 114 public: … … 157 160 } 158 161 159 const unsigned m_quotaInBytes = 5 * 1024 * 1024;162 const unsigned m_quotaInBytes = localStorageDatabaseQuotaInBytes; 160 163 161 164 HashMap<SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap; … … 327 330 : m_storageManager(storageManager) 328 331 , m_storageNamespaceID(storageNamespaceID) 329 , m_quotaInBytes( 5 * 1024 * 1024)332 , m_quotaInBytes(localStorageDatabaseQuotaInBytes) 330 333 { 331 334 } … … 465 468 : m_queue(WorkQueue::create("com.apple.WebKit.StorageManager")) 466 469 , m_localStorageDatabaseTracker(LocalStorageDatabaseTracker::create(m_queue.copyRef(), localStorageDirectory)) 470 , m_isEphemeral(localStorageDirectory.isNull()) 467 471 { 468 472 // Make sure the encoding is initialized before we start dispatching things to the queue. … … 674 678 void StorageManager::createLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData) 675 679 { 680 ASSERT(!m_isEphemeral); 676 681 std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connection.uniqueID(), storageMapID); 677 682 … … 737 742 void StorageManager::createSessionStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData) 738 743 { 744 if (m_isEphemeral) { 745 m_ephemeralStorage.add(securityOriginData, WebCore::StorageMap::create(localStorageDatabaseQuotaInBytes)); 746 return; 747 } 739 748 // FIXME: This should be a message check. 740 749 ASSERT(m_sessionStorageNamespaces.isValidKey(storageNamespaceID)); … … 786 795 } 787 796 788 void StorageManager::getValues(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageMapSeed, CompletionHandler<void(const HashMap<String, String>&)>&& completionHandler)797 void StorageManager::getValues(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t storageMapSeed, CompletionHandler<void(const HashMap<String, String>&)>&& completionHandler) 789 798 { 790 799 StorageArea* storageArea = findStorageArea(connection, storageMapID); 791 800 if (!storageArea) { 801 if (m_isEphemeral) { 802 if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) 803 return completionHandler(storageMap->items()); 804 } 792 805 // This is a session storage area for a page that has already been closed. Ignore it. 793 806 return completionHandler({ }); … … 798 811 } 799 812 800 void StorageManager::setItem(IPC::Connection& connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString)813 void StorageManager::setItem(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString) 801 814 { 802 815 StorageArea* storageArea = findStorageArea(connection, storageMapID); 803 816 if (!storageArea) { 817 if (m_isEphemeral) { 818 if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) { 819 String oldValue; 820 bool quotaException; 821 storageMap->setItem(key, value, oldValue, quotaException); 822 } 823 } 804 824 // This is a session storage area for a page that has already been closed. Ignore it. 805 825 return; … … 811 831 } 812 832 813 void StorageManager::removeItem(IPC::Connection& connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString)833 void StorageManager::removeItem(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString) 814 834 { 815 835 StorageArea* storageArea = findStorageArea(connection, storageMapID); 816 836 if (!storageArea) { 837 if (m_isEphemeral) { 838 if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) { 839 String oldValue; 840 storageMap->removeItem(key, oldValue); 841 } 842 } 817 843 // This is a session storage area for a page that has already been closed. Ignore it. 818 844 return; … … 823 849 } 824 850 825 void StorageManager::clear(IPC::Connection& connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString)851 void StorageManager::clear(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString) 826 852 { 827 853 StorageArea* storageArea = findStorageArea(connection, storageMapID); 828 854 if (!storageArea) { 855 if (m_isEphemeral) 856 m_ephemeralStorage.remove(securityOriginData); 829 857 // This is a session storage area for a page that has already been closed. Ignore it. 830 858 return; -
TabularUnified trunk/Source/WebKit/UIProcess/WebStorage/StorageManager.h ¶
r241595 r242122 28 28 #include "Connection.h" 29 29 #include "LocalStorageDatabaseTracker.h" 30 #include <WebCore/SecurityOriginData.h> 31 #include <WebCore/StorageMap.h> 30 32 #include <wtf/Forward.h> 31 33 #include <wtf/Function.h> … … 82 84 void destroyStorageMap(IPC::Connection&, uint64_t storageMapID); 83 85 84 void getValues(IPC::Connection&, uint64_t storageMapID, uint64_t storageMapSeed, CompletionHandler<void(const HashMap<String, String>&)>&&);85 void setItem(IPC::Connection&, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString);86 void removeItem(IPC::Connection&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString);87 void clear(IPC::Connection&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString);86 void getValues(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t storageMapSeed, CompletionHandler<void(const HashMap<String, String>&)>&&); 87 void setItem(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString); 88 void removeItem(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString); 89 void clear(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString); 88 90 89 91 class StorageArea; … … 107 109 108 110 HashMap<std::pair<IPC::Connection::UniqueID, uint64_t>, RefPtr<StorageArea>> m_storageAreasByConnection; 111 112 HashMap<WebCore::SecurityOriginData, Ref<WebCore::StorageMap>> m_ephemeralStorage; 113 bool m_isEphemeral { false }; 109 114 }; 110 115 -
TabularUnified trunk/Source/WebKit/UIProcess/WebStorage/StorageManager.messages.in ¶
r241595 r242122 27 27 DestroyStorageMap(uint64_t storageMapID) WantsConnection 28 28 29 GetValues( uint64_t storageMapID, uint64_t storageMapSeed) -> (HashMap<String, String> values) Delayed WantsConnection29 GetValues(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t storageMapSeed) -> (HashMap<String, String> values) Delayed WantsConnection 30 30 31 SetItem( uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String value, String urlString) WantsConnection32 RemoveItem( uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String urlString) WantsConnection33 Clear( uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String urlString) WantsConnection31 SetItem(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String value, String urlString) WantsConnection 32 RemoveItem(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String urlString) WantsConnection 33 Clear(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String urlString) WantsConnection 34 34 } -
TabularUnified trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp ¶
r242056 r242122 118 118 , m_resolvedConfiguration(WebsiteDataStoreConfiguration::create()) 119 119 , m_configuration(m_resolvedConfiguration->copy()) 120 , m_storageManager(StorageManager::create({ })) 120 121 , m_deviceIdHashSaltStorage(DeviceIdHashSaltStorage::create(isPersistent() ? m_configuration->deviceIdHashSaltsStorageDirectory() : String())) 121 122 , m_queue(WorkQueue::create("com.apple.WebKit.WebsiteDataStore")) -
TabularUnified trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp ¶
r235205 r242122 85 85 86 86 case StorageType::EphemeralLocal: 87 // The UI process is not involved for EphemeralLocal storages.87 ASSERT_NOT_REACHED(); 88 88 return; 89 89 } … … 140 140 m_pendingValueChanges.add(key); 141 141 142 WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::SetItem(m_s torageMapID, sourceArea->storageAreaID(), m_currentSeed, key, value, sourceFrame->document()->url()), 0);142 WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::SetItem(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, value, sourceFrame->document()->url()), 0); 143 143 } 144 144 … … 156 156 m_pendingValueChanges.add(key); 157 157 158 WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::RemoveItem(m_s torageMapID, sourceArea->storageAreaID(), m_currentSeed, key, sourceFrame->document()->url()), 0);158 WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::RemoveItem(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, sourceFrame->document()->url()), 0); 159 159 } 160 160 … … 165 165 m_hasPendingClear = true; 166 166 m_storageMap = StorageMap::create(m_quotaInBytes); 167 WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::Clear(m_s torageMapID, sourceArea->storageAreaID(), m_currentSeed, sourceFrame->document()->url()), 0);167 WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::Clear(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, sourceFrame->document()->url()), 0); 168 168 } 169 169 … … 194 194 // (This flag does not yet exist). Since loadValuesIfNeeded() ends up being called from within JavaScript code, processing incoming synchronous messages 195 195 // could lead to weird reentrency bugs otherwise. 196 WebProcess::singleton().parentProcessConnection()->sendSync(Messages::StorageManager::GetValues(m_s torageMapID, m_currentSeed), Messages::StorageManager::GetValues::Reply(values), 0);196 WebProcess::singleton().parentProcessConnection()->sendSync(Messages::StorageManager::GetValues(m_securityOrigin->data(), m_storageMapID, m_currentSeed), Messages::StorageManager::GetValues::Reply(values), 0); 197 197 198 198 m_storageMap = StorageMap::create(m_quotaInBytes); -
TabularUnified trunk/Source/WebKit/WebProcess/WebStorage/StorageNamespaceImpl.cpp ¶
r239535 r242122 48 48 Ref<StorageNamespaceImpl> StorageNamespaceImpl::createEphemeralLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes) 49 49 { 50 return adoptRef(*new StorageNamespaceImpl(StorageType::EphemeralLocal, identifier, nullptr, quotaInBytes));50 return createSessionStorageNamespace(identifier, quotaInBytes); 51 51 } 52 52 … … 80 80 Ref<StorageArea> StorageNamespaceImpl::storageArea(const SecurityOriginData& securityOrigin) 81 81 { 82 if (m_storageType == StorageType::EphemeralLocal)83 return ephemeralLocalStorageArea(securityOrigin);84 85 82 RefPtr<StorageAreaMap> map; 86 83 … … 95 92 } 96 93 97 class StorageNamespaceImpl::EphemeralStorageArea final : public StorageArea {98 public:99 static Ref<EphemeralStorageArea> create(const SecurityOriginData& origin, unsigned quotaInBytes)100 {101 return adoptRef(*new EphemeralStorageArea(origin, quotaInBytes));102 }103 104 Ref<EphemeralStorageArea> copy()105 {106 return adoptRef(*new EphemeralStorageArea(*this));107 }108 109 private:110 EphemeralStorageArea(const SecurityOriginData& origin, unsigned quotaInBytes)111 : m_securityOriginData(origin)112 , m_storageMap(StorageMap::create(quotaInBytes))113 {114 }115 116 EphemeralStorageArea(EphemeralStorageArea& other)117 : m_securityOriginData(other.m_securityOriginData)118 , m_storageMap(other.m_storageMap)119 {120 }121 122 // WebCore::StorageArea.123 unsigned length()124 {125 return m_storageMap->length();126 }127 128 String key(unsigned index)129 {130 return m_storageMap->key(index);131 }132 133 String item(const String& key)134 {135 return m_storageMap->getItem(key);136 }137 138 void setItem(Frame*, const String& key, const String& value, bool& quotaException)139 {140 String oldValue;141 if (auto newMap = m_storageMap->setItem(key, value, oldValue, quotaException))142 m_storageMap = WTFMove(newMap);143 }144 145 void removeItem(Frame*, const String& key)146 {147 String oldValue;148 if (auto newMap = m_storageMap->removeItem(key, oldValue))149 m_storageMap = WTFMove(newMap);150 }151 152 void clear(Frame*)153 {154 if (!m_storageMap->length())155 return;156 157 m_storageMap = StorageMap::create(m_storageMap->quota());158 }159 160 bool contains(const String& key)161 {162 return m_storageMap->contains(key);163 }164 165 StorageType storageType() const166 {167 return StorageType::EphemeralLocal;168 }169 170 size_t memoryBytesUsedByCache()171 {172 return 0;173 }174 175 void incrementAccessCount() { }176 void decrementAccessCount() { }177 void closeDatabaseIfIdle() { }178 179 const SecurityOriginData& securityOrigin() const180 {181 return m_securityOriginData;182 }183 184 SecurityOriginData m_securityOriginData;185 RefPtr<StorageMap> m_storageMap;186 };187 188 Ref<StorageArea> StorageNamespaceImpl::ephemeralLocalStorageArea(const SecurityOriginData& securityOrigin)189 {190 auto& slot = m_ephemeralLocalStorageAreas.add(securityOrigin, nullptr).iterator->value;191 if (!slot)192 slot = StorageNamespaceImpl::EphemeralStorageArea::create(securityOrigin, m_quotaInBytes);193 ASSERT(slot);194 return *slot;195 }196 197 94 Ref<StorageNamespace> StorageNamespaceImpl::copy(Page* newPage) 198 95 { … … 205 102 auto newNamespace = adoptRef(*new StorageNamespaceImpl(m_storageType, m_storageNamespaceID, m_topLevelOrigin.get(), m_quotaInBytes)); 206 103 207 for (auto& iter : m_ephemeralLocalStorageAreas)208 newNamespace->m_ephemeralLocalStorageAreas.set(iter.key, iter.value->copy());209 210 104 return WTFMove(newNamespace); 211 105 } -
TabularUnified trunk/Source/WebKit/WebProcess/WebStorage/StorageNamespaceImpl.h ¶
r239535 r242122 60 60 Ref<WebCore::StorageNamespace> copy(WebCore::Page*) override; 61 61 62 Ref<WebCore::StorageArea> ephemeralLocalStorageArea(const WebCore::SecurityOriginData&);63 64 62 const WebCore::StorageType m_storageType; 65 63 const uint64_t m_storageNamespaceID; … … 71 69 72 70 HashMap<WebCore::SecurityOriginData, StorageAreaMap*> m_storageAreaMaps; 73 74 class EphemeralStorageArea;75 HashMap<WebCore::SecurityOriginData, RefPtr<EphemeralStorageArea>> m_ephemeralLocalStorageAreas;76 71 }; 77 72 -
TabularUnified trunk/Tools/ChangeLog ¶
r242113 r242122 1 2019-02-26 Alex Christensen <achristensen@webkit.org> 2 3 Move ephemeral local storage from WebProcess to UIProcess 4 https://bugs.webkit.org/show_bug.cgi?id=195074 5 <rdar://problem/47937975> 6 7 Reviewed by Geoff Garen. 8 9 * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm: 10 1 11 2019-02-20 Jer Noble <jer.noble@apple.com> 2 12 -
TabularUnified trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm ¶
r242089 r242122 4399 4399 } 4400 4400 4401 TEST(ProcessSwap, EphemeralLocalStorage) 4402 { 4403 auto processPoolConfiguration = psonProcessPoolConfiguration(); 4404 auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); 4405 4406 auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); 4407 [webViewConfiguration setProcessPool:processPool.get()]; 4408 [webViewConfiguration setWebsiteDataStore:[WKWebsiteDataStore nonPersistentDataStore]]; 4409 auto handler = adoptNS([[PSONScheme alloc] init]); 4410 [handler addMappingFromURLString:@"pson://www.webkit.org/iframe.html" toData:"<script>window.localStorage.setItem('c','d')</script>"]; 4411 [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"]; 4412 4413 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); 4414 auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]); 4415 [webView setNavigationDelegate:delegate.get()]; 4416 4417 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://webkit.org/"]]]; 4418 TestWebKitAPI::Util::run(&done); 4419 4420 done = false; 4421 [webView evaluateJavaScript:@"window.localStorage.setItem('a','b')" completionHandler:^(id, NSError *) { 4422 done = true; 4423 }]; 4424 TestWebKitAPI::Util::run(&done); 4425 4426 done = false; 4427 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://example.com/"]]]; 4428 TestWebKitAPI::Util::run(&done); 4429 4430 done = false; 4431 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://webkit.org/"]]]; 4432 TestWebKitAPI::Util::run(&done); 4433 4434 done = false; 4435 [webView evaluateJavaScript:@"window.localStorage.getItem('a')" completionHandler:^(id result, NSError *) { 4436 EXPECT_TRUE([@"b" isEqualToString:result]); 4437 done = true; 4438 }]; 4439 TestWebKitAPI::Util::run(&done); 4440 4441 done = false; 4442 [webView loadHTMLString:@"<html><iframe src='pson://www.webkit.org/iframe.html'></iframe></html>" baseURL:[NSURL URLWithString:@"http://www.example.com/"]]; 4443 TestWebKitAPI::Util::run(&done); 4444 4445 done = false; 4446 [webView evaluateJavaScript:@"window.localStorage.getItem('a')" completionHandler:^(id result, NSError *) { 4447 EXPECT_FALSE([@"b" isEqualToString:result]); 4448 done = true; 4449 }]; 4450 TestWebKitAPI::Util::run(&done); 4451 } 4452 4401 4453 TEST(ProcessSwap, UsePrewarmedProcessAfterTerminatingNetworkProcess) 4402 4454 {
Note:
See TracChangeset
for help on using the changeset viewer.