test_refresh_firefox.py (28649B)
1 import os 2 import time 3 4 from marionette_driver.errors import NoAlertPresentException 5 from marionette_harness import MarionetteTestCase 6 7 8 # Holds info about things we need to cleanup after the tests are done. 9 class PendingCleanup: 10 desktop_backup_path = None 11 reset_profile_path = None 12 reset_profile_local_path = None 13 14 def __init__(self, profile_name_to_remove): 15 self.profile_name_to_remove = profile_name_to_remove 16 17 18 class TestFirefoxRefresh(MarionetteTestCase): 19 _sandbox = "firefox-refresh" 20 21 _username = "marionette-test-login" 22 _password = "marionette-test-password" 23 _bookmarkURL = "about:mozilla" 24 _bookmarkText = "Some bookmark from Marionette" 25 26 _cookieHost = "firefox-refresh.marionette-test.mozilla.org" 27 _cookiePath = "some/cookie/path" 28 _cookieName = "somecookie" 29 _cookieValue = "some cookie value" 30 31 _historyURL = "http://firefox-refresh.marionette-test.mozilla.org/" 32 _historyTitle = "Test visit for Firefox Reset" 33 34 _formHistoryFieldName = "some-very-unique-marionette-only-firefox-reset-field" 35 _formHistoryValue = "special-pumpkin-value" 36 37 _formAutofillAvailable = False 38 _formAutofillAddressGuid = None 39 40 _expectedURLs = ["about:robots", "about:mozilla"] 41 _expectedOpenGroupID = "test-open-group" 42 _expectedSavedGroups = ["test-saved-group"] 43 44 def savePassword(self): 45 self.runAsyncCode( 46 """ 47 let [username, password, resolve] = arguments; 48 let myLogin = new global.LoginInfo( 49 "test.marionette.mozilla.com", 50 "http://test.marionette.mozilla.com/some/form/", 51 null, 52 username, 53 password, 54 "username", 55 "password" 56 ); 57 Services.logins.addLoginAsync(myLogin) 58 .then(() => resolve(false), resolve); 59 """, 60 script_args=(self._username, self._password), 61 ) 62 63 def createBookmarkInMenu(self): 64 error = self.runAsyncCode( 65 """ 66 // let url = arguments[0]; 67 // let title = arguments[1]; 68 // let resolve = arguments[arguments.length - 1]; 69 let [url, title, resolve] = arguments; 70 PlacesUtils.bookmarks.insert({ 71 parentGuid: PlacesUtils.bookmarks.menuGuid, url, title 72 }).then(() => resolve(false), resolve); 73 """, 74 script_args=(self._bookmarkURL, self._bookmarkText), 75 ) 76 if error: 77 print(error) 78 79 def createBookmarksOnToolbar(self): 80 error = self.runAsyncCode( 81 """ 82 let resolve = arguments[arguments.length - 1]; 83 let children = []; 84 for (let i = 1; i <= 5; i++) { 85 children.push({url: `about:rights?p=${i}`, title: `Bookmark ${i}`}); 86 } 87 PlacesUtils.bookmarks.insertTree({ 88 guid: PlacesUtils.bookmarks.toolbarGuid, 89 children 90 }).then(() => resolve(false), resolve); 91 """ 92 ) 93 if error: 94 print(error) 95 96 def createHistory(self): 97 error = self.runAsyncCode( 98 """ 99 let resolve = arguments[arguments.length - 1]; 100 PlacesUtils.history.insert({ 101 url: arguments[0], 102 title: arguments[1], 103 visits: [{ 104 date: new Date(Date.now() - 5000), 105 referrer: "about:mozilla" 106 }] 107 }).then(() => resolve(false), 108 ex => resolve("Unexpected error in adding visit: " + ex)); 109 """, 110 script_args=(self._historyURL, self._historyTitle), 111 ) 112 if error: 113 print(error) 114 115 def createFormHistory(self): 116 error = self.runAsyncCode( 117 """ 118 let updateDefinition = { 119 op: "add", 120 fieldname: arguments[0], 121 value: arguments[1], 122 firstUsed: (Date.now() - 5000) * 1000, 123 }; 124 let resolve = arguments[arguments.length - 1]; 125 global.FormHistory.update(updateDefinition).then(() => { 126 resolve(false); 127 }, error => { 128 resolve("Unexpected error in adding formhistory: " + error); 129 }); 130 """, 131 script_args=(self._formHistoryFieldName, self._formHistoryValue), 132 ) 133 if error: 134 print(error) 135 136 def createFormAutofill(self): 137 if not self._formAutofillAvailable: 138 return 139 self._formAutofillAddressGuid = self.runAsyncCode( 140 """ 141 let resolve = arguments[arguments.length - 1]; 142 const TEST_ADDRESS_1 = { 143 "given-name": "John", 144 "additional-name": "R.", 145 "family-name": "Smith", 146 organization: "World Wide Web Consortium", 147 "street-address": "32 Vassar Street\\\nMIT Room 32-G524", 148 "address-level2": "Cambridge", 149 "address-level1": "MA", 150 "postal-code": "02139", 151 country: "US", 152 tel: "+15195555555", 153 email: "user@example.com", 154 }; 155 return global.formAutofillStorage.initialize().then(() => { 156 return global.formAutofillStorage.addresses.add(TEST_ADDRESS_1); 157 }).then(resolve); 158 """ 159 ) 160 161 def createCookie(self): 162 self.runCode( 163 """ 164 // Expire in 15 minutes: 165 let expireTime = Date.now() + 1000 * 15 * 60; 166 Services.cookies.add(arguments[0], arguments[1], arguments[2], arguments[3], 167 true, false, false, expireTime, {}, 168 Ci.nsICookie.SAMESITE_UNSET, Ci.nsICookie.SCHEME_UNSET); 169 """, 170 script_args=( 171 self._cookieHost, 172 self._cookiePath, 173 self._cookieName, 174 self._cookieValue, 175 ), 176 ) 177 178 def createSession(self): 179 self.runAsyncCode( 180 """ 181 let resolve = arguments[arguments.length - 1]; 182 const COMPLETE_STATE = Ci.nsIWebProgressListener.STATE_STOP + 183 Ci.nsIWebProgressListener.STATE_IS_NETWORK; 184 let { TabStateFlusher } = ChromeUtils.importESModule( 185 "resource:///modules/sessionstore/TabStateFlusher.sys.mjs" 186 ); 187 let expectedURLs = Array.from(arguments[0]) 188 let expectedOpenGroupID = arguments[1]; 189 gBrowser.addTabsProgressListener({ 190 onStateChange(browser, webprogress, request, flags, status) { 191 try { 192 request && request.QueryInterface(Ci.nsIChannel); 193 } catch (ex) {} 194 let uriLoaded = request.originalURI && request.originalURI.spec; 195 if ((flags & COMPLETE_STATE == COMPLETE_STATE) && uriLoaded && 196 expectedURLs.includes(uriLoaded)) { 197 TabStateFlusher.flush(browser).then(function() { 198 expectedURLs.splice(expectedURLs.indexOf(uriLoaded), 1); 199 if (!expectedURLs.length) { 200 gBrowser.removeTabsProgressListener(this); 201 resolve(); 202 } 203 }); 204 } 205 } 206 }); 207 let expectedTabs = new Set(); 208 for (let url of expectedURLs) { 209 expectedTabs.add(gBrowser.addTab(url, { 210 triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), 211 })); 212 } 213 if (expectedOpenGroupID) { 214 gBrowser.addTabGroup([gBrowser.tabs[gBrowser.tabs.length - 1]], { id: expectedOpenGroupID }); 215 } 216 // Close any other tabs that might be open: 217 let allTabs = Array.from(gBrowser.tabs); 218 for (let tab of allTabs) { 219 if (!expectedTabs.has(tab)) { 220 gBrowser.removeTab(tab); 221 } 222 } 223 """, # NOQA: E501 224 script_args=(self._expectedURLs, self._expectedOpenGroupID), 225 ) 226 227 self.runAsyncCode( 228 """ 229 let resolve = arguments[arguments.length - 1]; 230 let expectedSavedGroups = Array.from(arguments[0]); 231 let { TabStateFlusher } = ChromeUtils.importESModule( 232 "resource:///modules/sessionstore/TabStateFlusher.sys.mjs" 233 ); 234 235 let savePromises = []; 236 let groups = []; 237 for (let id of expectedSavedGroups) { 238 let tab = gBrowser.addTab("about:mozilla", { 239 triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), 240 }); 241 let group = gBrowser.addTabGroup([tab], { id }); 242 groups.push(group); 243 let groupSaved = new Promise(res => { 244 window.addEventListener("TabGroupSaved", (e) => { 245 if (e.target === group) { 246 res() 247 } 248 }); 249 }); 250 let groupRemoved = new Promise(res => { 251 window.addEventListener("TabGroupRemoved", (e) => { 252 if (e.target === group) { 253 res() 254 } 255 }); 256 }); 257 savePromises.push(Promise.allSettled([groupSaved, groupRemoved])); 258 } 259 TabStateFlusher.flushWindow(gBrowser.ownerGlobal).then(() => { 260 groups.forEach(group => { 261 group.saveAndClose(); 262 }) 263 Promise.allSettled(savePromises).then(resolve); 264 }); 265 266 """, 267 script_args=(self._expectedSavedGroups,), 268 ) 269 270 self.assertEqual( 271 self.marionette.execute_script( 272 """ 273 return SessionStore.savedGroups.length; 274 """ 275 ), 276 len(self._expectedSavedGroups), 277 "Correct number of groups were saved", 278 ) 279 280 def createFxa(self): 281 # This script will write an entry to the login manager and create 282 # a signedInUser.json in the profile dir. 283 self.runAsyncCode( 284 """ 285 let resolve = arguments[arguments.length - 1]; 286 let { FxAccountsStorageManager } = ChromeUtils.importESModule( 287 "resource://gre/modules/FxAccountsStorage.sys.mjs" 288 ); 289 let storage = new FxAccountsStorageManager(); 290 let data = {email: "test@test.com", uid: "uid", keyFetchToken: "top-secret"}; 291 storage.initialize(data); 292 storage.finalize().then(resolve); 293 """ 294 ) 295 296 def createSync(self): 297 # This script will write the canonical preference which indicates a user 298 # is signed into sync. 299 self.marionette.execute_script( 300 """ 301 Services.prefs.setStringPref("services.sync.username", "test@test.com"); 302 """ 303 ) 304 305 def checkPassword(self): 306 loginInfo = self.runAsyncCode( 307 """ 308 let [resolve] = arguments; 309 Services.logins.searchLoginsAsync({ 310 origin: "test.marionette.mozilla.com", 311 formActionOrigin: "http://test.marionette.mozilla.com/some/form/", 312 }).then(ary => resolve(ary.length ? ary : {username: "null", password: "null"})); 313 """ 314 ) 315 self.assertEqual(len(loginInfo), 1) 316 self.assertEqual(loginInfo[0]["username"], self._username) 317 self.assertEqual(loginInfo[0]["password"], self._password) 318 319 loginCount = self.runAsyncCode( 320 """ 321 let resolve = arguments[arguments.length - 1]; 322 Services.logins.getAllLogins().then(logins => resolve(logins.length)); 323 """ 324 ) 325 # Note that we expect 2 logins - one from us, one from sync. 326 self.assertEqual(loginCount, 2, "No other logins are present") 327 328 def checkBookmarkInMenu(self): 329 titleInBookmarks = self.runAsyncCode( 330 """ 331 let [url, resolve] = arguments; 332 PlacesUtils.bookmarks.fetch({url}).then( 333 bookmark => resolve(bookmark ? bookmark.title : ""), 334 ex => resolve(ex) 335 ); 336 """, 337 script_args=(self._bookmarkURL,), 338 ) 339 self.assertEqual(titleInBookmarks, self._bookmarkText) 340 341 def checkBookmarkToolbarVisibility(self): 342 toolbarVisible = self.marionette.execute_script( 343 """ 344 const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL; 345 return Services.xulStore.getValue(BROWSER_DOCURL, "PersonalToolbar", "collapsed"); 346 """ 347 ) 348 if toolbarVisible == "": 349 toolbarVisible = "false" 350 self.assertEqual(toolbarVisible, "false") 351 352 def checkHistory(self): 353 historyResult = self.runAsyncCode( 354 """ 355 let resolve = arguments[arguments.length - 1]; 356 PlacesUtils.history.fetch(arguments[0]).then(pageInfo => { 357 if (!pageInfo) { 358 resolve("No visits found"); 359 } else { 360 resolve(pageInfo); 361 } 362 }).catch(e => { 363 resolve("Unexpected error in fetching page: " + e); 364 }); 365 """, 366 script_args=(self._historyURL,), 367 ) 368 if type(historyResult) is str: 369 self.fail(historyResult) 370 return 371 372 self.assertEqual(historyResult["title"], self._historyTitle) 373 374 def checkFormHistory(self): 375 formFieldResults = self.runAsyncCode( 376 """ 377 let resolve = arguments[arguments.length - 1]; 378 let results = []; 379 global.FormHistory.search(["value"], {fieldname: arguments[0]}) 380 .then(resolve); 381 """, 382 script_args=(self._formHistoryFieldName,), 383 ) 384 if type(formFieldResults) is str: 385 self.fail(formFieldResults) 386 return 387 388 formFieldResultCount = len(formFieldResults) 389 self.assertEqual( 390 formFieldResultCount, 391 1, 392 "Should have exactly 1 entry for this field, got %d" % formFieldResultCount, 393 ) 394 if formFieldResultCount == 1: 395 self.assertEqual(formFieldResults[0]["value"], self._formHistoryValue) 396 397 formHistoryCount = self.runAsyncCode( 398 """ 399 let [resolve] = arguments; 400 global.FormHistory.count({}).then(resolve); 401 """ 402 ) 403 self.assertEqual( 404 formHistoryCount, 1, "There should be only 1 entry in the form history" 405 ) 406 407 def checkFormAutofill(self): 408 if not self._formAutofillAvailable: 409 return 410 411 formAutofillResults = self.runAsyncCode( 412 """ 413 let resolve = arguments[arguments.length - 1]; 414 return global.formAutofillStorage.initialize().then(() => { 415 return global.formAutofillStorage.addresses.getAll() 416 }).then(resolve); 417 """, 418 ) 419 if type(formAutofillResults) is str: 420 self.fail(formAutofillResults) 421 return 422 423 formAutofillAddressCount = len(formAutofillResults) 424 self.assertEqual( 425 formAutofillAddressCount, 426 1, 427 "Should have exactly 1 saved address, got %d" % formAutofillAddressCount, 428 ) 429 if formAutofillAddressCount == 1: 430 self.assertEqual( 431 formAutofillResults[0]["guid"], self._formAutofillAddressGuid 432 ) 433 434 def checkCookie(self): 435 cookieInfo = self.runCode( 436 """ 437 try { 438 let cookies = Services.cookies.getCookiesFromHost(arguments[0], {}); 439 let cookie = null; 440 for (let hostCookie of cookies) { 441 // getCookiesFromHost returns any cookie from the BASE host. 442 if (hostCookie.rawHost != arguments[0]) 443 continue; 444 if (cookie != null) { 445 return "more than 1 cookie! That shouldn't happen!"; 446 } 447 cookie = hostCookie; 448 } 449 return {path: cookie.path, name: cookie.name, value: cookie.value}; 450 } catch (ex) { 451 return "got exception trying to fetch cookie: " + ex; 452 } 453 """, 454 script_args=(self._cookieHost,), 455 ) 456 if not isinstance(cookieInfo, dict): 457 self.fail(cookieInfo) 458 return 459 self.assertEqual(cookieInfo["path"], self._cookiePath) 460 self.assertEqual(cookieInfo["value"], self._cookieValue) 461 self.assertEqual(cookieInfo["name"], self._cookieName) 462 463 def checkSession(self): 464 tabURIs = self.runCode( 465 """ 466 return [... gBrowser.browsers].map(b => b.currentURI && b.currentURI.spec) 467 """ 468 ) 469 self.assertSequenceEqual(tabURIs, ["about:welcomeback"]) 470 471 # Dismiss modal dialog if any. This is mainly to dismiss the check for 472 # default browser dialog if it shows up. 473 try: 474 alert = self.marionette.switch_to_alert() 475 alert.dismiss() 476 except NoAlertPresentException: 477 pass 478 479 tabURIs = self.runAsyncCode( 480 """ 481 let resolve = arguments[arguments.length - 1] 482 let mm = gBrowser.selectedBrowser.messageManager; 483 484 window.addEventListener("SSWindowStateReady", function() { 485 window.addEventListener("SSTabRestored", function() { 486 resolve(Array.from(gBrowser.browsers, b => b.currentURI?.spec)); 487 }, { capture: false, once: true }); 488 }, { capture: false, once: true }); 489 490 let fs = function() { 491 if (content.document.readyState === "complete") { 492 content.document.getElementById("errorTryAgain").click(); 493 } else { 494 content.window.addEventListener("load", function(event) { 495 content.document.getElementById("errorTryAgain").click(); 496 }, { once: true }); 497 } 498 }; 499 500 Services.prefs.setBoolPref("security.allow_parent_unrestricted_js_loads", true); 501 mm.loadFrameScript("data:application/javascript,(" + fs.toString() + ")()", true); 502 Services.prefs.setBoolPref("security.allow_parent_unrestricted_js_loads", false); 503 """ # NOQA: E501 504 ) 505 self.assertSequenceEqual(tabURIs, self._expectedURLs) 506 507 if self._expectedOpenGroupID: 508 groupExists = self.runCode( 509 """ 510 let groupID = arguments[0]; 511 let group = gBrowser.getTabGroupById(groupID); 512 return !!group; 513 """, 514 script_args=(self._expectedOpenGroupID,), 515 ) 516 self.assertTrue(groupExists, "open group was restored") 517 518 savedGroupIDs = self.runAsyncCode( 519 """ 520 let resolve = arguments[arguments.length - 1]; 521 let groupIDs = []; 522 for (let group of window.SessionStore.savedGroups) { 523 groupIDs.push(group.id); 524 } 525 resolve(groupIDs); 526 """, 527 script_args=(self._expectedSavedGroups,), 528 ) 529 self.assertSequenceEqual(savedGroupIDs, self._expectedSavedGroups) 530 531 def checkFxA(self): 532 result = self.runAsyncCode( 533 """ 534 let { FxAccountsStorageManager } = ChromeUtils.importESModule( 535 "resource://gre/modules/FxAccountsStorage.sys.mjs" 536 ); 537 let resolve = arguments[arguments.length - 1]; 538 let storage = new FxAccountsStorageManager(); 539 let result = {}; 540 storage.initialize(); 541 storage.getAccountData().then(data => { 542 result.accountData = data; 543 return storage.finalize(); 544 }).then(() => { 545 resolve(result); 546 }).catch(err => { 547 resolve(err.toString()); 548 }); 549 """ 550 ) 551 if type(result) is not dict: 552 self.fail(result) 553 return 554 self.assertEqual(result["accountData"]["email"], "test@test.com") 555 self.assertEqual(result["accountData"]["uid"], "uid") 556 self.assertEqual(result["accountData"]["keyFetchToken"], "top-secret") 557 558 def checkSync(self, expect_sync_user): 559 pref_value = self.marionette.execute_script( 560 """ 561 return Services.prefs.getStringPref("services.sync.username", null); 562 """ 563 ) 564 expected_value = "test@test.com" if expect_sync_user else None 565 self.assertEqual(pref_value, expected_value) 566 567 def checkStartupMigrationStateCleared(self): 568 result = self.runCode( 569 """ 570 let { MigrationUtils } = ChromeUtils.importESModule( 571 "resource:///modules/MigrationUtils.sys.mjs" 572 ); 573 return MigrationUtils.isStartupMigration; 574 """ 575 ) 576 self.assertFalse(result) 577 578 def checkRefreshPromptDisabled(self): 579 refreshPromptDisabled = self.runCode( 580 """ 581 return Services.prefs.getStringPref("browser.disableResetPrompt", false); 582 """ 583 ) 584 self.assertTrue(refreshPromptDisabled) 585 586 def checkProfile(self, has_migrated=False, expect_sync_user=True): 587 self.checkPassword() 588 self.checkBookmarkInMenu() 589 self.checkHistory() 590 self.checkFormHistory() 591 self.checkFormAutofill() 592 self.checkCookie() 593 self.checkFxA() 594 self.checkSync(expect_sync_user) 595 if has_migrated: 596 self.checkBookmarkToolbarVisibility() 597 self.checkSession() 598 self.checkStartupMigrationStateCleared() 599 self.checkRefreshPromptDisabled() 600 601 def createProfileData(self): 602 self.savePassword() 603 self.createBookmarkInMenu() 604 self.createBookmarksOnToolbar() 605 self.createHistory() 606 self.createFormHistory() 607 self.createFormAutofill() 608 self.createCookie() 609 self.createSession() 610 self.createFxa() 611 self.createSync() 612 613 def setUpScriptData(self): 614 self.marionette.set_context(self.marionette.CONTEXT_CHROME) 615 self.runCode( 616 """ 617 window.global = {}; 618 global.LoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1", "nsILoginInfo", "init"); 619 global.profSvc = Cc["@mozilla.org/toolkit/profile-service;1"].getService(Ci.nsIToolkitProfileService); 620 global.Preferences = ChromeUtils.importESModule( 621 "resource://gre/modules/Preferences.sys.mjs" 622 ).Preferences; 623 global.FormHistory = ChromeUtils.importESModule( 624 "resource://gre/modules/FormHistory.sys.mjs" 625 ).FormHistory; 626 """ # NOQA: E501 627 ) 628 self._formAutofillAvailable = self.runCode( 629 """ 630 try { 631 global.formAutofillStorage = ChromeUtils.importESModule( 632 "resource://formautofill/FormAutofillStorage.sys.mjs" 633 ).formAutofillStorage; 634 } catch(e) { 635 return false; 636 } 637 return true; 638 """ # NOQA: E501 639 ) 640 641 def runCode(self, script, *args, **kwargs): 642 return self.marionette.execute_script( 643 script, new_sandbox=False, sandbox=self._sandbox, *args, **kwargs 644 ) 645 646 def runAsyncCode(self, script, *args, **kwargs): 647 return self.marionette.execute_async_script( 648 script, new_sandbox=False, sandbox=self._sandbox, *args, **kwargs 649 ) 650 651 def setUp(self): 652 MarionetteTestCase.setUp(self) 653 self.setUpScriptData() 654 655 self.cleanups = [] 656 657 def tearDown(self): 658 # Force yet another restart with a clean profile to disconnect from the 659 # profile and environment changes we've made, to leave a more or less 660 # blank slate for the next person. 661 self.marionette.restart(in_app=False, clean=True) 662 self.setUpScriptData() 663 664 # Super 665 MarionetteTestCase.tearDown(self) 666 667 # A helper to deal with removing a load of files 668 import mozfile 669 670 for cleanup in self.cleanups: 671 if cleanup.desktop_backup_path: 672 mozfile.remove(cleanup.desktop_backup_path) 673 674 if cleanup.reset_profile_path: 675 # Remove ourselves from profiles.ini 676 self.runCode( 677 """ 678 let name = arguments[0]; 679 let profile = global.profSvc.getProfileByName(name); 680 profile.remove(false) 681 global.profSvc.flush(); 682 """, 683 script_args=(cleanup.profile_name_to_remove,), 684 ) 685 # Remove the local profile dir if it's not the same as the profile dir: 686 different_path = ( 687 cleanup.reset_profile_local_path != cleanup.reset_profile_path 688 ) 689 if cleanup.reset_profile_local_path and different_path: 690 mozfile.remove(cleanup.reset_profile_local_path) 691 692 # And delete all the files. 693 mozfile.remove(cleanup.reset_profile_path) 694 695 def doReset(self): 696 profileName = "marionette-test-profile-" + str(int(time.time() * 1000)) 697 cleanup = PendingCleanup(profileName) 698 self.runCode( 699 """ 700 // Ensure the current (temporary) profile is in profiles.ini: 701 let profD = Services.dirsvc.get("ProfD", Ci.nsIFile); 702 let profileName = arguments[1]; 703 let myProfile = global.profSvc.createProfile(profD, profileName); 704 global.profSvc.flush() 705 706 // Now add the reset parameters: 707 let prefsToKeep = Array.from(Services.prefs.getChildList("marionette.")); 708 // Add all the modified preferences set from geckoinstance.py to avoid 709 // non-local connections. 710 prefsToKeep = prefsToKeep.concat(JSON.parse( 711 Services.env.get("MOZ_MARIONETTE_REQUIRED_PREFS"))); 712 let prefObj = {}; 713 for (let pref of prefsToKeep) { 714 prefObj[pref] = global.Preferences.get(pref); 715 } 716 Services.env.set("MOZ_MARIONETTE_PREF_STATE_ACROSS_RESTARTS", JSON.stringify(prefObj)); 717 Services.env.set("MOZ_RESET_PROFILE_RESTART", "1"); 718 Services.env.set("XRE_PROFILE_PATH", arguments[0]); 719 """, 720 script_args=( 721 self.marionette.instance.profile.profile, 722 profileName, 723 ), 724 ) 725 726 profileLeafName = os.path.basename( 727 os.path.normpath(self.marionette.instance.profile.profile) 728 ) 729 730 # Now restart the browser to get it reset: 731 self.marionette.restart(clean=False, in_app=True) 732 self.setUpScriptData() 733 734 # Determine the new profile path (we'll need to remove it when we're done) 735 [cleanup.reset_profile_path, cleanup.reset_profile_local_path] = self.runCode( 736 """ 737 let profD = Services.dirsvc.get("ProfD", Ci.nsIFile); 738 let localD = Services.dirsvc.get("ProfLD", Ci.nsIFile); 739 return [profD.path, localD.path]; 740 """ 741 ) 742 743 # Determine the backup path 744 cleanup.desktop_backup_path = self.runCode( 745 """ 746 let container; 747 try { 748 container = Services.dirsvc.get("Desk", Ci.nsIFile); 749 } catch (ex) { 750 container = Services.dirsvc.get("Home", Ci.nsIFile); 751 } 752 let bundle = Services.strings.createBundle("chrome://mozapps/locale/profile/profileSelection.properties"); 753 let dirName = bundle.formatStringFromName("resetBackupDirectory", [Services.appinfo.name]); 754 container.append(dirName); 755 container.append(arguments[0]); 756 return container.path; 757 """, # NOQA: E501 758 script_args=(profileLeafName,), 759 ) 760 761 self.assertTrue( 762 os.path.isdir(cleanup.reset_profile_path), 763 "Reset profile path should be present", 764 ) 765 self.assertTrue( 766 os.path.isdir(cleanup.desktop_backup_path), 767 "Backup profile path should be present", 768 ) 769 self.assertIn(cleanup.profile_name_to_remove, cleanup.reset_profile_path) 770 return cleanup 771 772 def testResetEverything(self): 773 self.createProfileData() 774 775 self.checkProfile(expect_sync_user=True) 776 777 this_cleanup = self.doReset() 778 self.cleanups.append(this_cleanup) 779 780 # Now check that we're doing OK... 781 self.checkProfile(has_migrated=True, expect_sync_user=True) 782 783 def testFxANoSync(self): 784 # This test doesn't need to repeat all the non-sync tests... 785 # Setup FxA but *not* sync 786 self.createFxa() 787 788 self.checkFxA() 789 self.checkSync(False) 790 791 this_cleanup = self.doReset() 792 self.cleanups.append(this_cleanup) 793 794 self.checkFxA() 795 self.checkSync(False)