browser_search_userEngineDialog.js (22275B)
1 /* Any copyright is dedicated to the Public Domain. 2 https://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 requestLongerTimeout(2); 7 8 const { PlacesTestUtils } = ChromeUtils.importESModule( 9 "resource://testing-common/PlacesTestUtils.sys.mjs" 10 ); 11 const { SearchTestUtils } = ChromeUtils.importESModule( 12 "resource://testing-common/SearchTestUtils.sys.mjs" 13 ); 14 const { SearchUtils } = ChromeUtils.importESModule( 15 "moz-src:///toolkit/components/search/SearchUtils.sys.mjs" 16 ); 17 18 add_task(async function test_addEngineGet() { 19 await openPreferencesViaOpenPreferencesAPI("search", { 20 leaveOpen: true, 21 }); 22 23 // Add new engine via add engine dialog. 24 let doc = gBrowser.contentDocument; 25 let addButton = doc.querySelector("#addEngineButton"); 26 let dialogWin = await openDialogWith(doc, () => addButton.click()); 27 Assert.equal( 28 dialogWin.document.getElementById("titleContainer").style.display, 29 "none", 30 "Adjustable title is hidden in add engine dialog." 31 ); 32 33 setName("Bugzilla", dialogWin); 34 setUrl( 35 "https://bugzilla.mozilla.org/buglist.cgi?quicksearch=%s&list_id=17442621", 36 dialogWin 37 ); 38 await setAlias("bz", dialogWin); 39 40 let advanced = dialogWin.document.querySelector("dialog").getButton("extra1"); 41 Assert.ok(!advanced.hidden, "Button is visible"); 42 Assert.ok( 43 dialogWin.document.getElementById("advanced-section").hidden, 44 "Advanced section is hidden" 45 ); 46 advanced.click(); 47 Assert.ok(advanced.hidden, "Button was hidden"); 48 Assert.ok( 49 !dialogWin.document.getElementById("advanced-section").hidden, 50 "Advanced section was made visible" 51 ); 52 53 let promiseAdded = SearchTestUtils.promiseSearchNotification( 54 SearchUtils.MODIFIED_TYPE.ADDED, 55 SearchUtils.TOPIC_ENGINE_MODIFIED 56 ); 57 EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin); 58 await promiseAdded; 59 Assert.ok(true, "Got added notification."); 60 61 // Check new engine. 62 let engine = Services.search.getEngineByName("Bugzilla"); 63 Assert.equal(engine.name, "Bugzilla", "Name is correct."); 64 Assert.equal( 65 engine.getSubmission("föö").uri.spec, 66 "https://bugzilla.mozilla.org/buglist.cgi?quicksearch=f%C3%B6%C3%B6&list_id=17442621", 67 "URL is correct and encodes search terms using utf-8." 68 ); 69 Assert.equal(engine.alias, "bz", "Alias is correct."); 70 71 // Clean up. 72 BrowserTestUtils.removeTab(gBrowser.selectedTab); 73 await Services.search.removeEngine(engine); 74 }); 75 76 add_task(async function test_addEnginePost() { 77 await openPreferencesViaOpenPreferencesAPI("search", { 78 leaveOpen: true, 79 }); 80 81 // Add new engine via add engine dialog. 82 let doc = gBrowser.contentDocument; 83 let addButton = doc.querySelector("#addEngineButton"); 84 let dialogWin = await openDialogWith(doc, () => addButton.click()); 85 dialogWin.document.querySelector("dialog").getButton("extra1").click(); 86 87 setName("Bugzilla Post", dialogWin); 88 setUrl("https://bugzilla.mozilla.org/buglist.cgi", dialogWin); 89 await setAlias("bz", dialogWin); 90 setPostData("quicksearch=%s&list_id=17442621", dialogWin); 91 setSuggestUrl("https://bugzilla.mozilla.org/suggest?q=%s", dialogWin); 92 93 let promiseAdded = SearchTestUtils.promiseSearchNotification( 94 SearchUtils.MODIFIED_TYPE.ADDED, 95 SearchUtils.TOPIC_ENGINE_MODIFIED 96 ); 97 EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin); 98 await promiseAdded; 99 Assert.ok(true, "Got added notification."); 100 101 // Check new engine. 102 let engine = Services.search.getEngineByName("Bugzilla Post"); 103 Assert.equal(engine.name, "Bugzilla Post", "Name is correct."); 104 let submission = engine.getSubmission("föö"); 105 Assert.equal( 106 submission.uri.spec, 107 "https://bugzilla.mozilla.org/buglist.cgi", 108 "URL is correct." 109 ); 110 Assert.equal( 111 decodePostData(submission.postData), 112 "quicksearch=f%C3%B6%C3%B6&list_id=17442621", 113 "Post Data is correct and encodes search terms using utf-8." 114 ); 115 Assert.equal( 116 engine.getSubmission("föö", SearchUtils.URL_TYPE.SUGGEST_JSON).uri.spec, 117 "https://bugzilla.mozilla.org/suggest?q=f%C3%B6%C3%B6", 118 "Suggest URL is correct and encodes search terms using utf-8." 119 ); 120 Assert.equal(engine.alias, "bz", "Alias is correct."); 121 122 // Clean up. 123 BrowserTestUtils.removeTab(gBrowser.selectedTab); 124 await Services.search.removeEngine(engine); 125 }); 126 127 add_task(async function test_validation() { 128 await openPreferencesViaOpenPreferencesAPI("search", { 129 leaveOpen: true, 130 }); 131 let existingEngine = await Services.search.addUserEngine({ 132 name: "user", 133 url: "https://example.com/user?q={searchTerms}&b=ff", 134 alias: "u", 135 }); 136 137 let doc = gBrowser.contentDocument; 138 let addButton = doc.querySelector("#addEngineButton"); 139 let dialogWin = await openDialogWith(doc, () => addButton.click()); 140 141 let accept = dialogWin.document.querySelector("dialog").getButton("accept"); 142 let advanced = dialogWin.document.querySelector("dialog").getButton("extra1"); 143 let name = dialogWin.document.getElementById("engineName"); 144 let url = dialogWin.document.getElementById("engineUrl"); 145 let alias = dialogWin.document.getElementById("engineAlias"); 146 let suggestUrl = dialogWin.document.getElementById("suggestUrl"); 147 let postData = dialogWin.document.getElementById("enginePostData"); 148 149 Assert.ok( 150 name.value == "" && url.value == "" && alias.value == "", 151 "Everything is empty initially." 152 ); 153 Assert.ok(accept.disabled, "Button is disabled initially."); 154 await assertError(name, "add-engine-no-name"); 155 await assertError(url, "add-engine-no-url"); 156 await assertError(alias, null); 157 await assertError(suggestUrl, null); 158 159 setName("Example", dialogWin); 160 setUrl("https://example.com/search?q=%s", dialogWin); 161 await setAlias("abc", dialogWin); 162 setSuggestUrl("https://example.com/search?q=%s", dialogWin); 163 Assert.ok(!accept.disabled, "Button is enabled when everything is there."); 164 165 info("Checking name."); 166 setName("", dialogWin); 167 await assertError(name, "add-engine-no-name"); 168 Assert.ok(accept.disabled, "Name is required."); 169 170 setName(existingEngine.name, dialogWin); 171 await assertError(name, "add-engine-name-exists"); 172 Assert.ok(accept.disabled, "Existing name is not allowed."); 173 174 setName("Example", dialogWin); 175 await assertError(name, null); 176 Assert.ok(!accept.disabled, "Good name enables the button."); 177 178 info("Checking search URL."); 179 setUrl("", dialogWin); 180 Assert.ok(accept.disabled, "URL is required."); 181 await assertError(url, "add-engine-no-url"); 182 183 setUrl("javascript://%s", dialogWin); 184 await assertError(url, "add-engine-invalid-protocol"); 185 Assert.ok(accept.disabled, "Javascript URLs are not allowed."); 186 187 setUrl("not a url", dialogWin); 188 await assertError(url, "add-engine-invalid-url"); 189 Assert.ok(accept.disabled, "Invalid URLs are not allowed."); 190 191 setUrl("https://example.com/search?q=kitten", dialogWin); 192 await assertError(url, "add-engine-missing-terms-url"); 193 Assert.ok(accept.disabled, "URLs without %s are not allowed."); 194 195 setUrl("https://example.com/search?q=%s", dialogWin); 196 await assertError(url, null); 197 Assert.ok(!accept.disabled, "Good URL enables the button."); 198 199 info("Checking alias."); 200 await setAlias("", dialogWin); 201 await assertError(alias, null); 202 Assert.ok(!accept.disabled, "Alias is not required."); 203 204 await setAlias(existingEngine.alias, dialogWin); 205 await assertError(alias, "add-engine-keyword-exists"); 206 Assert.ok(accept.disabled, "Existing alias is not allowed."); 207 208 await setAlias(existingEngine.alias.toUpperCase(), dialogWin); 209 await assertError(alias, "add-engine-keyword-exists"); 210 Assert.ok(accept.disabled, "Alias duplicate test is case insensitive."); 211 212 await setAlias("abc", dialogWin); 213 await assertError(alias, null); 214 Assert.ok(!accept.disabled, "Good alias enables the button."); 215 216 advanced.click(); 217 info("Checking suggest URL."); 218 setSuggestUrl("javascript://%s", dialogWin); 219 await assertError(suggestUrl, "add-engine-invalid-protocol"); 220 Assert.ok(accept.disabled, "Javascript URLs are not allowed."); 221 222 setSuggestUrl("not a url", dialogWin); 223 await assertError(suggestUrl, "add-engine-invalid-url"); 224 Assert.ok(accept.disabled, "Invalid URLs are not allowed."); 225 226 setSuggestUrl("https://example.com/search?q=kitten", dialogWin); 227 await assertError(suggestUrl, "add-engine-missing-terms-url"); 228 Assert.ok(accept.disabled, "URLs without %s are not allowed."); 229 230 setSuggestUrl("https://example.com/search?q=%s", dialogWin); 231 await assertError(suggestUrl, null); 232 Assert.ok(!accept.disabled, "Good URL enables the button."); 233 234 info("Checking post data."); 235 setUrl("https://example.com/search", dialogWin); 236 await assertError(url, "add-engine-missing-terms-url"); 237 238 setPostData("test", dialogWin); 239 await assertError(postData, "add-engine-missing-terms-post-data"); 240 await assertError(url, null); 241 Assert.ok(accept.disabled, "Post data without %s is not allowed."); 242 243 setUrl("https://example.com/search", dialogWin); 244 setPostData("q=%s", dialogWin); 245 await assertError(postData, null); 246 await assertError(url, null); 247 Assert.ok(!accept.disabled, "Post data containing %s enables the button."); 248 249 // Clean up. 250 BrowserTestUtils.removeTab(gBrowser.selectedTab); 251 await Services.search.removeEngine(existingEngine); 252 }); 253 254 add_task(async function test_editGetEngine() { 255 await openPreferencesViaOpenPreferencesAPI("search", { 256 leaveOpen: true, 257 }); 258 259 let doc = gBrowser.contentDocument; 260 let tree = doc.querySelector("#engineList"); 261 let view = tree.view.wrappedJSObject; 262 let engine = await Services.search.addUserEngine({ 263 name: "user", 264 url: "https://example.com/user?q={searchTerms}&b=ff", 265 alias: "u", 266 }); 267 engine.wrappedJSObject.changeUrl( 268 SearchUtils.URL_TYPE.SUGGEST_JSON, 269 "https://example.com/suggest?query={searchTerms}", 270 null 271 ); 272 273 // Check buttons of all search engines + local shortcuts. 274 let removeButton = doc.querySelector("#removeEngineButton"); 275 let editButton = doc.querySelector("#editEngineButton"); 276 277 let userEngineIndex = null; 278 for (let i = 0; i < tree.view.rowCount; i++) { 279 view.selection.select(i); 280 let selectedEngine = view.selectedEngine; 281 if (selectedEngine?.isUserEngine) { 282 Assert.equal(selectedEngine.name, "user", "Is the new engine."); 283 Assert.ok(!removeButton.disabled, "Remove button is enabled."); 284 Assert.ok(!editButton.disabled, "Edit button is enabled."); 285 userEngineIndex = i; 286 } else { 287 Assert.ok(editButton.disabled, "Edit button is disabled."); 288 } 289 } 290 291 // Check if table contains new engine without reloading. 292 Assert.ok(!!userEngineIndex, "User engine is in the table."); 293 view.selection.select(userEngineIndex); 294 295 // Open the dialog and check values. 296 let dialogWin = await openDialogWith(doc, () => editButton.click()); 297 let acceptButton = dialogWin.document 298 .querySelector("dialog") 299 .shadowRoot.querySelector('button[dlgtype="accept"]'); 300 301 Assert.equal( 302 dialogWin.document.getElementById("titleContainer").style.display, 303 "none", 304 "Adjustable title is hidden in edit engine dialog." 305 ); 306 Assert.equal( 307 dialogWin.document.getElementById("engineName").value, 308 "user", 309 "Name in dialog is correct." 310 ); 311 Assert.equal( 312 dialogWin.document.getElementById("engineUrl").value, 313 "https://example.com/user?q=%s&b=ff", 314 "URL in dialog is correct." 315 ); 316 Assert.ok( 317 !dialogWin.document.getElementById("advanced-section").hidden, 318 "Advanced section is visible" 319 ); 320 Assert.equal( 321 dialogWin.document.getElementById("enginePostData").value, 322 "", 323 "Post data input is empty." 324 ); 325 Assert.equal( 326 dialogWin.document.getElementById("suggestUrl").value, 327 "https://example.com/suggest?query=%s", 328 "Suggest URL in dialog is correct" 329 ); 330 Assert.equal( 331 dialogWin.document.getElementById("engineAlias").value, 332 "u", 333 "Alias in dialog is correct." 334 ); 335 336 // Set new values. 337 setName("Searchfox", dialogWin); 338 setUrl("https://searchfox.org/mozilla-central/search", dialogWin); 339 await setAlias("sf", dialogWin); 340 setSuggestUrl("", dialogWin); 341 342 dialogWin.document.querySelector("dialog").getButton("extra1").click(); 343 setPostData("q=%s&path=&case=false®exp=false", dialogWin); 344 345 // Save changes to engine. 346 let promiseChanged = SearchTestUtils.promiseSearchNotification( 347 SearchUtils.MODIFIED_TYPE.CHANGED, 348 SearchUtils.TOPIC_ENGINE_MODIFIED, 349 3 350 ); 351 acceptButton.click(); 352 await promiseChanged; 353 Assert.ok(true, "Got 3 change notifications."); 354 355 // Open dialog again and check values. 356 dialogWin = await openDialogWith(doc, () => editButton.click()); 357 Assert.equal( 358 dialogWin.document.getElementById("engineName").value, 359 "Searchfox", 360 "Name in dialog reflects change" 361 ); 362 Assert.equal( 363 dialogWin.document.getElementById("engineUrl").value, 364 "https://searchfox.org/mozilla-central/search", 365 "URL in dialog reflects change" 366 ); 367 Assert.equal( 368 dialogWin.document.getElementById("engineAlias").value, 369 "sf", 370 "Alias in dialog reflects change" 371 ); 372 Assert.ok( 373 !dialogWin.document.getElementById("advanced-section").hidden, 374 "Advanced section is still visible" 375 ); 376 Assert.equal( 377 dialogWin.document.getElementById("enginePostData").value, 378 "q=%s&path=&case=false®exp=false", 379 "Post data reflects changes" 380 ); 381 Assert.equal( 382 dialogWin.document.getElementById("suggestUrl").value, 383 "", 384 "Suggest URL in dialog was removed" 385 ); 386 387 // Check search engine object. 388 let submission = engine.getSubmission("foo"); 389 Assert.equal( 390 submission.uri.spec, 391 "https://searchfox.org/mozilla-central/search", 392 "Search URL reflects changes" 393 ); 394 Assert.equal( 395 decodePostData(submission.postData), 396 "q=foo&path=&case=false®exp=false", 397 "Engine was converted into a POST engine." 398 ); 399 submission = engine.getSubmission("foo", SearchUtils.URL_TYPE.SUGGEST_JSON); 400 Assert.ok(!submission, "Suggest URL was removed"); 401 402 // Clean up. 403 BrowserTestUtils.removeTab(gBrowser.selectedTab); 404 await Services.search.removeEngine(engine); 405 }); 406 407 add_task(async function test_editPostEngine() { 408 await openPreferencesViaOpenPreferencesAPI("search", { 409 leaveOpen: true, 410 }); 411 412 let doc = gBrowser.contentDocument; 413 let tree = doc.querySelector("#engineList"); 414 let view = tree.view.wrappedJSObject; 415 416 let params = new URLSearchParams(); 417 params.append("q", "{searchTerms}"); 418 let engine = await Services.search.addUserEngine({ 419 name: "user post", 420 url: "https://example.com/user", 421 params, 422 method: "POST", 423 alias: "u", 424 }); 425 426 let editButton = doc.querySelector("#editEngineButton"); 427 428 for (let i = 0; i < tree.view.rowCount; i++) { 429 view.selection.select(i); 430 let selectedEngine = view.selectedEngine; 431 if (selectedEngine?.isUserEngine) { 432 view.selection.select(i); 433 break; 434 } 435 } 436 437 // Open the dialog. 438 let dialogWin = await openDialogWith(doc, () => editButton.click()); 439 Assert.equal( 440 dialogWin.document.getElementById("engineName").value, 441 "user post", 442 "Name in dialog is correct." 443 ); 444 Assert.equal( 445 dialogWin.document.getElementById("engineUrl").value, 446 "https://example.com/user", 447 "URL in dialog is correct." 448 ); 449 Assert.ok( 450 !dialogWin.document.getElementById("advanced-section").hidden, 451 "Advanced section is visible." 452 ); 453 Assert.equal( 454 dialogWin.document.getElementById("enginePostData").value, 455 "q=%s", 456 "Post data in dialog is correct." 457 ); 458 Assert.equal( 459 dialogWin.document.getElementById("suggestUrl").value, 460 "", 461 "Suggest URL in dialog is empty." 462 ); 463 Assert.equal( 464 dialogWin.document.getElementById("engineAlias").value, 465 "u", 466 "Alias in dialog is correct." 467 ); 468 469 // Set new values. 470 setName("Searchfox", dialogWin); 471 setUrl("https://searchfox.org/mozilla-central/search", dialogWin); 472 setPostData("q=%s&path=&case=false®exp=false", dialogWin); 473 setSuggestUrl("https://searchfox.org/suggest/%s", dialogWin); 474 await setAlias("sf", dialogWin); 475 476 // Save changes to engine. 477 let promiseChanged = SearchTestUtils.promiseSearchNotification( 478 SearchUtils.MODIFIED_TYPE.CHANGED, 479 SearchUtils.TOPIC_ENGINE_MODIFIED, 480 4 481 ); 482 EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin); 483 await promiseChanged; 484 Assert.ok(true, "Got 4 change notifications."); 485 486 // Open dialog again and check values. 487 dialogWin = await openDialogWith(doc, () => editButton.click()); 488 Assert.equal( 489 dialogWin.document.getElementById("engineName").value, 490 "Searchfox", 491 "Name in dialog reflects change." 492 ); 493 Assert.equal( 494 dialogWin.document.getElementById("engineUrl").value, 495 "https://searchfox.org/mozilla-central/search", 496 "URL in dialog reflects changes." 497 ); 498 Assert.equal( 499 dialogWin.document.getElementById("enginePostData").value, 500 "q=%s&path=&case=false®exp=false", 501 "Post data in dialog reflects changes." 502 ); 503 Assert.equal( 504 dialogWin.document.getElementById("suggestUrl").value, 505 "https://searchfox.org/suggest/%s", 506 "Suggest URL in dialog reflects changes." 507 ); 508 Assert.equal( 509 dialogWin.document.getElementById("engineAlias").value, 510 "sf", 511 "Alias in dialog reflects changes." 512 ); 513 514 // Check values of search engine object. 515 Assert.equal( 516 engine.name, 517 "Searchfox", 518 "Name of search engine object was updated." 519 ); 520 let submission = engine.getSubmission("foo"); 521 Assert.equal( 522 submission.uri.spec, 523 "https://searchfox.org/mozilla-central/search", 524 "Submission URL reflects changes." 525 ); 526 Assert.equal( 527 decodePostData(submission.postData), 528 "q=foo&path=&case=false®exp=false", 529 "Submission post data reflects changes" 530 ); 531 submission = engine.getSubmission("foo", SearchUtils.URL_TYPE.SUGGEST_JSON); 532 Assert.equal( 533 submission.uri.spec, 534 "https://searchfox.org/suggest/foo", 535 "Submission URL reflects changes." 536 ); 537 Assert.equal(submission.postData, null, "Submission URL is still GET."); 538 Assert.equal( 539 engine.alias, 540 "sf", 541 "Alias of search engine object was updated." 542 ); 543 544 // Clean up. 545 BrowserTestUtils.removeTab(gBrowser.selectedTab); 546 await Services.search.removeEngine(engine); 547 }); 548 549 add_task(async function test_icon() { 550 // Set up favicon. 551 let pageUrl = "https://search.test/"; 552 let iconUrl = "https://search.test/favicon.svg"; 553 let dataURL = "data:image/svg+xml;base64,PHN2Zy8+"; 554 555 await PlacesTestUtils.addVisits({ uri: new URL(pageUrl).URI }); 556 await PlacesTestUtils.setFaviconForPage(pageUrl, iconUrl, dataURL); 557 558 // Open Settings. 559 await openPreferencesViaOpenPreferencesAPI("search", { 560 leaveOpen: true, 561 }); 562 563 let doc = gBrowser.contentDocument; 564 let tree = doc.querySelector("#engineList"); 565 let view = tree.view.wrappedJSObject; 566 567 let addButton = doc.querySelector("#addEngineButton"); 568 let editButton = doc.querySelector("#editEngineButton"); 569 570 // Add engine and check favicon. 571 let dialogWin = await openDialogWith(doc, () => addButton.click()); 572 setName("Bugzilla", dialogWin); 573 setUrl("https://search.test/search?q=%s", dialogWin); 574 575 let promiseIcon = SearchTestUtils.promiseSearchNotification( 576 SearchUtils.MODIFIED_TYPE.ICON_CHANGED, 577 SearchUtils.TOPIC_ENGINE_MODIFIED 578 ); 579 dialogWin.document.querySelector("dialog").getButton("accept").click(); 580 let engine = await promiseIcon; 581 582 Assert.ok(true, "Icon was added"); 583 Assert.equal(await engine.getIconURL(), dataURL, "Icon is correct"); 584 585 // Change favicon. 586 dataURL = "data:image/svg+xml;base64,PHN2Zz48Y2lyY2xlIHI9IjEiLz48L3N2Zz4="; 587 await PlacesTestUtils.setFaviconForPage(pageUrl, iconUrl, dataURL); 588 589 // Edit engine and check favicon. 590 let engines = await Services.search.getEngines(); 591 let i = engines.findIndex(e => e.id == engine.id); 592 view.selection.select(i); 593 dialogWin = await openDialogWith(doc, () => editButton.click()); 594 595 promiseIcon = SearchTestUtils.promiseSearchNotification( 596 SearchUtils.MODIFIED_TYPE.ICON_CHANGED, 597 SearchUtils.TOPIC_ENGINE_MODIFIED 598 ); 599 dialogWin.document.querySelector("dialog").getButton("accept").click(); 600 await promiseIcon; 601 602 Assert.ok(true, "Icon was changed"); 603 Assert.equal(await engine.getIconURL(), dataURL, "New icon is correct"); 604 605 // Clean up. 606 BrowserTestUtils.removeTab(gBrowser.selectedTab); 607 await Services.search.removeEngine(engine); 608 PlacesUtils.favicons.expireAllFavicons(); 609 await PlacesUtils.history.clear(); 610 }); 611 612 /** 613 * Checks the error label of an input of the add engine dialog. 614 * 615 * @param {HTMLInputElement} elt 616 * The element whose error should be checked 617 * @param {?string} error 618 * The l10n id of the expected error message or null if no error is expected. 619 */ 620 async function assertError(elt, error = null) { 621 let errorLabel = elt.parentElement.querySelector(".error-label"); 622 623 if (error) { 624 let msg = await document.l10n.formatValue(error); 625 Assert.equal(errorLabel.textContent, msg); 626 } else { 627 Assert.equal(errorLabel.textContent, "valid"); 628 } 629 } 630 631 async function openDialogWith(doc, fn) { 632 info("Opening dialog."); 633 let dialogLoaded = TestUtils.topicObserved("subdialog-loaded"); 634 await fn(); 635 let [dialogWin] = await dialogLoaded; 636 await doc.ownerGlobal.gSubDialog.dialogs[0]._dialogReady; 637 Assert.ok(true, "Engine dialog opened"); 638 return dialogWin; 639 } 640 641 function setName(value, win) { 642 fillTextField("engineName", value, win); 643 } 644 645 function setUrl(value, win) { 646 fillTextField("engineUrl", value, win); 647 } 648 649 function setSuggestUrl(value, win) { 650 fillTextField("suggestUrl", value, win); 651 } 652 653 function setPostData(value, win) { 654 fillTextField("enginePostData", value, win); 655 } 656 657 async function setAlias(value, win) { 658 fillTextField("engineAlias", value, win); 659 await TestUtils.waitForTick(); 660 } 661 662 function fillTextField(id, text, win) { 663 let elt = win.document.getElementById(id); 664 elt.focus(); 665 elt.select(); 666 EventUtils.synthesizeKey("a", { metaKey: true }, win); 667 EventUtils.synthesizeKey("KEY_Backspace", {}, win); 668 669 for (let c of text.split("")) { 670 EventUtils.synthesizeKey(c, {}, win); 671 } 672 } 673 674 function decodePostData(postData) { 675 let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance( 676 Ci.nsIBinaryInputStream 677 ); 678 binaryStream.setInputStream(postData.data); 679 680 return binaryStream 681 .readBytes(binaryStream.available()) 682 .replace("searchTerms", "%s"); 683 }