Modified: trunk/Tools/ChangeLog (277266 => 277267)
--- trunk/Tools/ChangeLog 2021-05-10 16:35:17 UTC (rev 277266)
+++ trunk/Tools/ChangeLog 2021-05-10 16:38:00 UTC (rev 277267)
@@ -1,3 +1,27 @@
+2021-05-10 Chris Dumez <cdu...@apple.com>
+
+ Fix potential races in AppleLanguagesTest.UpdateAppleLanguages API test
+ https://bugs.webkit.org/show_bug.cgi?id=225429
+
+ Reviewed by Darin Adler.
+
+ Calling [TestWKWebView performAfterReceivingAnyMessage] registers a MessageHandler which sends an
+ async WebUserContentController::AddUserScriptMessageHandlers IPC to the WebProcess. We want to
+ make sure that that message handler is registered in the WebProcess before the JS on the page
+ calls `webkit.messageHandlers.testHandler.postMessage()`. To address this issue, I moved the
+ call to `[TestWKWebView performAfterReceivingAnyMessage]` before the call to evaluateJavaScript
+ that registers the event listener that may call `webkit.messageHandlers.testHandler.postMessage()`.
+
+ Also make sure the PreferenceObserver has been allocated after sending the
+ "NSApplicationDidBecomeActiveNotification" and before proceeding with the test.
+
+ I am also adding an extra check at the end to make sure that the value of navigator.language is
+ correct and to make sure that WKPreferenceObserver.preferenceDidChange was called. This was done
+ to help diagnose flakiness issues on the bots that I cannot reproduce locally.
+
+ * TestWebKitAPI/Tests/WebKit/OverrideAppleLanguagesPreference.mm:
+ (TEST_F):
+
2021-05-10 Aditya Keerthi <akeer...@apple.com>
[iPadOS] Do not present custom input peripherals when switching back to a tab with a focused element
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/OverrideAppleLanguagesPreference.mm (277266 => 277267)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit/OverrideAppleLanguagesPreference.mm 2021-05-10 16:35:17 UTC (rev 277266)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/OverrideAppleLanguagesPreference.mm 2021-05-10 16:38:00 UTC (rev 277267)
@@ -29,6 +29,8 @@
#import "PlatformUtilities.h"
#import "TestWKWebView.h"
+#import <WebKit/PreferenceObserver.h>
+#import <wtf/ObjCRuntimeExtras.h>
#import <wtf/cocoa/VectorCocoa.h>
#import <wtf/text/StringBuilder.h>
@@ -57,7 +59,7 @@
// On older macOSes, CFPREFS_DIRECT_MODE is disabled and the WebProcess does not see the updated AppleLanguages
// after the AppleLanguagePreferencesChangedNotification notification.
// FIXME: This test is currently disabled on Apple Silicon because it times out there (https://bugs.webkit.org/show_bug.cgi?id=222619).
-#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 110000 && CPU(X86_64)
+#if PLATFORM(MAC) && ENABLE(CFPREFS_DIRECT_MODE) && CPU(X86_64)
class AppleLanguagesTest : public testing::Test {
public:
AppleLanguagesTest()
@@ -86,11 +88,51 @@
String m_savedAppleLanguages;
};
+static IMP sharedInstanceMethodOriginal = nil;
+static IMP preferenceDidChangeMethodOriginal = nil;
+static bool preferenceObserverSharedInstanceCalled = false;
+static bool preferenceObserverPreferenceDidChangeCalled = false;
+
+static WKPreferenceObserver *sharedInstanceMethodOverride(id self, SEL selector)
+{
+ WKPreferenceObserver *observer = wtfCallIMP<WKPreferenceObserver *>(sharedInstanceMethodOriginal, self, selector);
+ preferenceObserverSharedInstanceCalled = true;
+ return observer;
+}
+
+static WKPreferenceObserver *preferenceDidChangeMethodOverride(id self, SEL selector, NSString *domain, NSString *key, NSString *encodedValue)
+{
+ NSLog(@"preferenceDidChangeMethodOverride: domain=%@, key=%@, encodedValue=%@", domain, key, encodedValue);
+ if ([key isEqualToString:@"AppleLanguages"])
+ preferenceObserverPreferenceDidChangeCalled = true;
+ WKPreferenceObserver *observer = wtfCallIMP<WKPreferenceObserver *>(preferenceDidChangeMethodOriginal, self, selector, domain, key, encodedValue);
+ return observer;
+}
+
TEST_F(AppleLanguagesTest, UpdateAppleLanguages)
{
+ preferenceObserverSharedInstanceCalled = false;
+ Method sharedInstanceMethod = class_getClassMethod(objc_getClass("WKPreferenceObserver"), @selector(sharedInstance));
+ ASSERT(sharedInstanceMethod);
+ sharedInstanceMethodOriginal = method_setImplementation(sharedInstanceMethod, (IMP)sharedInstanceMethodOverride);
+ ASSERT(sharedInstanceMethodOriginal);
+ Method preferenceDidChangeMethod = class_getInstanceMethod(objc_getClass("WKPreferenceObserver"), @selector(preferenceDidChange:key:encodedValue:));
+ ASSERT(preferenceDidChangeMethod);
+ preferenceDidChangeMethodOriginal = method_setImplementation(preferenceDidChangeMethod, (IMP)preferenceDidChangeMethodOverride);
+ ASSERT(preferenceDidChangeMethodOriginal);
+
// Tests uses "en-GB" language initially.
system([NSString stringWithFormat:@"defaults write NSGlobalDomain AppleLanguages '(\"en-GB\")'"].UTF8String);
+ auto getLanguageFromNSUserDefaults = [] {
+ auto languages = makeVector<String>([[NSUserDefaults standardUserDefaults] valueForKey:@"AppleLanguages"]);
+ return languages.isEmpty() ? emptyString() : languages[0];
+ };
+ unsigned timeout = 0;
+ while (getLanguageFromNSUserDefaults() != "en-GB" && ++timeout < 100)
+ TestWebKitAPI::Util::sleep(0.1);
+ EXPECT_WK_STREQ(@"en-GB", getLanguageFromNSUserDefaults());
+
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]);
[webView synchronouslyLoadTestPageNamed:@"simple"];
@@ -97,6 +139,12 @@
// We only listen for preference changes when the application is active.
[[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationDidBecomeActiveNotification object:NSApp userInfo:nil];
+ timeout = 0;
+ while (!preferenceObserverSharedInstanceCalled && ++timeout < 100)
+ TestWebKitAPI::Util::sleep(0.1);
+ EXPECT_TRUE(preferenceObserverSharedInstanceCalled);
+ if (!preferenceObserverSharedInstanceCalled)
+ return;
auto preferredLanguage = [&] {
return [webView stringByEvaluatingJavaScript:@"navigator.language"];
@@ -104,13 +152,6 @@
EXPECT_WK_STREQ(@"en-GB", preferredLanguage());
__block bool done = false;
- [webView evaluateJavaScript:@"_onlanguagechange_ = () => { webkit.messageHandlers.testHandler.postMessage(navigator.language); }; true;" completionHandler:^(id value, NSError *error) {
- EXPECT_TRUE(!error);
- done = true;
- }];
- TestWebKitAPI::Util::run(&done);
-
- done = false;
__block bool didChangeLanguage = false;
[webView performAfterReceivingAnyMessage:^(NSString *newLanguage) {
EXPECT_WK_STREQ(@"en-US", newLanguage);
@@ -118,10 +159,16 @@
done = true;
}];
+ [webView evaluateJavaScript:@"_onlanguagechange_ = () => { webkit.messageHandlers.testHandler.postMessage(navigator.language); }; true;" completionHandler:^(id value, NSError *error) {
+ EXPECT_TRUE(!error);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
// Switch system language from "en-GB" to "en-US". Make sure that we fire a languagechange event at the Window and that navigator.language
- // now reports "en-gb".
+ // now reports "en-GB".
system([NSString stringWithFormat:@"defaults write NSGlobalDomain AppleLanguages '(\"en-US\")'"].UTF8String);
- CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), CFSTR("AppleLanguagePreferencesChangedNotification"), nullptr, nullptr, true);
// Implement our own timeout because we would fail to reset the language if we let the test actually time out.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
@@ -130,5 +177,10 @@
TestWebKitAPI::Util::run(&done);
EXPECT_TRUE(didChangeLanguage);
+ EXPECT_TRUE(preferenceObserverPreferenceDidChangeCalled);
+ EXPECT_WK_STREQ(@"en-US", preferredLanguage());
+ EXPECT_WK_STREQ(@"en-US", getLanguageFromNSUserDefaults());
+
+ method_setImplementation(sharedInstanceMethod, (IMP)sharedInstanceMethodOriginal);
}
#endif