test_device.js (5048B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { getFxAccountsSingleton } = ChromeUtils.importESModule( 7 "resource://gre/modules/FxAccounts.sys.mjs" 8 ); 9 const fxAccounts = getFxAccountsSingleton(); 10 11 const { CLIENT_IS_THUNDERBIRD, ON_NEW_DEVICE_ID, PREF_ACCOUNT_ROOT } = 12 ChromeUtils.importESModule("resource://gre/modules/FxAccountsCommon.sys.mjs"); 13 const { TestUtils } = ChromeUtils.importESModule( 14 "resource://testing-common/TestUtils.sys.mjs" 15 ); 16 17 _("Misc tests for FxAccounts.device"); 18 19 fxAccounts.device._checkRemoteCommandsUpdateNeeded = async () => false; 20 21 add_test(function test_default_device_name() { 22 // Note that head_helpers overrides getDefaultLocalName - this test is 23 // really just to ensure the actual implementation is sane - we can't 24 // really check the value it uses is correct. 25 // We are just hoping to avoid a repeat of bug 1369285. 26 let def = fxAccounts.device.getDefaultLocalName(); // make sure it doesn't throw. 27 _("default value is " + def); 28 ok(!!def.length); 29 30 // This is obviously tied to the implementation, but we want early warning 31 // if any of these things fail. 32 // We really want one of these 2 to provide a value. 33 let hostname = Services.sysinfo.get("device") || Services.dns.myHostName; 34 _("hostname is " + hostname); 35 ok(!!hostname.length); 36 // the hostname should be in the default. 37 ok(def.includes(hostname)); 38 // We expect the following to work as a fallback to the above. 39 let fallback = Cc["@mozilla.org/network/protocol;1?name=http"].getService( 40 Ci.nsIHttpProtocolHandler 41 ).oscpu; 42 _("UA fallback is " + fallback); 43 ok(!!fallback.length); 44 // the fallback should not be in the default 45 ok(!def.includes(fallback)); 46 47 run_next_test(); 48 }); 49 50 add_test(function test_migration() { 51 Services.prefs.clearUserPref("identity.fxaccounts.account.device.name"); 52 Services.prefs.setStringPref("services.sync.client.name", "my client name"); 53 // calling getLocalName() should move the name to the new pref and reset the old. 54 equal(fxAccounts.device.getLocalName(), "my client name"); 55 equal( 56 Services.prefs.getStringPref("identity.fxaccounts.account.device.name"), 57 "my client name" 58 ); 59 ok(!Services.prefs.prefHasUserValue("services.sync.client.name")); 60 run_next_test(); 61 }); 62 63 add_test(function test_migration_set_before_get() { 64 Services.prefs.setStringPref("services.sync.client.name", "old client name"); 65 fxAccounts.device.setLocalName("new client name"); 66 equal(fxAccounts.device.getLocalName(), "new client name"); 67 run_next_test(); 68 }); 69 70 add_task(async function test_reset() { 71 // We don't test the client name specifically here because the client name 72 // is set as part of signing the user in via the attempt to register the 73 // device. 74 const testPref = PREF_ACCOUNT_ROOT + "test-pref"; 75 Services.prefs.setStringPref(testPref, "whatever"); 76 let credentials = { 77 email: "foo@example.com", 78 uid: "1234@lcip.org", 79 sessionToken: "dead", 80 verified: true, 81 ...MOCK_ACCOUNT_KEYS, 82 }; 83 // FxA will try to register its device record in the background after signin. 84 const registerDevice = sinon 85 .stub(fxAccounts._internal.fxAccountsClient, "registerDevice") 86 .callsFake(async () => { 87 return { id: "foo" }; 88 }); 89 const notifyPromise = TestUtils.topicObserved(ON_NEW_DEVICE_ID); 90 await fxAccounts._internal.setSignedInUser(credentials); 91 await notifyPromise; 92 if (!CLIENT_IS_THUNDERBIRD) { 93 // Firefox fires the notification twice - once during `setSignedInUser` and 94 // once after it returns. It's the second notification we need to wait for. 95 // Thunderbird, OTOH, fires only once during `setSignedInUser` and that's 96 // what we need to wait for. 97 await TestUtils.topicObserved(ON_NEW_DEVICE_ID); 98 } 99 ok(!Services.prefs.prefHasUserValue(testPref)); 100 // signing the user out should reset the name pref. 101 const namePref = PREF_ACCOUNT_ROOT + "device.name"; 102 ok(Services.prefs.prefHasUserValue(namePref)); 103 await fxAccounts.signOut(/* localOnly = */ true); 104 ok(!Services.prefs.prefHasUserValue(namePref)); 105 registerDevice.restore(); 106 }); 107 108 add_task(async function test_name_sanitization() { 109 fxAccounts.device.setLocalName("emoji is valid \u2665"); 110 Assert.equal(fxAccounts.device.getLocalName(), "emoji is valid \u2665"); 111 112 let invalid = "x\uFFFD\n\r\t" + "x".repeat(255); 113 let sanitized = "x\uFFFD\uFFFD\uFFFD\uFFFD" + "x".repeat(250); // 255 total. 114 115 // If the pref already has the invalid value we still get the valid one back. 116 Services.prefs.setStringPref( 117 "identity.fxaccounts.account.device.name", 118 invalid 119 ); 120 Assert.equal(fxAccounts.device.getLocalName(), sanitized); 121 122 // But if we explicitly set it to an invalid name, the sanitized value ends 123 // up in the pref. 124 fxAccounts.device.setLocalName(invalid); 125 Assert.equal(fxAccounts.device.getLocalName(), sanitized); 126 Assert.equal( 127 Services.prefs.getStringPref("identity.fxaccounts.account.device.name"), 128 sanitized 129 ); 130 });