test_providerHeuristicFallback.js (23514B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 /** 5 * Tests that visit-url and search engine heuristic results are returned by 6 * UrlbarProviderHeuristicFallback. 7 */ 8 9 const QUICKACTIONS_PREF = "browser.urlbar.suggest.quickactions"; 10 const SUGGEST_ENABLED_PREF = "browser.search.suggest.enabled"; 11 const PRIVATE_SEARCH_PREF = "browser.search.separatePrivateDefault.ui.enabled"; 12 13 // We make sure that restriction tokens and search terms are correctly 14 // recognized when they are separated by each of these different types of spaces 15 // and combinations of spaces. U+3000 is the ideographic space in CJK and is 16 // commonly used by CJK speakers. 17 const TEST_SPACES = [" ", "\u3000", " \u3000", "\u3000 "]; 18 19 testEngine_setup(); 20 21 add_setup(async function () { 22 registerCleanupFunction(async () => { 23 Services.prefs.clearUserPref(QUICKACTIONS_PREF); 24 Services.prefs.clearUserPref(SUGGEST_ENABLED_PREF); 25 Services.prefs.clearUserPref(PRIVATE_SEARCH_PREF); 26 Services.prefs.clearUserPref("keyword.enabled"); 27 }); 28 Services.prefs.setBoolPref(QUICKACTIONS_PREF, false); 29 Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, false); 30 Services.prefs.setBoolPref(PRIVATE_SEARCH_PREF, false); 31 }); 32 33 add_task(async function () { 34 info("visit url, no protocol"); 35 let query = "mozilla.org"; 36 let context = createContext(query, { isPrivate: false }); 37 await check_results({ 38 context, 39 matches: [ 40 makeVisitResult(context, { 41 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 42 uri: `http://${query}/`, 43 title: `${query}/`, 44 heuristic: true, 45 }), 46 makeSearchResult(context, { 47 engineName: SUGGESTIONS_ENGINE_NAME, 48 }), 49 ], 50 }); 51 52 info("visit url, no protocol but with 2 dots"); 53 query = "www.mozilla.org"; 54 context = createContext(query, { isPrivate: false }); 55 await check_results({ 56 context, 57 matches: [ 58 makeVisitResult(context, { 59 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 60 uri: `http://${query}/`, 61 title: `${query}/`, 62 heuristic: true, 63 }), 64 makeSearchResult(context, { 65 engineName: SUGGESTIONS_ENGINE_NAME, 66 }), 67 ], 68 }); 69 70 info("visit url, no protocol, e-mail like"); 71 query = "a@b.com"; 72 context = createContext(query, { isPrivate: false }); 73 await check_results({ 74 context, 75 matches: [ 76 makeVisitResult(context, { 77 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 78 uri: `http://${query}/`, 79 title: `${query}/`, 80 heuristic: true, 81 }), 82 makeSearchResult(context, { 83 engineName: SUGGESTIONS_ENGINE_NAME, 84 }), 85 ], 86 }); 87 88 info("visit url, with protocol but with 2 dots"); 89 query = "https://www.mozilla.org"; 90 context = createContext(query, { isPrivate: false }); 91 await check_results({ 92 context, 93 matches: [ 94 makeVisitResult(context, { 95 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 96 uri: `${query}/`, 97 title: `${query}/`, 98 heuristic: true, 99 }), 100 ], 101 }); 102 103 // info("visit url, with protocol but with 3 dots"); 104 query = "https://www.mozilla.org.tw"; 105 context = createContext(query, { isPrivate: false }); 106 await check_results({ 107 context, 108 matches: [ 109 makeVisitResult(context, { 110 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 111 uri: `${query}/`, 112 title: `${query}/`, 113 heuristic: true, 114 }), 115 ], 116 }); 117 118 info("visit url, with protocol"); 119 query = "https://mozilla.org"; 120 context = createContext(query, { isPrivate: false }); 121 await check_results({ 122 context, 123 matches: [ 124 makeVisitResult(context, { 125 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 126 uri: `${query}/`, 127 title: `${query}/`, 128 heuristic: true, 129 }), 130 ], 131 }); 132 133 info("visit url on searchbar (should search)"); 134 query = "https://mozilla.org"; 135 context = createContext(query, { 136 isPrivate: false, 137 sapName: "searchbar", 138 }); 139 await check_results({ 140 context, 141 matches: [ 142 makeSearchResult(context, { 143 engineName: SUGGESTIONS_ENGINE_NAME, 144 heuristic: true, 145 query, 146 }), 147 ], 148 }); 149 150 info("visit url, about: protocol (no host)"); 151 query = "about:nonexistent"; 152 context = createContext(query, { isPrivate: false }); 153 await check_results({ 154 context, 155 matches: [ 156 makeVisitResult(context, { 157 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 158 uri: query, 159 title: query, 160 heuristic: true, 161 }), 162 ], 163 }); 164 165 info("visit url, with non-standard whitespace"); 166 query = "https://mozilla.org"; 167 context = createContext(`${query}\u2028`, { isPrivate: false }); 168 await check_results({ 169 context, 170 matches: [ 171 makeVisitResult(context, { 172 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 173 uri: `${query}/`, 174 title: `${query}/`, 175 heuristic: true, 176 }), 177 ], 178 }); 179 180 // This is distinct because of how we predict being able to url autofill via 181 // host lookups. 182 info("visit url, host matching visited host but not visited url"); 183 await PlacesTestUtils.addVisits([ 184 { 185 uri: Services.io.newURI("http://mozilla.org/wine/"), 186 title: "Mozilla Wine", 187 transition: PlacesUtils.history.TRANSITION_TYPED, 188 }, 189 ]); 190 query = "mozilla.org/rum"; 191 context = createContext(`${query}\u2028`, { isPrivate: false }); 192 await check_results({ 193 context, 194 matches: [ 195 makeVisitResult(context, { 196 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 197 uri: `http://${query}`, 198 title: `${query}`, 199 iconUri: "page-icon:http://mozilla.org/", 200 heuristic: true, 201 }), 202 ], 203 }); 204 await PlacesUtils.history.clear(); 205 206 // And hosts with no dot in them are special, due to requiring safelisting. 207 info("unknown host"); 208 query = "firefox"; 209 context = createContext(query, { isPrivate: false }); 210 await check_results({ 211 context, 212 matches: [ 213 makeSearchResult(context, { 214 engineName: SUGGESTIONS_ENGINE_NAME, 215 heuristic: true, 216 }), 217 ], 218 }); 219 220 info("string with known host"); 221 query = "firefox/get"; 222 context = createContext(query, { isPrivate: false }); 223 await check_results({ 224 context, 225 matches: [ 226 makeSearchResult(context, { 227 engineName: SUGGESTIONS_ENGINE_NAME, 228 heuristic: true, 229 }), 230 ], 231 }); 232 233 Services.prefs.setBoolPref("browser.fixup.domainwhitelist.firefox", true); 234 registerCleanupFunction(() => { 235 Services.prefs.clearUserPref("browser.fixup.domainwhitelist.firefox"); 236 }); 237 238 info("known host"); 239 query = "firefox"; 240 context = createContext(query, { isPrivate: false }); 241 await check_results({ 242 context, 243 matches: [ 244 makeVisitResult(context, { 245 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 246 uri: `http://${query}/`, 247 title: `${query}/`, 248 heuristic: true, 249 }), 250 makeSearchResult(context, { 251 engineName: SUGGESTIONS_ENGINE_NAME, 252 }), 253 ], 254 }); 255 256 info("url with known host"); 257 query = "firefox/get"; 258 context = createContext(query, { isPrivate: false }); 259 await check_results({ 260 context, 261 matches: [ 262 makeVisitResult(context, { 263 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 264 uri: `http://${query}`, 265 title: `${query}`, 266 iconUri: "page-icon:http://firefox/", 267 heuristic: true, 268 }), 269 ], 270 }); 271 272 info("visit url, host matching visited host but not visited url, known host"); 273 Services.prefs.setBoolPref("browser.fixup.domainwhitelist.mozilla", true); 274 registerCleanupFunction(() => { 275 Services.prefs.clearUserPref("browser.fixup.domainwhitelist.mozilla"); 276 }); 277 query = "mozilla/rum"; 278 context = createContext(query, { isPrivate: false }); 279 await check_results({ 280 context, 281 matches: [ 282 makeVisitResult(context, { 283 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 284 uri: `http://${query}`, 285 title: `${query}`, 286 iconUri: "page-icon:http://mozilla/", 287 heuristic: true, 288 }), 289 ], 290 }); 291 292 // ipv4 and ipv6 literal addresses should offer to visit. 293 info("visit url, ipv4 literal"); 294 query = "127.0.0.1"; 295 context = createContext(query, { isPrivate: false }); 296 await check_results({ 297 context, 298 matches: [ 299 makeVisitResult(context, { 300 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 301 uri: `http://${query}/`, 302 title: `${query}/`, 303 heuristic: true, 304 }), 305 ], 306 }); 307 308 info("visit url, ipv6 literal"); 309 query = "[2001:db8::1]"; 310 context = createContext(query, { isPrivate: false }); 311 await check_results({ 312 context, 313 matches: [ 314 makeVisitResult(context, { 315 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 316 uri: `http://${query}/`, 317 title: `${query}/`, 318 heuristic: true, 319 }), 320 ], 321 }); 322 323 // Setting keyword.enabled to false should always try to visit. 324 let keywordEnabled = Services.prefs.getBoolPref("keyword.enabled"); 325 Services.prefs.setBoolPref("keyword.enabled", false); 326 registerCleanupFunction(() => { 327 Services.prefs.clearUserPref("keyword.enabled"); 328 }); 329 info("visit url, keyword.enabled = false"); 330 query = "bacon"; 331 context = createContext(query, { isPrivate: false }); 332 await check_results({ 333 context, 334 matches: [ 335 makeVisitResult(context, { 336 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 337 uri: `http://${query}/`, 338 title: `${query}/`, 339 heuristic: true, 340 }), 341 ], 342 }); 343 344 info("visit two word query, keyword.enabled = false"); 345 query = "bacon lovers"; 346 context = createContext(query, { isPrivate: false }); 347 await check_results({ 348 context, 349 matches: [ 350 makeVisitResult(context, { 351 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 352 uri: query, 353 title: query, 354 heuristic: true, 355 }), 356 ], 357 }); 358 359 info("Forced search through a restriction token, keyword.enabled = false"); 360 query = "?bacon"; 361 context = createContext(query, { isPrivate: false }); 362 await check_results({ 363 context, 364 matches: [ 365 makeSearchResult(context, { 366 engineName: SUGGESTIONS_ENGINE_NAME, 367 heuristic: true, 368 query: "bacon", 369 }), 370 ], 371 }); 372 373 info("Forced search through search mode, keyword.enabled = false"); 374 query = "bacon"; 375 context = createContext(query, { 376 isPrivate: false, 377 searchMode: { 378 engineName: SUGGESTIONS_ENGINE_NAME, 379 isGeneralPurposeEngine: false, 380 }, 381 }); 382 await check_results({ 383 context, 384 matches: [ 385 makeSearchResult(context, { 386 engineName: SUGGESTIONS_ENGINE_NAME, 387 heuristic: true, 388 query: "bacon", 389 }), 390 ], 391 }); 392 393 info("Forced search through searchbar, keyword.enabled = false"); 394 query = "bacon"; 395 context = createContext(query, { 396 isPrivate: false, 397 sapName: "searchbar", 398 }); 399 await check_results({ 400 context, 401 matches: [ 402 makeSearchResult(context, { 403 engineName: SUGGESTIONS_ENGINE_NAME, 404 heuristic: true, 405 query: "bacon", 406 }), 407 ], 408 }); 409 410 info("Non-search restriction token and invalid URL, keyword.enabled = false"); 411 query = "bacon *"; 412 context = createContext(query, { isPrivate: false }); 413 await check_results({ 414 context, 415 matches: [], 416 }); 417 418 Services.prefs.setBoolPref("keyword.enabled", true); 419 info("visit two word query, keyword.enabled = true"); 420 query = "bacon lovers"; 421 context = createContext(query, { isPrivate: false }); 422 await check_results({ 423 context, 424 matches: [ 425 makeSearchResult(context, { 426 engineName: SUGGESTIONS_ENGINE_NAME, 427 heuristic: true, 428 }), 429 ], 430 }); 431 432 Services.prefs.setBoolPref("keyword.enabled", keywordEnabled); 433 434 info("visit url, scheme+host"); 435 query = "http://example"; 436 context = createContext(query, { isPrivate: false }); 437 await check_results({ 438 context, 439 matches: [ 440 makeVisitResult(context, { 441 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 442 uri: `${query}/`, 443 title: `${query}/`, 444 heuristic: true, 445 }), 446 ], 447 }); 448 449 info("visit url, scheme+host"); 450 query = "ftp://example"; 451 context = createContext(query, { isPrivate: false }); 452 await check_results({ 453 context, 454 matches: [ 455 makeVisitResult(context, { 456 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 457 uri: `${query}/`, 458 title: `${query}/`, 459 heuristic: true, 460 }), 461 ], 462 }); 463 464 info("visit url, host+port"); 465 query = "example:8080"; 466 context = createContext(query, { isPrivate: false }); 467 await check_results({ 468 context, 469 matches: [ 470 makeVisitResult(context, { 471 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 472 uri: `http://${query}/`, 473 title: `${query}/`, 474 heuristic: true, 475 }), 476 ], 477 }); 478 479 info("numerical operations that look like urls should search"); 480 query = "123/12"; 481 context = createContext(query, { isPrivate: false }); 482 await check_results({ 483 context, 484 matches: [ 485 makeSearchResult(context, { 486 engineName: SUGGESTIONS_ENGINE_NAME, 487 heuristic: true, 488 }), 489 makeCalculatorResult(context, { 490 value: Number((123 / 12).toFixed(8)).toString(), 491 }), 492 ], 493 }); 494 495 info("numerical operations that look like urls should search"); 496 query = "123.12/12.1"; 497 context = createContext(query, { isPrivate: false }); 498 await check_results({ 499 context, 500 matches: [ 501 makeSearchResult(context, { 502 engineName: SUGGESTIONS_ENGINE_NAME, 503 heuristic: true, 504 }), 505 makeCalculatorResult(context, { 506 value: Number((123.12 / 12.1).toFixed(8)).toString(), 507 }), 508 ], 509 }); 510 511 query = "resource:///modules"; 512 context = createContext(query, { isPrivate: false }); 513 await check_results({ 514 context, 515 matches: [ 516 makeVisitResult(context, { 517 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 518 uri: query, 519 title: query, 520 heuristic: true, 521 }), 522 ], 523 }); 524 525 info("access resource://app/modules"); 526 query = "resource://app/modules"; 527 context = createContext(query, { isPrivate: false }); 528 await check_results({ 529 context, 530 matches: [ 531 makeVisitResult(context, { 532 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 533 uri: query, 534 title: query, 535 heuristic: true, 536 }), 537 ], 538 }); 539 540 info("protocol with an extra slash"); 541 query = "http:///"; 542 context = createContext(query, { isPrivate: false }); 543 await check_results({ 544 context, 545 matches: [ 546 makeSearchResult(context, { 547 engineName: SUGGESTIONS_ENGINE_NAME, 548 heuristic: true, 549 }), 550 ], 551 }); 552 553 info("change default engine"); 554 let originalTestEngine = Services.search.getEngineByName( 555 SUGGESTIONS_ENGINE_NAME 556 ); 557 await SearchTestUtils.installSearchExtension({ 558 name: "AliasEngine", 559 keyword: "alias", 560 }); 561 let engine2 = Services.search.getEngineByName("AliasEngine"); 562 Assert.notEqual( 563 Services.search.defaultEngine, 564 engine2, 565 "New engine shouldn't be the current engine yet" 566 ); 567 await Services.search.setDefault( 568 engine2, 569 Ci.nsISearchService.CHANGE_REASON_UNKNOWN 570 ); 571 query = "toronto"; 572 context = createContext(query, { isPrivate: false }); 573 await check_results({ 574 context, 575 matches: [ 576 makeSearchResult(context, { 577 engineName: "AliasEngine", 578 heuristic: true, 579 }), 580 ], 581 }); 582 await Services.search.setDefault( 583 originalTestEngine, 584 Ci.nsISearchService.CHANGE_REASON_UNKNOWN 585 ); 586 587 info( 588 "Leading search-mode restriction tokens are removed from the search result." 589 ); 590 for (let token of UrlbarTokenizer.SEARCH_MODE_RESTRICT) { 591 for (let spaces of TEST_SPACES) { 592 query = token + spaces + "query"; 593 info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) })); 594 let expectedQuery = query.substring(1).trimStart(); 595 context = createContext(query, { isPrivate: false }); 596 info(`Searching for "${query}", expecting "${expectedQuery}"`); 597 let payload = { 598 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 599 heuristic: true, 600 query: expectedQuery, 601 alias: token, 602 }; 603 if (token == UrlbarTokenizer.RESTRICT.SEARCH) { 604 payload.source = UrlbarUtils.RESULT_SOURCE.SEARCH; 605 payload.engineName = SUGGESTIONS_ENGINE_NAME; 606 } 607 await check_results({ 608 context, 609 matches: [makeSearchResult(context, payload)], 610 }); 611 } 612 } 613 614 info( 615 "Leading search-mode restriction tokens are removed from the search result with keyword.enabled = false." 616 ); 617 Services.prefs.setBoolPref("keyword.enabled", false); 618 for (let token of UrlbarTokenizer.SEARCH_MODE_RESTRICT) { 619 for (let spaces of TEST_SPACES) { 620 query = token + spaces + "query"; 621 info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) })); 622 let expectedQuery = query.substring(1).trimStart(); 623 context = createContext(query, { isPrivate: false }); 624 info(`Searching for "${query}", expecting "${expectedQuery}"`); 625 let payload = { 626 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 627 heuristic: true, 628 query: expectedQuery, 629 alias: token, 630 }; 631 if (token == UrlbarTokenizer.RESTRICT.SEARCH) { 632 payload.source = UrlbarUtils.RESULT_SOURCE.SEARCH; 633 payload.engineName = SUGGESTIONS_ENGINE_NAME; 634 } 635 await check_results({ 636 context, 637 matches: [makeSearchResult(context, payload)], 638 }); 639 } 640 } 641 Services.prefs.clearUserPref("keyword.enabled"); 642 643 info( 644 "Leading non-search-mode restriction tokens are not removed from the search result." 645 ); 646 for (let token of Object.values(UrlbarTokenizer.RESTRICT)) { 647 if (UrlbarTokenizer.SEARCH_MODE_RESTRICT.has(token)) { 648 continue; 649 } 650 for (let spaces of TEST_SPACES) { 651 query = token + spaces + "query"; 652 info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) })); 653 let expectedQuery = query; 654 context = createContext(query, { isPrivate: false }); 655 info(`Searching for "${query}", expecting "${expectedQuery}"`); 656 await check_results({ 657 context, 658 matches: [ 659 makeSearchResult(context, { 660 heuristic: true, 661 query: expectedQuery, 662 engineName: SUGGESTIONS_ENGINE_NAME, 663 }), 664 ], 665 }); 666 } 667 } 668 669 info( 670 "Test the format inputed is user@host, and the host is in domainwhitelist" 671 ); 672 Services.prefs.setBoolPref("browser.fixup.domainwhitelist.test-host", true); 673 registerCleanupFunction(() => { 674 Services.prefs.clearUserPref("browser.fixup.domainwhitelist.test-host"); 675 }); 676 677 query = "any@test-host"; 678 context = createContext(query, { isPrivate: false }); 679 await check_results({ 680 context, 681 matches: [ 682 makeVisitResult(context, { 683 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 684 uri: `http://${query}/`, 685 title: `${query}/`, 686 heuristic: true, 687 }), 688 makeSearchResult(context, { 689 engineName: SUGGESTIONS_ENGINE_NAME, 690 }), 691 ], 692 }); 693 694 info( 695 "Test the format inputed is user@host, but the host is not in domainwhitelist" 696 ); 697 query = "any@not-host"; 698 context = createContext(query, { isPrivate: false }); 699 await check_results({ 700 context, 701 matches: [ 702 makeSearchResult(context, { 703 heuristic: true, 704 query, 705 engineName: SUGGESTIONS_ENGINE_NAME, 706 }), 707 ], 708 }); 709 710 info( 711 "Test if the format of user:pass@host is handled as visit even if the host is not in domainwhitelist" 712 ); 713 query = "user:pass@not-host"; 714 context = createContext(query, { isPrivate: false }); 715 await check_results({ 716 context, 717 matches: [ 718 makeVisitResult(context, { 719 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 720 uri: "http://user:pass@not-host/", 721 title: "user:pass@not-host/", 722 heuristic: true, 723 }), 724 ], 725 }); 726 727 info("Test if the format of user@ipaddress is handled as visit"); 728 query = "user@192.168.0.1"; 729 context = createContext(query, { isPrivate: false }); 730 await check_results({ 731 context, 732 matches: [ 733 makeVisitResult(context, { 734 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 735 uri: "http://user@192.168.0.1/", 736 title: "user@192.168.0.1/", 737 heuristic: true, 738 }), 739 makeSearchResult(context, { 740 heuristic: false, 741 query, 742 engineName: SUGGESTIONS_ENGINE_NAME, 743 }), 744 ], 745 }); 746 747 await PlacesUtils.history.clear(); 748 // Check that punycode results are properly decoded before being displayed. 749 info("visit url, host matching visited host but not visited url"); 750 await PlacesTestUtils.addVisits([ 751 { 752 uri: Services.io.newURI("http://test.пример.com/"), 753 title: "test.пример.com", 754 transition: PlacesUtils.history.TRANSITION_TYPED, 755 }, 756 ]); 757 context = createContext("test", { isPrivate: false }); 758 await check_results({ 759 context, 760 matches: [ 761 makeVisitResult(context, { 762 source: UrlbarUtils.RESULT_SOURCE.HISTORY, 763 uri: `http://test.xn--e1afmkfd.com/`, 764 title: "test.пример.com", 765 heuristic: true, 766 iconUri: "page-icon:http://test.xn--e1afmkfd.com/", 767 }), 768 ], 769 }); 770 await PlacesUtils.history.clear(); 771 }); 772 773 add_task(async function dont_fixup_urls_with_at_symbol() { 774 info("don't fixup search string if it contains no protocol and spaces."); 775 let query = "Lorem Ipsum @mozilla.org"; 776 let context = createContext(query, { isPrivate: false }); 777 await check_results({ 778 context, 779 matches: [ 780 makeSearchResult(context, { 781 engineName: SUGGESTIONS_ENGINE_NAME, 782 heuristic: true, 783 }), 784 ], 785 }); 786 787 query = "http://Lorem Ipsum @mozilla.org"; 788 context = createContext(query, { isPrivate: false }); 789 await check_results({ 790 context, 791 matches: [ 792 makeVisitResult(context, { 793 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 794 uri: `http://Lorem%20Ipsum%20@mozilla.org/`, 795 title: `${query}/`, 796 heuristic: true, 797 }), 798 ], 799 }); 800 query = "https://Lorem Ipsum @mozilla.org"; 801 context = createContext(query, { isPrivate: false }); 802 await check_results({ 803 context, 804 matches: [ 805 makeVisitResult(context, { 806 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 807 uri: `https://Lorem%20Ipsum%20@mozilla.org/`, 808 title: `${query}/`, 809 heuristic: true, 810 }), 811 ], 812 }); 813 814 query = "LoremIpsum@mozilla.org"; 815 context = createContext(query, { isPrivate: false }); 816 await check_results({ 817 context, 818 matches: [ 819 makeVisitResult(context, { 820 source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, 821 uri: `http://${query}/`, 822 title: `${query}/`, 823 heuristic: true, 824 }), 825 makeSearchResult(context, { 826 engineName: SUGGESTIONS_ENGINE_NAME, 827 }), 828 ], 829 }); 830 831 query = ""; 832 context = createContext(query, { isPrivate: false }); 833 await check_results({ 834 context, 835 matches: [], 836 }); 837 }); 838 839 /** 840 * Returns an array of code points in the given string. Each code point is 841 * returned as a hexidecimal string. 842 * 843 * @param {string} str 844 * The code points of this string will be returned. 845 * @returns {Array} 846 * Array of code points in the string, where each is a hexidecimal string. 847 */ 848 function codePoints(str) { 849 return str.split("").map(s => s.charCodeAt(0).toString(16)); 850 }