FeatureCalloutMessages.sys.mjs (46524B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // Eventually, make this a messaging system 6 // provider instead of adding these message 7 // into OnboardingMessageProvider.sys.mjs 8 const PDFJS_PREF = "browser.pdfjs.feature-tour"; 9 // Empty screens are included as placeholders to ensure step 10 // indicator shows the correct number of total steps in the tour 11 const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000; 12 13 // Generate a JEXL targeting string based on the `complete` property being true 14 // in a given Feature Callout tour progress preference value (which is JSON). 15 const matchIncompleteTargeting = (prefName, defaultValue = false) => { 16 // regExpMatch() is a JEXL filter expression. Here we check if 'complete' 17 // exists in the pref's value, and returns true if the tour is incomplete. 18 const prefVal = `'${prefName}' | preferenceValue`; 19 // prefVal might be null if the preference doesn't exist. in this case, don't 20 // try to pipe into regExpMatch. 21 const completeMatch = `${prefVal} | regExpMatch('(?<=complete":)(.*)(?=})')`; 22 return `((${prefVal}) ? ((${completeMatch}) ? (${completeMatch}[1] != "true") : ${String( 23 defaultValue 24 )}) : ${String(defaultValue)})`; 25 }; 26 27 // Generate a JEXL targeting string based on the current screen id found in a 28 // given Feature Callout tour progress preference. 29 const matchCurrentScreenTargeting = (prefName, screenIdRegEx = ".*") => { 30 // regExpMatch() is a JEXL filter expression. Here we check if 'screen' exists 31 // in the pref's value, and if it matches the screenIdRegEx. Returns 32 // null otherwise. 33 const prefVal = `'${prefName}' | preferenceValue`; 34 const screenMatch = `${prefVal} | regExpMatch('(?<=screen"\s*:)\s*"(${screenIdRegEx})(?="\s*,)')`; 35 const screenValMatches = `(${screenMatch}) ? !!(${screenMatch}[1]) : false`; 36 return `(${screenValMatches})`; 37 }; 38 39 /** 40 * add24HourImpressionJEXLTargeting - 41 * Creates a "hasn't been viewed in > 24 hours" 42 * JEXL string and adds it to each message specified 43 * 44 * @param {Array} messageIds - IDs of messages that the targeting string will be added to 45 * @param {string} prefix - The prefix of messageIDs that will used to create the JEXL string 46 * @param {Array} messages - The array of messages that will be edited 47 * @returns {Array} - The array of messages with the appropriate targeting strings edited 48 */ 49 function add24HourImpressionJEXLTargeting( 50 messageIds, 51 prefix, 52 uneditedMessages 53 ) { 54 let noImpressionsIn24HoursString = uneditedMessages 55 .filter(message => message.id.startsWith(prefix)) 56 .map( 57 message => 58 // If the last impression is null or if epoch time 59 // of the impression is < current time - 24hours worth of MS 60 `(messageImpressions.${message.id}[messageImpressions.${ 61 message.id 62 } | length - 1] == null || messageImpressions.${ 63 message.id 64 }[messageImpressions.${message.id} | length - 1] < ${ 65 Date.now() - ONE_DAY_IN_MS 66 })` 67 ) 68 .join(" && "); 69 70 // We're appending the string here instead of using 71 // template strings to avoid a recursion error from 72 // using the 'messages' variable within itself 73 return uneditedMessages.map(message => { 74 if (messageIds.includes(message.id)) { 75 message.targeting += `&& ${noImpressionsIn24HoursString}`; 76 } 77 78 return message; 79 }); 80 } 81 82 // Exporting the about:firefoxview messages as a method here 83 // acts as a safety guard against mutations of the original objects 84 const MESSAGES = () => { 85 let messages = [ 86 { 87 id: "TAB_GROUP_ONBOARDING_CALLOUT", 88 template: "feature_callout", 89 groups: ["cfr"], 90 content: { 91 id: "TAB_GROUP_ONBOARDING_CALLOUT", 92 template: "multistage", 93 backdrop: "transparent", 94 transitions: false, 95 screens: [ 96 { 97 id: "TAB_GROUP_ONBOARDING_CALLOUT_HORIZONTAL", 98 anchors: [ 99 { 100 selector: 101 "#tabbrowser-tabs:not([overflow]) .tab-content[selected]:not([pinned])", 102 panel_position: { 103 anchor_attachment: "bottomcenter", 104 callout_attachment: "topright", 105 }, 106 }, 107 { 108 selector: 109 "#tabbrowser-tabs:not([overflow]) tab:not([pinned]):last-of-type", 110 panel_position: { 111 anchor_attachment: "bottomcenter", 112 callout_attachment: "topright", 113 }, 114 }, 115 { 116 selector: 117 "#tabbrowser-tabs:not([overflow]) #tabs-newtab-button", 118 panel_position: { 119 anchor_attachment: "bottomcenter", 120 callout_attachment: "topright", 121 }, 122 }, 123 { 124 selector: "#tabbrowser-tabs", 125 panel_position: { 126 anchor_attachment: "bottomcenter", 127 callout_attachment: "topright", 128 }, 129 }, 130 ], 131 content: { 132 position: "callout", 133 width: "333px", 134 padding: 16, 135 logo: { 136 imageURL: 137 "chrome://browser/content/asrouter/assets/tabgroups/hort-animated-light.svg", 138 darkModeImageURL: 139 "chrome://browser/content/asrouter/assets/tabgroups/hort-animated-dark.svg", 140 reducedMotionImageURL: 141 "chrome://browser/content/asrouter/assets/tabgroups/hort-static-light.svg", 142 darkModeReducedMotionImageURL: 143 "chrome://browser/content/asrouter/assets/tabgroups/hort-static-dark.svg", 144 height: "172px", 145 width: "300px", 146 }, 147 title: { 148 string_id: "tab-groups-onboarding-feature-callout-title", 149 }, 150 subtitle: { 151 string_id: "tab-groups-onboarding-feature-callout-subtitle", 152 }, 153 dismiss_button: { 154 action: { 155 dismiss: true, 156 }, 157 background: true, 158 size: "small", 159 marginInline: "0 20px", 160 marginBlock: "20px 0", 161 }, 162 }, 163 }, 164 ], 165 }, 166 targeting: 167 "tabsClosedCount >= 1 && currentTabsOpen >= 8 && ('browser.tabs.groups.enabled' | preferenceValue) && (!'sidebar.verticalTabs' | preferenceValue) && currentTabGroups == 0 && savedTabGroups == 0 && !activeNotifications", 168 trigger: { 169 id: "nthTabClosed", 170 }, 171 frequency: { 172 lifetime: 1, 173 }, 174 skip_in_tests: "it's not tested in automation", 175 }, 176 { 177 id: "TAB_GROUP_ONBOARDING_CALLOUT", 178 template: "feature_callout", 179 groups: ["cfr"], 180 content: { 181 id: "TAB_GROUP_ONBOARDING_CALLOUT", 182 template: "multistage", 183 backdrop: "transparent", 184 transitions: false, 185 screens: [ 186 { 187 id: "TAB_GROUP_ONBOARDING_CALLOUT_VERTICAL", 188 anchors: [ 189 { 190 selector: 191 "#tabbrowser-tabs:not([overflow]) .tab-content[selected]:not([pinned])", 192 panel_position: { 193 anchor_attachment: "rightcenter", 194 callout_attachment: "topleft", 195 }, 196 }, 197 { 198 selector: 199 "#tabbrowser-tabs:not([overflow]) tab:not([pinned]):last-of-type", 200 panel_position: { 201 anchor_attachment: "rightcenter", 202 callout_attachment: "topleft", 203 }, 204 }, 205 { 206 selector: 207 "#tabbrowser-tabs:not([overflow]) #tabs-newtab-button", 208 panel_position: { 209 anchor_attachment: "rightcenter", 210 callout_attachment: "topleft", 211 }, 212 }, 213 { 214 selector: "#tabbrowser-tabs", 215 panel_position: { 216 anchor_attachment: "rightcenter", 217 callout_attachment: "topleft", 218 }, 219 }, 220 ], 221 content: { 222 position: "callout", 223 width: "333px", 224 padding: 16, 225 logo: { 226 imageURL: 227 "chrome://browser/content/asrouter/assets/tabgroups/vert-animated-light.svg", 228 darkModeImageURL: 229 "chrome://browser/content/asrouter/assets/tabgroups/vert-animated-dark.svg", 230 reducedMotionImageURL: 231 "chrome://browser/content/asrouter/assets/tabgroups/vert-static-light.svg", 232 darkModeReducedMotionImageURL: 233 "chrome://browser/content/asrouter/assets/tabgroups/vert-static-dark.svg", 234 height: "172px", 235 width: "300px", 236 }, 237 title: { 238 string_id: "tab-groups-onboarding-feature-callout-title", 239 }, 240 subtitle: { 241 string_id: "tab-groups-onboarding-feature-callout-subtitle", 242 }, 243 dismiss_button: { 244 action: { 245 dismiss: true, 246 }, 247 background: true, 248 size: "small", 249 marginInline: "0 20px", 250 marginBlock: "20px 0", 251 }, 252 }, 253 }, 254 ], 255 }, 256 targeting: 257 "tabsClosedCount >= 1 && currentTabsOpen >= 8 && ('browser.tabs.groups.enabled' | preferenceValue) && ('sidebar.revamp' | preferenceValue) && ('sidebar.verticalTabs' | preferenceValue) && currentTabGroups == 0 && savedTabGroups == 0 && !activeNotifications", 258 trigger: { 259 id: "nthTabClosed", 260 }, 261 frequency: { 262 lifetime: 1, 263 }, 264 skip_in_tests: "it's not tested in automation", 265 }, 266 // Appears the first time a user uses the "save and close" action on a tab group, 267 // anchored to the alltabs-button. Will only show if at least an hour has passed 268 // since the CREATE_TAB_GROUP callout showed. 269 { 270 id: "SAVE_TAB_GROUP_ONBOARDING_CALLOUT", 271 template: "feature_callout", 272 groups: [], 273 content: { 274 id: "SAVE_TAB_GROUP_ONBOARDING_CALLOUT", 275 template: "multistage", 276 backdrop: "transparent", 277 transitions: false, 278 screens: [ 279 { 280 id: "SAVE_TAB_GROUP_ONBOARDING_CALLOUT_ALLTABS_BUTTON", 281 anchors: [ 282 { 283 selector: "#alltabs-button", 284 panel_position: { 285 anchor_attachment: "bottomcenter", 286 callout_attachment: "topright", 287 }, 288 }, 289 ], 290 content: { 291 position: "callout", 292 padding: 16, 293 width: "330px", 294 title_logo: { 295 imageURL: 296 "chrome://browser/content/asrouter/assets/smiling-fox-icon.svg", 297 width: "24px", 298 height: "24px", 299 marginInline: "0 16px", 300 alignment: "top", 301 }, 302 title: { 303 string_id: "tab-groups-onboarding-saved-groups-title-3", 304 }, 305 primary_button: { 306 label: { 307 string_id: "tab-groups-onboarding-dismiss", 308 }, 309 action: { 310 dismiss: true, 311 }, 312 }, 313 }, 314 }, 315 ], 316 }, 317 targeting: 318 "('browser.tabs.groups.enabled' | preferenceValue) && userPrefs.cfrFeatures && (!messageImpressions.CREATE_TAB_GROUP_ONBOARDING_CALLOUT[messageImpressions.CREATE_TAB_GROUP_ONBOARDING_CALLOUT | length - 1] || messageImpressions.CREATE_TAB_GROUP_ONBOARDING_CALLOUT[messageImpressions.CREATE_TAB_GROUP_ONBOARDING_CALLOUT | length - 1] < currentDate|date - 3600000) && alltabsButtonAreaType != null", 319 trigger: { 320 id: "tabGroupSaved", 321 }, 322 frequency: { 323 lifetime: 1, 324 }, 325 skip_in_tests: "it's not tested in automation", 326 }, 327 // Appears the first time a user uses the "save and close" action on a tab group, 328 // if the alltabs-button has been removed. Anchored to the urlbar. Will only show 329 // if CREATE_TAB_GROUP callout has not shown, or at least an hour has passed since 330 // the CREATE_TAB_GROUP callout showed. 331 { 332 id: "SAVE_TAB_GROUP_ONBOARDING_CALLOUT", 333 template: "feature_callout", 334 groups: [], 335 content: { 336 id: "SAVE_TAB_GROUP_ONBOARDING_CALLOUT", 337 template: "multistage", 338 backdrop: "transparent", 339 transitions: false, 340 screens: [ 341 { 342 id: "SAVE_TAB_GROUP_ONBOARDING_CALLOUT_URLBAR", 343 anchors: [ 344 { 345 selector: ".urlbar-input-box", 346 panel_position: { 347 anchor_attachment: "bottomcenter", 348 callout_attachment: "topcenter", 349 }, 350 }, 351 ], 352 content: { 353 position: "callout", 354 padding: 16, 355 width: "330px", 356 title_logo: { 357 imageURL: 358 "chrome://browser/content/asrouter/assets/smiling-fox-icon.svg", 359 width: "24px", 360 height: "24px", 361 marginInline: "0 16px", 362 alignment: "top", 363 }, 364 title: { 365 string_id: 366 "tab-groups-onboarding-saved-groups-no-alltabs-button-title-2", 367 }, 368 primary_button: { 369 label: { 370 string_id: "tab-groups-onboarding-dismiss", 371 }, 372 action: { 373 dismiss: true, 374 }, 375 }, 376 }, 377 }, 378 ], 379 }, 380 targeting: 381 "('browser.tabs.groups.enabled' | preferenceValue) && userPrefs.cfrFeatures && (!messageImpressions.CREATE_TAB_GROUP_ONBOARDING_CALLOUT[messageImpressions.CREATE_TAB_GROUP_ONBOARDING_CALLOUT | length - 1] || messageImpressions.CREATE_TAB_GROUP_ONBOARDING_CALLOUT[messageImpressions.CREATE_TAB_GROUP_ONBOARDING_CALLOUT | length - 1] < currentDate|date - 3600000) && alltabsButtonAreaType == null", 382 trigger: { 383 id: "tabGroupSaved", 384 }, 385 frequency: { 386 lifetime: 1, 387 }, 388 skip_in_tests: "it's not tested in automation", 389 }, 390 // Appears the first time a user creates a tab group, after clicking the "Done" 391 // button. Anchored to the alltabs-button. Will only show if the SAVE_TAB_GROUP 392 // callout has not shown, or if at least an hour has passed 393 // since the SAVE_TAB_GROUP callout showed. 394 { 395 id: "CREATE_TAB_GROUP_ONBOARDING_CALLOUT", 396 template: "feature_callout", 397 groups: [], 398 content: { 399 id: "CREATE_TAB_GROUP_ONBOARDING_CALLOUT", 400 template: "multistage", 401 backdrop: "transparent", 402 transitions: false, 403 screens: [ 404 { 405 id: "CREATE_TAB_GROUP_ONBOARDING_CALLOUT_ALLTABS_BUTTON", 406 anchors: [ 407 { 408 selector: "#alltabs-button", 409 panel_position: { 410 anchor_attachment: "bottomcenter", 411 callout_attachment: "topright", 412 }, 413 }, 414 ], 415 content: { 416 position: "callout", 417 padding: 16, 418 width: "330px", 419 title_logo: { 420 imageURL: 421 "chrome://browser/content/asrouter/assets/smiling-fox-icon.svg", 422 width: "24px", 423 height: "24px", 424 marginInline: "0 16px", 425 alignment: "top", 426 }, 427 title: { 428 string_id: "tab-groups-onboarding-create-group-title-3", 429 }, 430 primary_button: { 431 label: { 432 string_id: "tab-groups-onboarding-dismiss", 433 }, 434 action: { 435 dismiss: true, 436 }, 437 }, 438 }, 439 }, 440 ], 441 }, 442 targeting: 443 "('browser.tabs.groups.enabled' | preferenceValue) && userPrefs.cfrFeatures && (!messageImpressions.SAVE_TAB_GROUP_ONBOARDING_CALLOUT[messageImpressions.SAVE_TAB_GROUP_ONBOARDING_CALLOUT | length - 1] || messageImpressions.SAVE_TAB_GROUP_ONBOARDING_CALLOUT[messageImpressions.SAVE_TAB_GROUP_ONBOARDING_CALLOUT | length - 1] < currentDate|date - 3600000) && alltabsButtonAreaType != null", 444 trigger: { 445 id: "tabGroupCreated", 446 }, 447 frequency: { 448 lifetime: 1, 449 }, 450 skip_in_tests: "it's not tested in automation", 451 }, 452 // Appears the first time a user creates a tab group, after clicking the "Done" 453 // button, if the alltabs-button has been removed. Anchored to the urlbar. Will 454 // only show if the SAVE_TAB_GROUP callout has not shown, or if at least an hour 455 // has passed since the SAVE_TAB_GROUP callout showed. 456 { 457 id: "CREATE_TAB_GROUP_ONBOARDING_CALLOUT", 458 template: "feature_callout", 459 groups: [], 460 content: { 461 id: "CREATE_TAB_GROUP_ONBOARDING_CALLOUT", 462 template: "multistage", 463 backdrop: "transparent", 464 transitions: false, 465 screens: [ 466 { 467 id: "CREATE_TAB_GROUP_ONBOARDING_CALLOUT_URLBAR", 468 anchors: [ 469 { 470 selector: ".urlbar-input-box", 471 panel_position: { 472 anchor_attachment: "bottomcenter", 473 callout_attachment: "topcenter", 474 }, 475 }, 476 ], 477 content: { 478 position: "callout", 479 padding: 16, 480 width: "330px", 481 title_logo: { 482 imageURL: 483 "chrome://browser/content/asrouter/assets/smiling-fox-icon.svg", 484 width: "24px", 485 height: "24px", 486 marginInline: "0 16px", 487 alignment: "top", 488 }, 489 title: { 490 string_id: 491 "tab-groups-onboarding-create-group-no-alltabs-button-title", 492 }, 493 primary_button: { 494 label: { 495 string_id: "tab-groups-onboarding-dismiss", 496 }, 497 action: { 498 dismiss: true, 499 }, 500 }, 501 }, 502 }, 503 ], 504 }, 505 targeting: 506 "('browser.tabs.groups.enabled' | preferenceValue) && userPrefs.cfrFeatures && (!messageImpressions.SAVE_TAB_GROUP_ONBOARDING_CALLOUT[messageImpressions.SAVE_TAB_GROUP_ONBOARDING_CALLOUT | length - 1] || messageImpressions.SAVE_TAB_GROUP_ONBOARDING_CALLOUT[messageImpressions.SAVE_TAB_GROUP_ONBOARDING_CALLOUT | length - 1] < currentDate|date - 3600000) && alltabsButtonAreaType == null", 507 trigger: { 508 id: "tabGroupCreated", 509 }, 510 frequency: { 511 lifetime: 1, 512 }, 513 skip_in_tests: "it's not tested in automation", 514 }, 515 // Appears after a browser restart if Session Restore is disabled, to direct 516 // users to tab groups that were saved automatically. Anchored to the alltabs-button. 517 { 518 id: "SESSION_RESTORE_TAB_GROUP_CALLOUT", 519 template: "feature_callout", 520 groups: [], 521 content: { 522 id: "SESSION_RESTORE_TAB_GROUP_CALLOUT", 523 template: "multistage", 524 backdrop: "transparent", 525 transitions: false, 526 screens: [ 527 { 528 id: "SESSION_RESTORE_TAB_GROUP_CALLOUT_ALLTABS_BUTTON", 529 anchors: [ 530 { 531 selector: "#alltabs-button", 532 panel_position: { 533 anchor_attachment: "bottomcenter", 534 callout_attachment: "topright", 535 }, 536 }, 537 ], 538 content: { 539 position: "callout", 540 padding: 16, 541 width: "330px", 542 title_logo: { 543 imageURL: 544 "chrome://browser/content/asrouter/assets/smiling-fox-icon.svg", 545 width: "24px", 546 height: "24px", 547 marginInline: "0 16px", 548 alignment: "top", 549 }, 550 title: { 551 string_id: "tab-groups-onboarding-session-restore-title-2", 552 }, 553 primary_button: { 554 label: { 555 string_id: "tab-groups-onboarding-dismiss", 556 }, 557 action: { 558 dismiss: true, 559 }, 560 }, 561 }, 562 }, 563 ], 564 }, 565 targeting: 566 "('browser.tabs.groups.enabled' | preferenceValue) && userPrefs.cfrFeatures && previousSessionEnd && ('browser.startup.page' | preferenceValue != 3) && savedTabGroups >= 1 && alltabsButtonAreaType != null", 567 trigger: { 568 id: "defaultBrowserCheck", 569 }, 570 priority: 2, 571 frequency: { 572 lifetime: 1, 573 }, 574 skip_in_tests: "not tested in automation", 575 }, 576 // Appears after a browser restart if Session Restore is disabled, to direct 577 // users to tab groups that were saved automatically, for users who have 578 // removed the alltabs button. Anchored to the urlbar. 579 { 580 id: "SESSION_RESTORE_TAB_GROUP_CALLOUT", 581 template: "feature_callout", 582 groups: [], 583 content: { 584 id: "SESSION_RESTORE_TAB_GROUP_CALLOUT", 585 template: "multistage", 586 backdrop: "transparent", 587 transitions: false, 588 screens: [ 589 { 590 id: "SESSION_RESTORE_TAB_GROUP_CALLOUT_URLBAR", 591 anchors: [ 592 { 593 selector: ".urlbar-input-box", 594 panel_position: { 595 anchor_attachment: "bottomcenter", 596 callout_attachment: "topcenter", 597 }, 598 }, 599 ], 600 content: { 601 position: "callout", 602 padding: 16, 603 width: "330px", 604 title_logo: { 605 imageURL: 606 "chrome://browser/content/asrouter/assets/smiling-fox-icon.svg", 607 width: "24px", 608 height: "24px", 609 marginInline: "0 16px", 610 alignment: "top", 611 }, 612 title: { 613 string_id: 614 "tab-groups-onboarding-saved-groups-no-alltabs-button-title-2", 615 }, 616 primary_button: { 617 label: { 618 string_id: "tab-groups-onboarding-dismiss", 619 }, 620 action: { 621 dismiss: true, 622 }, 623 }, 624 }, 625 }, 626 ], 627 }, 628 targeting: 629 "('browser.tabs.groups.enabled' | preferenceValue) && userPrefs.cfrFeatures && previousSessionEnd && ('browser.startup.page' | preferenceValue != 3) && savedTabGroups >= 1 && alltabsButtonAreaType == null", 630 trigger: { 631 id: "defaultBrowserCheck", 632 }, 633 priority: 2, 634 frequency: { 635 lifetime: 1, 636 }, 637 skip_in_tests: "not tested in automation", 638 }, 639 { 640 id: "ADDONS_STAFF_PICK_PT_2", 641 template: "feature_callout", 642 groups: ["cfr"], 643 content: { 644 id: "ADDONS_STAFF_PICK_PT_2", 645 template: "multistage", 646 backdrop: "transparent", 647 transitions: false, 648 screens: [ 649 { 650 id: "ADDONS_STAFF_PICK_PT_2_A", 651 anchors: [ 652 { 653 selector: "#unified-extensions-button", 654 panel_position: { 655 anchor_attachment: "bottomcenter", 656 callout_attachment: "topright", 657 }, 658 arrow_width: "26.9", 659 }, 660 ], 661 content: { 662 position: "callout", 663 width: "310px", 664 padding: 16, 665 title_logo: { 666 imageURL: 667 "chrome://browser/content/asrouter/assets/smiling-fox-icon.svg", 668 width: "24px", 669 height: "24px", 670 marginInline: "4px 14px", 671 }, 672 title: { 673 raw: "Give your browsing a boost", 674 marginInline: "0 48px", 675 }, 676 subtitle: { 677 raw: "Make browsing faster, safer, or just plain fun with Firefox add-ons. See what our staff recommends!", 678 paddingInline: "34px 0", 679 }, 680 primary_button: { 681 label: { 682 raw: "Explore add-ons", 683 }, 684 action: { 685 dismiss: true, 686 type: "OPEN_URL", 687 data: { 688 args: "https://addons.mozilla.org/en-US/firefox/collections/4757633/36d285535db74c6986abbeeed3e214/?page=1&collection_sort=added", 689 where: "tabshifted", 690 }, 691 }, 692 }, 693 dismiss_button: { 694 action: { 695 dismiss: true, 696 }, 697 size: "small", 698 marginInline: "0 14px", 699 marginBlock: "14px 0", 700 }, 701 }, 702 }, 703 ], 704 }, 705 targeting: 706 "userPrefs.cfrAddons && userPrefs.cfrFeatures && localeLanguageCode == 'en' && ((currentDate|date - profileAgeCreated|date) / 86400000 < 28) && !screenImpressions.AW_AMO_INTRODUCE && !willShowDefaultPrompt && !activeNotifications && source == 'newtab' && previousSessionEnd", 707 trigger: { 708 id: "defaultBrowserCheck", 709 }, 710 frequency: { 711 lifetime: 1, 712 }, 713 }, 714 { 715 id: "FIREFOX_VIEW_TAB_PICKUP_REMINDER", 716 template: "feature_callout", 717 content: { 718 id: "FIREFOX_VIEW_TAB_PICKUP_REMINDER", 719 template: "multistage", 720 backdrop: "transparent", 721 transitions: false, 722 disableHistoryUpdates: true, 723 screens: [ 724 { 725 id: "FIREFOX_VIEW_TAB_PICKUP_REMINDER", 726 anchors: [ 727 { 728 selector: "#tab-pickup-container", 729 arrow_position: "top", 730 }, 731 ], 732 content: { 733 position: "callout", 734 title: { 735 string_id: 736 "continuous-onboarding-firefox-view-tab-pickup-title", 737 }, 738 subtitle: { 739 string_id: 740 "continuous-onboarding-firefox-view-tab-pickup-subtitle", 741 }, 742 logo: { 743 imageURL: "chrome://browser/content/callout-tab-pickup.svg", 744 darkModeImageURL: 745 "chrome://browser/content/callout-tab-pickup-dark.svg", 746 height: "128px", 747 }, 748 primary_button: { 749 label: { 750 string_id: "mr1-onboarding-get-started-primary-button-label", 751 }, 752 style: "secondary", 753 action: { 754 type: "CLICK_ELEMENT", 755 navigate: true, 756 data: { 757 selector: 758 "#tab-pickup-container button.primary:not(#error-state-button)", 759 }, 760 }, 761 }, 762 dismiss_button: { 763 action: { 764 navigate: true, 765 }, 766 }, 767 page_event_listeners: [ 768 { 769 params: { 770 type: "toggle", 771 selectors: "#tab-pickup-container", 772 }, 773 action: { reposition: true }, 774 }, 775 ], 776 }, 777 }, 778 ], 779 }, 780 priority: 2, 781 targeting: `source == "about:firefoxview" && "browser.firefox-view.view-count" | preferenceValue > 2 782 && (("identity.fxaccounts.enabled" | preferenceValue == false) || !(("services.sync.engine.tabs" | preferenceValue == true) && ("services.sync.username" | preferenceValue))) && (!messageImpressions.FIREFOX_VIEW_SPOTLIGHT[messageImpressions.FIREFOX_VIEW_SPOTLIGHT | length - 1] || messageImpressions.FIREFOX_VIEW_SPOTLIGHT[messageImpressions.FIREFOX_VIEW_SPOTLIGHT | length - 1] < currentDate|date - ${ONE_DAY_IN_MS})`, 783 frequency: { 784 lifetime: 1, 785 }, 786 trigger: { id: "featureCalloutCheck" }, 787 }, 788 { 789 id: "PDFJS_FEATURE_TOUR_A", 790 template: "feature_callout", 791 content: { 792 id: "PDFJS_FEATURE_TOUR", 793 template: "multistage", 794 backdrop: "transparent", 795 transitions: false, 796 disableHistoryUpdates: true, 797 tour_pref_name: PDFJS_PREF, 798 screens: [ 799 { 800 id: "FEATURE_CALLOUT_1_A", 801 anchors: [ 802 { 803 selector: "hbox#browser", 804 arrow_position: "top-end", 805 absolute_position: { top: "43px", right: "51px" }, 806 }, 807 ], 808 content: { 809 position: "callout", 810 title: { 811 string_id: "callout-pdfjs-edit-title", 812 }, 813 subtitle: { 814 string_id: "callout-pdfjs-edit-body-a", 815 }, 816 primary_button: { 817 label: { 818 string_id: "callout-pdfjs-edit-button", 819 }, 820 style: "secondary", 821 action: { 822 type: "SET_PREF", 823 data: { 824 pref: { 825 name: PDFJS_PREF, 826 value: JSON.stringify({ 827 screen: "FEATURE_CALLOUT_2_A", 828 complete: false, 829 }), 830 }, 831 }, 832 }, 833 }, 834 dismiss_button: { 835 action: { 836 type: "SET_PREF", 837 data: { 838 pref: { 839 name: PDFJS_PREF, 840 value: JSON.stringify({ 841 screen: "", 842 complete: true, 843 }), 844 }, 845 }, 846 }, 847 }, 848 }, 849 }, 850 { 851 id: "FEATURE_CALLOUT_2_A", 852 anchors: [ 853 { 854 selector: "hbox#browser", 855 arrow_position: "top-end", 856 absolute_position: { top: "43px", right: "23px" }, 857 }, 858 ], 859 content: { 860 position: "callout", 861 title: { 862 string_id: "callout-pdfjs-draw-title", 863 }, 864 subtitle: { 865 string_id: "callout-pdfjs-draw-body-a", 866 }, 867 primary_button: { 868 label: { 869 string_id: "callout-pdfjs-draw-button", 870 }, 871 style: "secondary", 872 action: { 873 type: "SET_PREF", 874 data: { 875 pref: { 876 name: PDFJS_PREF, 877 value: JSON.stringify({ 878 screen: "", 879 complete: true, 880 }), 881 }, 882 }, 883 }, 884 }, 885 dismiss_button: { 886 action: { 887 type: "SET_PREF", 888 data: { 889 pref: { 890 name: PDFJS_PREF, 891 value: JSON.stringify({ 892 screen: "", 893 complete: true, 894 }), 895 }, 896 }, 897 }, 898 }, 899 }, 900 }, 901 ], 902 }, 903 priority: 1, 904 targeting: `source == "open" && ${matchCurrentScreenTargeting( 905 PDFJS_PREF, 906 "FEATURE_CALLOUT_[0-9]_A" 907 )} && ${matchIncompleteTargeting(PDFJS_PREF)}`, 908 trigger: { id: "pdfJsFeatureCalloutCheck" }, 909 }, 910 { 911 id: "PDFJS_FEATURE_TOUR_B", 912 template: "feature_callout", 913 content: { 914 id: "PDFJS_FEATURE_TOUR", 915 template: "multistage", 916 backdrop: "transparent", 917 transitions: false, 918 disableHistoryUpdates: true, 919 tour_pref_name: PDFJS_PREF, 920 screens: [ 921 { 922 id: "FEATURE_CALLOUT_1_B", 923 anchors: [ 924 { 925 selector: "hbox#browser", 926 arrow_position: "top-end", 927 absolute_position: { top: "43px", right: "51px" }, 928 }, 929 ], 930 content: { 931 position: "callout", 932 title: { 933 string_id: "callout-pdfjs-edit-title", 934 }, 935 subtitle: { 936 string_id: "callout-pdfjs-edit-body-b", 937 }, 938 primary_button: { 939 label: { 940 string_id: "callout-pdfjs-edit-button", 941 }, 942 style: "secondary", 943 action: { 944 type: "SET_PREF", 945 data: { 946 pref: { 947 name: PDFJS_PREF, 948 value: JSON.stringify({ 949 screen: "FEATURE_CALLOUT_2_B", 950 complete: false, 951 }), 952 }, 953 }, 954 }, 955 }, 956 dismiss_button: { 957 action: { 958 type: "SET_PREF", 959 data: { 960 pref: { 961 name: PDFJS_PREF, 962 value: JSON.stringify({ 963 screen: "", 964 complete: true, 965 }), 966 }, 967 }, 968 }, 969 }, 970 }, 971 }, 972 { 973 id: "FEATURE_CALLOUT_2_B", 974 anchors: [ 975 { 976 selector: "hbox#browser", 977 arrow_position: "top-end", 978 absolute_position: { top: "43px", right: "23px" }, 979 }, 980 ], 981 content: { 982 position: "callout", 983 title: { 984 string_id: "callout-pdfjs-draw-title", 985 }, 986 subtitle: { 987 string_id: "callout-pdfjs-draw-body-b", 988 }, 989 primary_button: { 990 label: { 991 string_id: "callout-pdfjs-draw-button", 992 }, 993 style: "secondary", 994 action: { 995 type: "SET_PREF", 996 data: { 997 pref: { 998 name: PDFJS_PREF, 999 value: JSON.stringify({ 1000 screen: "", 1001 complete: true, 1002 }), 1003 }, 1004 }, 1005 }, 1006 }, 1007 dismiss_button: { 1008 action: { 1009 type: "SET_PREF", 1010 data: { 1011 pref: { 1012 name: PDFJS_PREF, 1013 value: JSON.stringify({ 1014 screen: "", 1015 complete: true, 1016 }), 1017 }, 1018 }, 1019 }, 1020 }, 1021 }, 1022 }, 1023 ], 1024 }, 1025 priority: 1, 1026 targeting: `source == "open" && ${matchCurrentScreenTargeting( 1027 PDFJS_PREF, 1028 "FEATURE_CALLOUT_[0-9]_B" 1029 )} && ${matchIncompleteTargeting(PDFJS_PREF)}`, 1030 trigger: { id: "pdfJsFeatureCalloutCheck" }, 1031 }, 1032 // cookie banner reduction onboarding 1033 { 1034 id: "CFR_COOKIEBANNER", 1035 groups: ["cfr"], 1036 template: "feature_callout", 1037 content: { 1038 id: "CFR_COOKIEBANNER", 1039 template: "multistage", 1040 backdrop: "transparent", 1041 transitions: false, 1042 disableHistoryUpdates: true, 1043 screens: [ 1044 { 1045 id: "COOKIEBANNER_CALLOUT", 1046 anchors: [ 1047 { 1048 selector: "#tracking-protection-icon-container", 1049 panel_position: { 1050 callout_attachment: "topleft", 1051 anchor_attachment: "bottomcenter", 1052 }, 1053 }, 1054 ], 1055 content: { 1056 position: "callout", 1057 autohide: true, 1058 title: { 1059 string_id: "cookie-banner-blocker-onboarding-header", 1060 paddingInline: "12px 0", 1061 }, 1062 subtitle: { 1063 string_id: "cookie-banner-blocker-onboarding-body", 1064 paddingInline: "34px 0", 1065 }, 1066 title_logo: { 1067 alignment: "top", 1068 height: "20px", 1069 width: "20px", 1070 imageURL: 1071 "chrome://browser/skin/controlcenter/3rdpartycookies-blocked.svg", 1072 }, 1073 dismiss_button: { 1074 size: "small", 1075 action: { dismiss: true }, 1076 }, 1077 additional_button: { 1078 label: { 1079 string_id: "cookie-banner-blocker-onboarding-learn-more", 1080 marginInline: "34px 0", 1081 }, 1082 style: "link", 1083 alignment: "start", 1084 action: { 1085 type: "OPEN_URL", 1086 data: { 1087 args: "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/cookie-banner-reduction", 1088 where: "tabshifted", 1089 }, 1090 }, 1091 }, 1092 }, 1093 }, 1094 ], 1095 }, 1096 frequency: { 1097 lifetime: 1, 1098 }, 1099 skip_in_tests: "it's not tested in automation", 1100 trigger: { 1101 id: "cookieBannerHandled", 1102 }, 1103 targeting: `'cookiebanners.ui.desktop.enabled'|preferenceValue == true && 'cookiebanners.ui.desktop.showCallout'|preferenceValue == true && 'browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features' | preferenceValue != false`, 1104 }, 1105 { 1106 id: "FX_VIEW_DISCOVERABILITY_ALL_USERS", 1107 template: "feature_callout", 1108 groups: ["cfr"], 1109 content: { 1110 id: "FX_VIEW_DISCOVERABILITY_ALL_USERS", 1111 template: "multistage", 1112 backdrop: "transparent", 1113 transitions: false, 1114 screens: [ 1115 { 1116 id: "FX_VIEW_DISCOVERABILITY_ALL_USERS_SCREEN", 1117 anchors: [ 1118 { 1119 selector: "#firefox-view-button", 1120 panel_position: { 1121 anchor_attachment: "bottomcenter", 1122 callout_attachment: "topleft", 1123 }, 1124 no_open_on_anchor: true, 1125 arrow_width: "15.5563", 1126 }, 1127 ], 1128 content: { 1129 position: "callout", 1130 width: "342px", 1131 padding: 16, 1132 page_event_listeners: [ 1133 { 1134 params: { 1135 type: "click", 1136 selectors: "#firefox-view-button", 1137 }, 1138 action: { 1139 dismiss: true, 1140 }, 1141 }, 1142 ], 1143 title_logo: { 1144 imageURL: 1145 "chrome://browser/content/asrouter/assets/fox-question-mark-icon.svg", 1146 width: "25px", 1147 height: "29px", 1148 marginInline: "4px 14px", 1149 alignment: "top", 1150 }, 1151 title: { 1152 string_id: "fx-view-discoverability-title", 1153 marginInline: "0 16px", 1154 }, 1155 subtitle: { 1156 string_id: "fx-view-discoverability-subtitle", 1157 paddingInline: "34px 0", 1158 marginBlock: "-8px -4px", 1159 }, 1160 additional_button: { 1161 label: { 1162 string_id: "fx-view-discoverability-secondary-button-label", 1163 }, 1164 style: "secondary", 1165 action: { 1166 type: "BLOCK_MESSAGE", 1167 data: { 1168 id: "FX_VIEW_DISCOVERABILITY_ALL_USERS", 1169 }, 1170 dismiss: true, 1171 }, 1172 }, 1173 secondary_button: { 1174 label: { 1175 string_id: "fx-view-discoverability-primary-button-label", 1176 }, 1177 style: "primary", 1178 action: { 1179 type: "OPEN_FIREFOX_VIEW", 1180 navigate: true, 1181 }, 1182 }, 1183 submenu_button: { 1184 submenu: [ 1185 { 1186 type: "action", 1187 label: { 1188 string_id: "split-dismiss-button-dont-show-option", 1189 }, 1190 action: { 1191 type: "BLOCK_MESSAGE", 1192 data: { 1193 id: "FX_VIEW_DISCOVERABILITY_ALL_USERS", 1194 }, 1195 dismiss: true, 1196 }, 1197 id: "block_recommendation", 1198 }, 1199 { 1200 type: "action", 1201 label: { 1202 string_id: "split-dismiss-button-show-fewer-option", 1203 }, 1204 action: { 1205 type: "MULTI_ACTION", 1206 dismiss: true, 1207 data: { 1208 actions: [ 1209 { 1210 type: "SET_PREF", 1211 data: { 1212 pref: { 1213 name: "messaging-system-action.firefox-view-recommendations", 1214 value: true, 1215 }, 1216 }, 1217 }, 1218 { 1219 type: "BLOCK_MESSAGE", 1220 data: { 1221 id: "FX_VIEW_DISCOVERABILITY_ALL_USERS", 1222 }, 1223 }, 1224 ], 1225 }, 1226 }, 1227 id: "show_fewer_recommendations", 1228 }, 1229 { 1230 type: "separator", 1231 }, 1232 { 1233 type: "action", 1234 label: { 1235 string_id: "split-dismiss-button-manage-settings-option", 1236 }, 1237 action: { 1238 type: "OPEN_ABOUT_PAGE", 1239 data: { 1240 args: "preferences#general-cfrfeatures", 1241 where: "tab", 1242 }, 1243 dismiss: true, 1244 }, 1245 id: "manage_settings", 1246 }, 1247 ], 1248 attached_to: "additional_button", 1249 }, 1250 }, 1251 }, 1252 ], 1253 }, 1254 frequency: { 1255 lifetime: 1, 1256 }, 1257 skip_in_tests: "it's not tested in automation", 1258 targeting: 1259 "!isMajorUpgrade && !willShowDefaultPrompt && !activeNotifications && previousSessionEnd && fxViewButtonAreaType != null && tabsClosedCount >= 5 && (currentDate|date - profileAgeCreated|date) / 86400000 >= 7 && 'browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features' | preferenceValue != false", 1260 trigger: { 1261 id: "nthTabClosed", 1262 }, 1263 }, 1264 { 1265 id: "NEW_PROFILE_APP_MENU_TOUR", 1266 groups: [], 1267 profileScope: "single", 1268 targeting: 1269 "'browser.profiles.profile-name.updated' | preferenceValue == true && userPrefs.cfrFeatures", 1270 trigger: { 1271 id: "preferenceObserver", 1272 params: ["browser.profiles.profile-name.updated"], 1273 }, 1274 frequency: { 1275 lifetime: 1, 1276 }, 1277 skip_in_tests: "it's not tested in automation", 1278 template: "feature_callout", 1279 content: { 1280 id: "NEW_PROFILE_APP_MENU_TOUR", 1281 template: "multistage", 1282 backdrop: "transparent", 1283 transitions: false, 1284 disableHistoryUpdates: true, 1285 screens: [ 1286 { 1287 id: "NEW_PROFILE_APP_MENU_TOUR", 1288 anchors: [ 1289 { 1290 selector: "#PanelUI-button", 1291 panel_position: { 1292 anchor_attachment: "leftcenter", 1293 callout_attachment: "topright", 1294 }, 1295 }, 1296 ], 1297 content: { 1298 position: "callout", 1299 logo: { 1300 imageURL: 1301 "chrome://browser/content/asrouter/assets/fox-with-profiles.svg", 1302 height: "100%", 1303 width: "100%", 1304 }, 1305 title: { 1306 string_id: "profiles-appmenu-callout-tour-title", 1307 paddingBlock: "8px", 1308 }, 1309 subtitle: { 1310 string_id: "profiles-appmenu-callout-tour-subtitle", 1311 }, 1312 dismiss_button: { 1313 size: "small", 1314 background: true, 1315 marginInline: "0 21px", 1316 marginBlock: "21px 0", 1317 action: { 1318 dismiss: true, 1319 }, 1320 }, 1321 primary_button: { 1322 label: { 1323 string_id: "profiles-appmenu-callout-tour-primary-button", 1324 }, 1325 action: { 1326 navigate: true, 1327 type: "HIGHLIGHT_FEATURE", 1328 data: { args: "profilesAppMenuButton" }, 1329 }, 1330 }, 1331 }, 1332 }, 1333 ], 1334 }, 1335 }, 1336 ]; 1337 messages = add24HourImpressionJEXLTargeting( 1338 ["FIREFOX_VIEW_TAB_PICKUP_REMINDER"], 1339 "FIREFOX_VIEW", 1340 messages 1341 ); 1342 return messages; 1343 }; 1344 1345 export const FeatureCalloutMessages = { 1346 getMessages() { 1347 return MESSAGES(); 1348 }, 1349 };