element that is the root element for Peregrine Pages / Experiences.\r\n * There is only ever 1 root element on a page\r\n * @type {string}\r\n */\r\nexport const rootElementId: string = \"msnewsroot\";\r\n\r\n/**\r\n * Element names that are commonly used in Peregrine pages and experiences\r\n * @type {object}\r\n */\r\nexport const htmlElementIds: any = {\r\n html: \"html\",\r\n head: \"head\",\r\n body: \"body\"\r\n};\r\n\r\n/**\r\n * Constants used by application cache related scenarios\r\n */\r\nexport const applicationCacheConstants = {\r\n /**\r\n * Attribute name on html tag that is set when appcache is being used on the page\r\n */\r\n manifestAttributeName: \"manifest\",\r\n\r\n /**\r\n * Local storage key that holds the appcache info used to determine page refresh needs\r\n * for different page types.\r\n */\r\n pagesRefreshData: \"ac_prd\",\r\n\r\n /**\r\n * Local storage key that holds the appcache stored head data entries\r\n */\r\n storedHeadDataKey: \"ac_shd\",\r\n\r\n /**\r\n * Local storage key that holds the appcache stored activity IDs\r\n */\r\n storedLastUsedActivityIdKey: \"ac_sai\"\r\n\r\n};\r\n\r\n/**\r\n * The attributes that are part of markup elements that we care about\r\n */\r\nexport const clientSettings = \"data-client-settings\";\r\nexport const pagetypeSettings = \"data-pagetype\";\r\nexport const id = \"data-id\";\r\nexport const info = \"data-info\";\r\nexport const js = \"data-js\";\r\nexport const m = \"data-m\";\r\nexport const lang = \"lang\";\r\nexport const dir = \"dir\";\r\nexport const serviceUrl = \"data-service-url\";\r\nexport const telemetryId = \"data-telemetry-id\";\r\nexport const trackPageProduct = \"data-page-product\";\r\nexport const trackPageType = \"data-page-type\";\r\n\r\n/**\r\n * The number of characters that our Service Request Ids must have. This is currently defined by OneService\r\n * @type {number}\r\n */\r\nexport const numberOfCharactersNeededForUniqueRequestId: number = 32;\r\n\r\n/**\r\n * The minimum number of path segments that will be in the URL which hosts MS News Experience pages.\r\n * The first path segment should be the vertical key, e.g. spartan and the second path segment\r\n * should be the the category key, e.g. ntp\r\n * @type {number}\r\n */\r\nexport const minimumHostPagePathSegments: number = 2;\r\n\r\n/**\r\n * Default value we use for the name of the cookie that holds the ANID\r\n */\r\nexport const anonCookieName = \"APP_ANON\";\r\n\r\n/**\r\n * App Anon Cookie Exists Cookie Name. This cookie is a marker if APP_ANON exist or not.\r\n * This is necessary because APP_ANON is HTTP cookie and not accessible by JS.\r\n */\r\nexport const appAnonCookieExistsCookieName = \"aace\";\r\n\r\n/**\r\n * Child cookie name, used to signal if rpsUser is child account.\r\n */\r\nexport const childCookieName = \"child\";\r\n\r\n/**\r\n * Migration consent state cookie, indicates user has already granted or denied migration consent\r\n */\r\nexport const migrationConsentStateKey = \"migration-state\";\r\n\r\n/**\r\n * Id of MSCC cookie banner container element.\r\n */\r\nexport const msccCookieBannerElementId = \"consent-banner-container\";\r\n\r\n/**\r\n * Headers used for one service requests\r\n */\r\nexport const oneServiceHeaders = {\r\n activityId: \"x-client-activityid\",\r\n authorization: \"Authorization\"\r\n};\r\n\r\n/**\r\n * used query string params in OneService requests\r\n */\r\nexport const oneServiceQueryStringKeys = {\r\n activityId: \"activityId\",\r\n apiKey: \"apikey\",\r\n complexInfoPaneEnabled: \"cipenabled\",\r\n contentType: \"contentType\",\r\n delta: \"delta\",\r\n disableTypeSerialization: \"DisableTypeSerialization\",\r\n infopaneCount: \"infopaneCount\",\r\n fdhead: \"fdhead\",\r\n feedLayoutRequestType: \"t\",\r\n filter: \"$filter\",\r\n ids: \"ids\",\r\n location: \"location\",\r\n market: \"market\",\r\n ocid: \"ocid\",\r\n parentContentId: \"parent-content-id\",\r\n parentNamespace: \"parent-ns\",\r\n parentTitle: \"parent-title\",\r\n query: \"query\",\r\n queryType: \"queryType\",\r\n qScope: \"qscope\",\r\n responseSchema: \"responseschema\",\r\n select: \"$select\",\r\n session: \"session\",\r\n signInCookieName: \"scn\",\r\n skip: \"$skip\",\r\n source: \"source\",\r\n timeOut: \"timeOut\",\r\n top: \"$top\",\r\n user: \"user\",\r\n wrapOData: \"wrapodata\"\r\n};\r\n\r\n/**\r\n * Constants to use as role attribute value for elements\r\n */\r\nexport enum AriaRoles {\r\n /**\r\n * Presentation role is used to remove semantic meaning from an element and any of its related child elements.\r\n */\r\n Presentation = \"presentation\"\r\n}\r\n\r\n/**\r\n * Basic enum values for mobile device orientation\r\n */\r\nexport enum DeviceOrientation {\r\n Unknown = \"Unknown\",\r\n Portrait = \"Portrait\",\r\n Landscape = \"Landscape\"\r\n}\r\n\r\n/**\r\n * Enterprise compliant domain for One Service api\r\n */\r\nexport const EnterpriseOneServiceApi = \"https://ent-api.msn.com/\";\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n// Defines constants used in telemetry beacons\r\n//
\r\n// This is a auto-generated file using MSNTelemetryCodeGen (https://microsoft.visualstudio.com/DefaultCollection/Universal%20Store/_git/MSN.Tool.Telemetry?path=%2FMSNTelemetryDimensionsCodeGen/)\r\n// \r\n\r\n//
\r\n// This is a auto-generated file using MSNTelemetryDimensionsCodeGen (https://microsoft.visualstudio.com/DefaultCollection/Universal%20Store/_git/MSN.Tool.Telemetry?path=%2FMSNTelemetryDimensionsCodeGen/)\r\n// \r\nvar PageNamePageTypeMappingList = {};\r\nvar TelemetryTypeContentTypeMappingList = {};\r\nvar TelemetryTypeBehaviorTypeMappingList = {};\r\n\r\n///
Telemetry Product \r\nvar TelemetryProduct = {\r\n Spartan: \"spartan\",\r\n Prime: \"prime\",\r\n PrimeMobile: \"prime_mobile\",\r\n IEext: \"ieext\",\r\n SpartanMobile: \"spartan_mobile\",\r\n TabbedShell: \"tabbedshell\",\r\n ChromeExt: \"chromeext\",\r\n Downlevel: \"downlevel\",\r\n Xbox: \"xbox\"\r\n};\r\n\r\n///
Telemetry PageType \r\nvar TelemetryPageType = {\r\n Unspecified: \"unspecified\",\r\n DHP: \"dhp\",\r\n NTP: \"ntp\",\r\n HomePage: \"hp\",\r\n VerticalHomePage: \"verthp\",\r\n StructuredDataPage: \"data\",\r\n SectionFront: \"secfront\",\r\n SiteSearch: \"sitesearch\",\r\n Article: \"article\",\r\n Gallery: \"gallery\",\r\n Video: \"video\",\r\n SubjectSection: \"subjectsec\",\r\n CustomColumn: \"custcol\"\r\n};\r\n\r\n// TODO: (nubenja) Remove this once all partners moves from TelemetryType to ContentType and ContentAction\r\n///
Telemetry Type \r\nvar TelemetryType = {\r\n Undefined: 0,\r\n Header: 1,\r\n Footer: 2,\r\n TopNavBar: 3,\r\n NavBar: 4,\r\n DropDown: 5,\r\n Section: 6,\r\n Carousel: 7,\r\n Module: 8,\r\n SearchBox: 9,\r\n InputBox: 10,\r\n ActionButton: 11,\r\n Interaction: 12,\r\n Headline: 13,\r\n Navigation: 14,\r\n Entity: 15,\r\n StructuredData: 16,\r\n AppStore: 17,\r\n AppLaunch: 18,\r\n CmsPromotions: 19,\r\n MicrosoftWebStore: 20,\r\n XboxStore: 21,\r\n OfficeStore: 22,\r\n AppInstall: 23,\r\n PartnerLinks: 24,\r\n SponsoredContent: 25,\r\n Follow: 26,\r\n Unfollow: 27,\r\n MoreFrom: 28,\r\n Topic: 29,\r\n Provider: 30,\r\n Spotlight: 33,\r\n ShareClose: 36,\r\n Share: 37,\r\n Like: 38,\r\n Dislike: 39,\r\n Unlike: 40,\r\n Undislike: 41,\r\n Mute: 42,\r\n Unmute: 43,\r\n MuteCancel: 44,\r\n Manage: 45,\r\n NewStories: 46,\r\n AutoSuggest: 47,\r\n BingCard: 48,\r\n Tile: 49,\r\n TrendingNews: 50,\r\n AllCoverage: 51,\r\n Report: 52,\r\n AdChoice: 53,\r\n Hide: 55,\r\n Unhide: 56\r\n};\r\n\r\n///
Telemetry Content Type \r\nvar TelemetryContentType = {\r\n Undefined: 0,\r\n App: 1,\r\n Article: 2,\r\n Feed: 3,\r\n Gallery: 4,\r\n AppStorePromo: 5,\r\n Settings: 6,\r\n SponsoredContent: 7,\r\n StructuredDataCard: 8,\r\n Video: 9,\r\n Webview: 10,\r\n Activity: 11,\r\n Win32: 12,\r\n OfficeDocument: 13,\r\n LocalFile: 14,\r\n CardAction: 15\r\n};\r\n\r\n///
Telemetry Behavior Type \r\nconst TelemetryBehaviorType = {\r\n Undefined: 0,\r\n Navigate: 1,\r\n ContextMenu: 2,\r\n Pin: 3,\r\n Unpin: 4,\r\n Rearrange: 5,\r\n Remove: 6,\r\n Add: 7,\r\n Open: 8,\r\n View: 9,\r\n Follow: 10,\r\n Unfollow: 11,\r\n More: 12,\r\n Close: 13,\r\n Share: 14,\r\n Like: 15,\r\n Dislike: 16,\r\n Unlike: 17,\r\n Undislike: 18,\r\n Mute: 19,\r\n Unmute: 20,\r\n Cancel: 21,\r\n Launch: 22,\r\n Install: 23,\r\n Manage: 24,\r\n Show: 25,\r\n MuteCancel: 26,\r\n Save: 27,\r\n Hide: 28,\r\n Unhide: 29,\r\n Customize: 30\r\n};\r\n\r\n///
Telemetry ContentPlacedBySource \r\nvar ContentPlacedBySource = {\r\n Editor: 0,\r\n PersonalizationAlgo: 1,\r\n Bing: 2,\r\n Taboola: 3,\r\n Outbrain: 4,\r\n AutoCuration: 5,\r\n User: 6,\r\n AppNexus: 7,\r\n OtherSponconProvider: 8\r\n};\r\n\r\n///
Telemetry Page Configuration \r\nvar TelemetryPageConfiguration = {\r\n NoContent: 0,\r\n OneBox: 1,\r\n TopSites: 2,\r\n Suggested: 4,\r\n ContentFeed: 8,\r\n WinFre: 16,\r\n StripeLayout: 1024\r\n};\r\n\r\n///
Telemetry Partner Namespace \r\nvar TelemetryPartnerNamespace = {\r\n MMX: \"m\",\r\n Shell: \"s\",\r\n Edge: \"e\",\r\n Office: \"o\",\r\n Activity: \"a\",\r\n Cortana: \"c\"\r\n};\r\n\r\n///
Telemetry PageName \r\nvar TelemetryPageName = {\r\n StartPage: telemetryPageName(\"startpage\", TelemetryPageType.HomePage),\r\n // @ts-ignore\r\n DefaultPage: telemetryPageName(\"default\"),\r\n // @ts-ignore\r\n EduPage: telemetryPageName(\"edu\"),\r\n // @ts-ignore\r\n ChildModePage: telemetryPageName(\"child\"),\r\n // @ts-ignore\r\n Office: telemetryPageName(\"office\"),\r\n // @ts-ignore\r\n Feed: telemetryPageName(\"xfeed\"),\r\n // @ts-ignore\r\n Discover: telemetryPageName(\"discover\"),\r\n // @ts-ignore\r\n MyInterests: telemetryPageName(\"myinterests\"),\r\n // @ts-ignore\r\n CombinedInterests: telemetryPageName(\"cinterests\"),\r\n ArticlePageNames:\r\n {\r\n Article: telemetryPageName(\"article\", TelemetryPageType.Article),\r\n ArticleVNext: telemetryPageName(\"articlevnext\", TelemetryPageType.Article),\r\n ArticleListicle: telemetryPageName(\"article_listicle\", TelemetryPageType.Article),\r\n ArticleCollection: telemetryPageName(\"articlecollection\", TelemetryPageType.Article),\r\n ArticleFullScreen: telemetryPageName(\"articlefullscreen\", TelemetryPageType.Article),\r\n FlexibleArticle: telemetryPageName(\"articleflex\", TelemetryPageType.Article),\r\n FlexibleArticleMobile: telemetryPageName(\"articleflexmobile\", TelemetryPageType.Article),\r\n ArticleGalleryFullScreen: telemetryPageName(\"article_galleryfs\", TelemetryPageType.Article)\r\n },\r\n GalleryPageNames:\r\n {\r\n Gallery: telemetryPageName(\"gallery\", TelemetryPageType.Gallery),\r\n GalleryVNext: telemetryPageName(\"galleryvnext\", TelemetryPageType.Gallery),\r\n GalleryFullScreen: telemetryPageName(\"gallery_fullscreen\", TelemetryPageType.Gallery),\r\n GalleryClassic: telemetryPageName(\"gallery_classic\", TelemetryPageType.Gallery),\r\n GalleryClassicFullScreen: telemetryPageName(\"gallery_classicfs\", TelemetryPageType.Gallery),\r\n GallerySearch: telemetryPageName(\"gallery_search\", TelemetryPageType.Gallery),\r\n GallerySearchFullScreen: telemetryPageName(\"gallery_searchfs\", TelemetryPageType.Gallery),\r\n FlexibleGallery: telemetryPageName(\"galleryflex\", TelemetryPageType.Gallery),\r\n FlexibleGalleryMobile: telemetryPageName(\"galleryflexmobile\", TelemetryPageType.Gallery),\r\n GalleryImmersive: telemetryPageName(\"gallery_immersive\", TelemetryPageType.Gallery),\r\n GalleryImmersiveFullScreen: telemetryPageName(\"gallery_immersivefs\", TelemetryPageType.Gallery),\r\n GallerySponsored: telemetryPageName(\"gallery_sponsor\", TelemetryPageType.Gallery),\r\n GallerySponsoredFullScreen: telemetryPageName(\"gallery_sponsorfs\", TelemetryPageType.Gallery),\r\n GalleryInline: telemetryPageName(\"gallery_inline\", TelemetryPageType.Gallery)\r\n },\r\n VideoPageNames:\r\n {\r\n ChannelPlayerPage: telemetryPageName(\"channelplayerpage\", TelemetryPageType.Video),\r\n PartnerPlayerPage: telemetryPageName(\"partnerplayerpage\", TelemetryPageType.Video)\r\n },\r\n VerticalHomePageNames:\r\n {\r\n HomePage: telemetryPageName(\"homepage\", TelemetryPageType.VerticalHomePage),\r\n HomePageToday: telemetryPageName(\"homepage-today\", TelemetryPageType.VerticalHomePage)\r\n },\r\n StructuredDataPageNames:\r\n {\r\n Gamecenter: telemetryPageName(\"gamecenter\", TelemetryPageType.StructuredDataPage),\r\n Schedule: telemetryPageName(\"schedule\", TelemetryPageType.StructuredDataPage),\r\n Scores: telemetryPageName(\"scores\", TelemetryPageType.StructuredDataPage),\r\n Stocksummary: telemetryPageName(\"stocksummary\", TelemetryPageType.StructuredDataPage),\r\n Stocksummaryoneriver: telemetryPageName(\"stocksummaryoneriver\", TelemetryPageType.StructuredDataPage),\r\n Weatherxplatmaps: telemetryPageName(\"weatherxplatmaps\", TelemetryPageType.StructuredDataPage),\r\n Standings: telemetryPageName(\"standings\", TelemetryPageType.StructuredDataPage),\r\n Markets: telemetryPageName(\"markets\", TelemetryPageType.StructuredDataPage),\r\n Watchlistpage: telemetryPageName(\"watchlistpage\", TelemetryPageType.StructuredDataPage),\r\n Data_modelpage: telemetryPageName(\"data_modelpage\", TelemetryPageType.StructuredDataPage),\r\n Immersivechartspage: telemetryPageName(\"immersivechartspage\", TelemetryPageType.StructuredDataPage),\r\n Currencies: telemetryPageName(\"currencies\", TelemetryPageType.StructuredDataPage),\r\n Indexdetailspage: telemetryPageName(\"indexdetailspage\", TelemetryPageType.StructuredDataPage),\r\n Data_makepage: telemetryPageName(\"data_makepage\", TelemetryPageType.StructuredDataPage),\r\n Weatherfullscreenmaps: telemetryPageName(\"weatherfullscreenmaps\", TelemetryPageType.StructuredDataPage),\r\n Weatherthresholdmaps: telemetryPageName(\"weatherthresholdmaps\", TelemetryPageType.StructuredDataPage),\r\n Stockanalysisdetails: telemetryPageName(\"stockanalysisdetails\", TelemetryPageType.StructuredDataPage),\r\n Data_yearoverview: telemetryPageName(\"data_yearoverview\", TelemetryPageType.StructuredDataPage),\r\n Data_segmenthub: telemetryPageName(\"data_segmenthub\", TelemetryPageType.StructuredDataPage),\r\n Weathermaps: telemetryPageName(\"weathermaps\", TelemetryPageType.StructuredDataPage),\r\n Playerstats: telemetryPageName(\"playerstats\", TelemetryPageType.StructuredDataPage),\r\n Funddetailspage: telemetryPageName(\"funddetailspage\", TelemetryPageType.StructuredDataPage),\r\n Exercisedetails: telemetryPageName(\"exercisedetails\", TelemetryPageType.StructuredDataPage),\r\n Teams: telemetryPageName(\"teams\", TelemetryPageType.StructuredDataPage),\r\n Etfdetailspage: telemetryPageName(\"etfdetailspage\", TelemetryPageType.StructuredDataPage),\r\n Binganswermaps: telemetryPageName(\"binganswermaps\", TelemetryPageType.StructuredDataPage),\r\n Workoutdetails: telemetryPageName(\"workoutdetails\", TelemetryPageType.StructuredDataPage),\r\n Competitionstats: telemetryPageName(\"competitionstats\", TelemetryPageType.StructuredDataPage),\r\n Polls: telemetryPageName(\"polls\", TelemetryPageType.StructuredDataPage),\r\n Data_photos: telemetryPageName(\"data_photos\", TelemetryPageType.StructuredDataPage),\r\n Videocategorylistpage: telemetryPageName(\"videocategorylistpage\", TelemetryPageType.StructuredDataPage),\r\n Stockfinancialsdetails: telemetryPageName(\"stockfinancialsdetails\", TelemetryPageType.StructuredDataPage),\r\n Commoditydetailspage: telemetryPageName(\"commoditydetailspage\", TelemetryPageType.StructuredDataPage),\r\n Data_yearoverview_trim: telemetryPageName(\"data_yearoverview_trim\", TelemetryPageType.StructuredDataPage),\r\n Worldwidepage: telemetryPageName(\"worldwidepage\", TelemetryPageType.StructuredDataPage),\r\n Data_photos_trim: telemetryPageName(\"data_photos_trim\", TelemetryPageType.StructuredDataPage),\r\n Stockcompanydetails: telemetryPageName(\"stockcompanydetails\", TelemetryPageType.StructuredDataPage),\r\n Retirementplanner: telemetryPageName(\"retirementplanner\", TelemetryPageType.StructuredDataPage),\r\n Livecoverage: telemetryPageName(\"livecoverage\", TelemetryPageType.StructuredDataPage),\r\n Teamroster: telemetryPageName(\"teamroster\", TelemetryPageType.StructuredDataPage),\r\n Stockhistorydetails: telemetryPageName(\"stockhistorydetails\", TelemetryPageType.StructuredDataPage),\r\n Filterresultspage: telemetryPageName(\"filterresultspage\", TelemetryPageType.StructuredDataPage),\r\n Data_carcompare: telemetryPageName(\"data_carcompare\", TelemetryPageType.StructuredDataPage),\r\n Stockownershipdetails: telemetryPageName(\"stockownershipdetails\", TelemetryPageType.StructuredDataPage),\r\n Driverstandings: telemetryPageName(\"driverstandings\", TelemetryPageType.StructuredDataPage),\r\n Timevalueofmoney: telemetryPageName(\"timevalueofmoney\", TelemetryPageType.StructuredDataPage),\r\n Savingscalculator: telemetryPageName(\"savingscalculator\", TelemetryPageType.StructuredDataPage),\r\n Iccmatches: telemetryPageName(\"iccmatches\", TelemetryPageType.StructuredDataPage),\r\n Other_flightsearchresult: telemetryPageName(\"other_flightsearchresult\", TelemetryPageType.StructuredDataPage),\r\n Stockrelateddetails: telemetryPageName(\"stockrelateddetails\", TelemetryPageType.StructuredDataPage),\r\n Data_specs_trim: telemetryPageName(\"data_specs_trim\", TelemetryPageType.StructuredDataPage),\r\n Stockoptionsdetails: telemetryPageName(\"stockoptionsdetails\", TelemetryPageType.StructuredDataPage),\r\n HomepageAlerts: telemetryPageName(\"homepage-alerts\", TelemetryPageType.StructuredDataPage),\r\n HomepageRecordsandAverages: telemetryPageName(\"homepage-recordsandaverages\", TelemetryPageType.StructuredDataPage),\r\n HomepageWeatherTraffic: telemetryPageName(\"homepage-weathertraffic\", TelemetryPageType.StructuredDataPage),\r\n Data_specs: telemetryPageName(\"data_specs\", TelemetryPageType.StructuredDataPage),\r\n Data_pricing: telemetryPageName(\"data_pricing\", TelemetryPageType.StructuredDataPage),\r\n Mortgagecalculator: telemetryPageName(\"mortgagecalculator\", TelemetryPageType.StructuredDataPage),\r\n Data_performance_trim: telemetryPageName(\"data_performance_trim\", TelemetryPageType.StructuredDataPage),\r\n Theatershowtimes: telemetryPageName(\"theatershowtimes\", TelemetryPageType.StructuredDataPage),\r\n Data_pricing_trim: telemetryPageName(\"data_pricing_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_photosInterior: telemetryPageName(\"data_photos-interior\", TelemetryPageType.StructuredDataPage),\r\n Indexdetailsanalysispage: telemetryPageName(\"indexdetailsanalysispage\", TelemetryPageType.StructuredDataPage),\r\n Data_photosInterior_trim: telemetryPageName(\"data_photos-interior_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_photosColors: telemetryPageName(\"data_photos-colors\", TelemetryPageType.StructuredDataPage),\r\n Data_carReviews_trim: telemetryPageName(\"data_car-reviews_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_carReviews: telemetryPageName(\"data_car-reviews\", TelemetryPageType.StructuredDataPage),\r\n Racecalendar: telemetryPageName(\"racecalendar\", TelemetryPageType.StructuredDataPage),\r\n Teamstandings: telemetryPageName(\"teamstandings\", TelemetryPageType.StructuredDataPage),\r\n Data_photosColors_trim: telemetryPageName(\"data_photos-colors_trim\", TelemetryPageType.StructuredDataPage),\r\n Stockdetails: telemetryPageName(\"stockdetails\", TelemetryPageType.StructuredDataPage),\r\n Data_interiorFeatures_trim: telemetryPageName(\"data_interior-features_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_exteriorFeatures_trim: telemetryPageName(\"data_exterior-features_trim\", TelemetryPageType.StructuredDataPage),\r\n Calendar: telemetryPageName(\"calendar\", TelemetryPageType.StructuredDataPage),\r\n TeamStats: telemetryPageName(\"teamstats\", TelemetryPageType.StructuredDataPage),\r\n Movieshowtimes: telemetryPageName(\"movieshowtimes\", TelemetryPageType.StructuredDataPage),\r\n Drafts: telemetryPageName(\"drafts\", TelemetryPageType.StructuredDataPage),\r\n Data_technologyFeatures_trim: telemetryPageName(\"data_technology-features_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_workoutdetails_collection: telemetryPageName(\"data_workoutdetails_collection\", TelemetryPageType.StructuredDataPage),\r\n Data_photosExterior: telemetryPageName(\"data_photos-exterior\", TelemetryPageType.StructuredDataPage),\r\n Data_photosExterior_trim: telemetryPageName(\"data_photos-exterior_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_photos360Interior: telemetryPageName(\"data_photos-360-interior\", TelemetryPageType.StructuredDataPage),\r\n Immersivechartsmarketspage: telemetryPageName(\"immersivechartsmarketspage\", TelemetryPageType.StructuredDataPage),\r\n Returnoninvestment: telemetryPageName(\"returnoninvestment\", TelemetryPageType.StructuredDataPage),\r\n Indexdetailsrelatedpage: telemetryPageName(\"indexdetailsrelatedpage\", TelemetryPageType.StructuredDataPage),\r\n Gonepage: telemetryPageName(\"gonepage\", TelemetryPageType.StructuredDataPage),\r\n Data_compare: telemetryPageName(\"data_compare\", TelemetryPageType.StructuredDataPage),\r\n Data_compare_trim: telemetryPageName(\"data_compare_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_options_trim: telemetryPageName(\"data_options_trim\", TelemetryPageType.StructuredDataPage),\r\n Entitiespage: telemetryPageName(\"entitiespage\", TelemetryPageType.StructuredDataPage),\r\n Workoutdetailsprint: telemetryPageName(\"workoutdetailsprint\", TelemetryPageType.StructuredDataPage),\r\n Data_photos360Exterior: telemetryPageName(\"data_photos-360-exterior\", TelemetryPageType.StructuredDataPage),\r\n HomepageDatacarfinder: telemetryPageName(\"homepage-datacarfinder\", TelemetryPageType.StructuredDataPage),\r\n Data_photos360Interior_trim: telemetryPageName(\"data_photos-360-interior_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_skeleton: telemetryPageName(\"data_skeleton\", TelemetryPageType.StructuredDataPage),\r\n Mortgagerates: telemetryPageName(\"mortgagerates\", TelemetryPageType.StructuredDataPage),\r\n Brackets: telemetryPageName(\"brackets\", TelemetryPageType.StructuredDataPage),\r\n Data_photos360Exterior_trim: telemetryPageName(\"data_photos-360-exterior_trim\", TelemetryPageType.StructuredDataPage),\r\n Data_photocompare: telemetryPageName(\"data_photocompare\", TelemetryPageType.StructuredDataPage),\r\n HomepageWeather10day: telemetryPageName(\"homepage-weather10day\", TelemetryPageType.StructuredDataPage),\r\n Data_performance: telemetryPageName(\"data_performance\", TelemetryPageType.StructuredDataPage),\r\n HomepageWeatherextendedforecast: telemetryPageName(\"homepage-weatherextendedforecast\", TelemetryPageType.StructuredDataPage),\r\n Savings: telemetryPageName(\"savings\", TelemetryPageType.StructuredDataPage),\r\n Data_exteriorFeatures: telemetryPageName(\"data_exterior-features\", TelemetryPageType.StructuredDataPage),\r\n Data_interiorFeatures: telemetryPageName(\"data_interior-features\", TelemetryPageType.StructuredDataPage),\r\n Data_options: telemetryPageName(\"data_options\", TelemetryPageType.StructuredDataPage),\r\n Travelgonepage: telemetryPageName(\"travelgonepage\", TelemetryPageType.StructuredDataPage),\r\n Recipe: telemetryPageName(\"recipe\", TelemetryPageType.StructuredDataPage),\r\n Getportfoliodatapage: telemetryPageName(\"getportfoliodatapage\", TelemetryPageType.StructuredDataPage),\r\n Brokercenterpage: telemetryPageName(\"brokercenterpage\", TelemetryPageType.StructuredDataPage),\r\n Data_technologyFeatures: telemetryPageName(\"data_technology-features\", TelemetryPageType.StructuredDataPage),\r\n Tvlistings: telemetryPageName(\"tvlistings\", TelemetryPageType.StructuredDataPage),\r\n Ownerstandings: telemetryPageName(\"ownerstandings\", TelemetryPageType.StructuredDataPage),\r\n Entitydetailspage: telemetryPageName(\"entitydetailspage\", TelemetryPageType.StructuredDataPage),\r\n Creditcards: telemetryPageName(\"creditcards\", TelemetryPageType.StructuredDataPage),\r\n Cmssitemap: telemetryPageName(\"cmssitemap\", TelemetryPageType.StructuredDataPage),\r\n Externalnativeadpage: telemetryPageName(\"externalnativeadpage\", TelemetryPageType.StructuredDataPage),\r\n Autoloans: telemetryPageName(\"autoloans\", TelemetryPageType.StructuredDataPage),\r\n Externalcontent: telemetryPageName(\"externalcontent\", TelemetryPageType.StructuredDataPage),\r\n Htmlsitemap: telemetryPageName(\"htmlsitemap\", TelemetryPageType.StructuredDataPage)\r\n },\r\n CustomColumnPageNames:\r\n {\r\n TrendingTopics: telemetryPageName(\"topic_tt\", TelemetryPageType.CustomColumn),\r\n GlobalSettingsPage: telemetryPageName(\"globalsettingspage\", TelemetryPageType.CustomColumn),\r\n MyTopics: telemetryPageName(\"mytopics\", TelemetryPageType.CustomColumn),\r\n WeatherPlaces: telemetryPageName(\"weatherplaces\", TelemetryPageType.CustomColumn),\r\n MyFavorites: telemetryPageName(\"myfavorites\", TelemetryPageType.CustomColumn),\r\n TopicResult: telemetryPageName(\"topicresult\", TelemetryPageType.CustomColumn),\r\n Collections: telemetryPageName(\"collections\", TelemetryPageType.CustomColumn),\r\n Rouxbe: telemetryPageName(\"rouxbe\", TelemetryPageType.CustomColumn),\r\n ShoppingList: telemetryPageName(\"shopping list\", TelemetryPageType.CustomColumn),\r\n MyHealthReportsPage: telemetryPageName(\"myhealthreportspage\", TelemetryPageType.CustomColumn),\r\n Error404page: telemetryPageName(\"error404page\", TelemetryPageType.CustomColumn),\r\n AppsPromotion: telemetryPageName(\"appspromotion\", TelemetryPageType.CustomColumn),\r\n Error500page: telemetryPageName(\"error500page\", TelemetryPageType.CustomColumn),\r\n DietTrackerPreSigninPage: telemetryPageName(\"diettrackerpresigninpage\", TelemetryPageType.CustomColumn),\r\n ExerciseTrackerPreSigninPage: telemetryPageName(\"exercisetrackerpresigninpage\", TelemetryPageType.CustomColumn),\r\n WebSlicePage: telemetryPageName(\"other_webslice\", TelemetryPageType.CustomColumn),\r\n Error200Page: telemetryPageName(\"error200page\", TelemetryPageType.CustomColumn),\r\n AboutUsPage: telemetryPageName(\"aboutus\", TelemetryPageType.CustomColumn),\r\n UnSupport: telemetryPageName(\"unsupport\", TelemetryPageType.CustomColumn),\r\n Disclaimer: telemetryPageName(\"disclaimer\", TelemetryPageType.CustomColumn),\r\n TermsOfService: telemetryPageName(\"termsofservice\", TelemetryPageType.CustomColumn),\r\n SevereWeather: telemetryPageName(\"severeweather\", TelemetryPageType.CustomColumn)\r\n },\r\n SubjectSectionPageNames:\r\n {\r\n TeamhomePage: telemetryPageName(\"teamhome\", TelemetryPageType.SubjectSection),\r\n PlayerPage: telemetryPageName(\"player\", TelemetryPageType.SubjectSection),\r\n MarketMoversPage: telemetryPageName(\"marketmovers\", TelemetryPageType.SubjectSection),\r\n CommoditiesPage: telemetryPageName(\"commoditiespage\", TelemetryPageType.SubjectSection),\r\n ChefPage: telemetryPageName(\"chef\", TelemetryPageType.SubjectSection),\r\n NutritionIndexPage: telemetryPageName(\"nutritionindex\", TelemetryPageType.SubjectSection),\r\n FinanceTechnologyPage: telemetryPageName(\"finance-technologypage\", TelemetryPageType.SubjectSection),\r\n MedicalindexPage: telemetryPageName(\"medicalindex\", TelemetryPageType.SubjectSection)\r\n },\r\n SiteSearchPageNames:\r\n {\r\n SearchResultsPage: telemetryPageName(\"searchresultspage\", TelemetryPageType.SiteSearch),\r\n VideoSearchResultsPage: telemetryPageName(\"videosearchresultspage\", TelemetryPageType.SiteSearch),\r\n PartnerVideolistPage: telemetryPageName(\"partnervideolistpage\", TelemetryPageType.SiteSearch),\r\n HomepageBingserpIframepage: telemetryPageName(\"homepage-bingserpiframepage\", TelemetryPageType.SiteSearch),\r\n SitesearchSitesearch: telemetryPageName(\"sitesearch_sitesearch\", TelemetryPageType.SiteSearch),\r\n SearchResults: telemetryPageName(\"search results\", TelemetryPageType.SiteSearch),\r\n SerpPage: telemetryPageName(\"serppage\", TelemetryPageType.SiteSearch),\r\n FindaMoviePage: telemetryPageName(\"findamoviepage\", TelemetryPageType.SiteSearch)\r\n },\r\n SectionFrontPageNames:\r\n {\r\n Competitionhub: telemetryPageName(\"competitionhub\", TelemetryPageType.SectionFront),\r\n Local: telemetryPageName(\"local\", TelemetryPageType.SectionFront),\r\n Stockscreener: telemetryPageName(\"stockscreener\", TelemetryPageType.SectionFront),\r\n Toolslandingpage: telemetryPageName(\"toolslandingpage\", TelemetryPageType.SectionFront),\r\n Showtimes: telemetryPageName(\"showtimes\", TelemetryPageType.SectionFront),\r\n FinanceRealEstatepage: telemetryPageName(\"finance-real-estatepage\", TelemetryPageType.SectionFront),\r\n CookingSchool: telemetryPageName(\"cooking school\", TelemetryPageType.SectionFront),\r\n Allcompetitions: telemetryPageName(\"allcompetitions\", TelemetryPageType.SectionFront),\r\n Newspage: telemetryPageName(\"newspage\", TelemetryPageType.SectionFront),\r\n CocktailHub: telemetryPageName(\"cocktail hub\", TelemetryPageType.SectionFront),\r\n Travelflightsearchhubpage: telemetryPageName(\"travelflightsearchhubpage\", TelemetryPageType.SectionFront),\r\n Hotelshubpage: telemetryPageName(\"hotelshubpage\", TelemetryPageType.SectionFront),\r\n WineHub: telemetryPageName(\"wine hub\", TelemetryPageType.SectionFront),\r\n ChefHub: telemetryPageName(\"chef hub\", TelemetryPageType.SectionFront),\r\n Travelflightstatushubpage: telemetryPageName(\"travelflightstatushubpage\", TelemetryPageType.SectionFront),\r\n HomepageCompetitionhub: telemetryPageName(\"homepage-competitionhub\", TelemetryPageType.SectionFront),\r\n Editorial: telemetryPageName(\"editorial\", TelemetryPageType.SectionFront),\r\n SecfrontHotel: telemetryPageName(\"secfront_hotel\", TelemetryPageType.SectionFront),\r\n SecfrontTNews: telemetryPageName(\"secfront_tnews\", TelemetryPageType.SectionFront)\r\n }\r\n};\r\n\r\n///
Telemetry PageMode \r\nvar TelemetryPageMode = {\r\n Default: 0,\r\n Trial: 1,\r\n Subscription: 2\r\n};\r\n\r\n///
Telemetry Page Pivot \r\nvar TelemetryPagePivot = {\r\n Undefined: \"undefined\",\r\n Office: \"office\",\r\n Apps: \"apps\",\r\n News: \"news\",\r\n Timeline: \"timeline\",\r\n StartMenu: \"startmenu\"\r\n};\r\n\r\n///
Telemetry User Id Type \r\nvar TelemetryUserType = {\r\n Aad: \"aad\",\r\n Msa: \"msa\",\r\n MsaKids: \"msa-kids\",\r\n Local: \"local\"\r\n};\r\n\r\nconst TelemetryActionType = {\r\n Click: \"click\",\r\n Hover: \"mouseenter\",\r\n Submit: \"submit\",\r\n View: \"view\",\r\n RightClick: \"rightclick\"\r\n};\r\n\r\nexport var telemetryDataTypes = {\r\n TelemetryProduct: TelemetryProduct,\r\n TelemetryPageType: TelemetryPageType,\r\n TelemetryType: TelemetryType,\r\n TelemetryContentType: TelemetryContentType,\r\n TelemetryBehaviorType: TelemetryBehaviorType,\r\n ContentPlacedBySource: ContentPlacedBySource,\r\n TelemetryPageConfiguration: TelemetryPageConfiguration,\r\n TelemetryPageName: TelemetryPageName,\r\n TelemetryPageMode: TelemetryPageMode,\r\n TelemetryPagePivot: TelemetryPagePivot,\r\n TelemetryPartnerNamespace: TelemetryPartnerNamespace,\r\n TelemetryUserType: TelemetryUserType,\r\n getTelemetryContentType: getTelemetryContentType,\r\n getTelemetryPageInfo: getTelemetryPageInfo,\r\n validateTelemetryDataType: validateTelemetryDataType,\r\n getTelemetryBehavior: getTelemetryBehavior,\r\n TelemetryActionType: TelemetryActionType\r\n};\r\n\r\n///
\r\n/// This function gets the telemetry page info object from the given pageName string.\r\n/// \r\n///
PageName string\r\n///
The Telemetry Page Name object\r\nfunction getTelemetryPageInfo(pageName) {\r\n if (pageName && PageNamePageTypeMappingList) {\r\n pageName = pageName.toLowerCase();\r\n if (PageNamePageTypeMappingList[pageName] !== undefined) {\r\n return PageNamePageTypeMappingList[pageName];\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n///
\r\n/// This function validates and returns the telemetry data type from the given string of the data type.\r\n/// \r\n///
DataType enum e.g. telemetryDataType.TelemetryPageType\r\n///
value of the type to validate\r\n///
The Telemetry Page type\r\nfunction validateTelemetryDataType(type, value) {\r\n if (type && value) {\r\n for (var prop in type) {\r\n if (type.hasOwnProperty(prop)) {\r\n if ((typeof value == \"string\" && type[prop] === value.toLowerCase()) ||\r\n type[prop] === value) {\r\n return type[prop];\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n///
\r\n/// Private class to define the telemetry Page Name. This class is purposefully not exposed to public.\r\n/// Public should use getTelemetryPageName to get the telemetrypagename object from the given pagename string.\r\n/// All the telemetry page names should be defined as part of this javascript file.\r\n/// \r\n///
PageName string\r\n///
PageType should be of type TelemetryPageType\r\n///
The Telemetry Page Name object\r\nfunction telemetryPageName(pageName, pageType) {\r\n if (pageName) {\r\n var name = pageName.toLowerCase();\r\n var pType = pageType || TelemetryPageType.Unspecified;\r\n var telemetryPageNameObject = { PageName: name, PageType: pType };\r\n PageNamePageTypeMappingList[name] = telemetryPageNameObject;\r\n\r\n return telemetryPageNameObject;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n///
\r\n/// This function gets the telemetry contentType from the given telemetryType.\r\n/// \r\n///
TelemetryType enum value\r\n///
ContentType enum.\r\nfunction getTelemetryContentType(telemetryType) {\r\n if (TelemetryTypeContentTypeMappingList[telemetryType]) {\r\n return TelemetryTypeContentTypeMappingList[telemetryType];\r\n }\r\n}\r\n\r\n///
\r\n/// This function gets the telemetry contentAction from the given telemetryType.\r\n/// \r\n///
TelemetryType enum value\r\n///
ContentAction enum.\r\nfunction getTelemetryBehavior(telemetryType)\r\n{\r\n if (TelemetryTypeBehaviorTypeMappingList[telemetryType])\r\n {\r\n return TelemetryTypeBehaviorTypeMappingList[telemetryType];\r\n } else {\r\n return TelemetryBehaviorType.Undefined;\r\n }\r\n}\r\n\r\n///
\r\n/// Private function for initializing mapping between telemetryType and telemetryContentType.\r\n/// This will be removed after telemetryType deprecated.\r\n/// \r\nfunction initTelemetryTypeContentTypeMappingList() {\r\n TelemetryTypeContentTypeMappingList[TelemetryType.AppInstall] = TelemetryContentType.App;\r\n TelemetryTypeContentTypeMappingList[TelemetryType.AppLaunch] = TelemetryContentType.App;\r\n TelemetryTypeContentTypeMappingList[TelemetryType.SponsoredContent] = TelemetryContentType.SponsoredContent;\r\n TelemetryTypeContentTypeMappingList[TelemetryType.StructuredData] = TelemetryContentType.StructuredDataCard;\r\n TelemetryTypeContentTypeMappingList[TelemetryType.AppStore] = TelemetryContentType.AppStorePromo;\r\n}\r\n\r\n///
\r\n/// Private function for initializing mapping between telemetryType and TelemetryBehaviorType.\r\n/// This will be removed after telemetryType deprecated.\r\n/// \r\nfunction initTelemetryTypeBehaviorTypeMappingList()\r\n{\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.AppInstall] = TelemetryBehaviorType.Install;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.AppLaunch] = TelemetryBehaviorType.Launch;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Follow] = TelemetryBehaviorType.Follow;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Unfollow] = TelemetryBehaviorType.Unfollow;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Like] = TelemetryBehaviorType.Like;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Dislike] = TelemetryBehaviorType.Dislike;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Unlike] = TelemetryBehaviorType.Unlike;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Undislike] = TelemetryBehaviorType.Undislike;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Mute] = TelemetryBehaviorType.Mute;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Unmute] = TelemetryBehaviorType.Unmute;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.MuteCancel] = TelemetryBehaviorType.MuteCancel;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Manage] = TelemetryBehaviorType.Manage;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Hide] = TelemetryBehaviorType.Hide;\r\n TelemetryTypeBehaviorTypeMappingList[TelemetryType.Unhide] = TelemetryBehaviorType.Unhide;\r\n}\r\n\r\n// Init telemetryType mapping\r\ninitTelemetryTypeContentTypeMappingList();\r\ninitTelemetryTypeBehaviorTypeMappingList();","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { canUseDOM, getDocumentElementsByTagName, getLocationSearch, getLocationHostname } from \"@msnews/isomorphic-util\";\r\nimport { applicationCacheConstants, clientSettings, dir, htmlElementIds, info, js, lang, pagetypeSettings } from \"../constants\";\r\n\r\nimport { AudienceModeType } from \"@msnews/experiences-constants\";\r\nimport { DeviceFormFactorType } from \"cms-models-msn/configuration/types/DeviceFormFactorType\";\r\nimport { Environment } from \"./Environment\";\r\nimport { ILocale } from \"cms-models-msn/configuration/ILocale\";\r\nimport { IPcsBrowserScope } from \"../types/PcsBrowsersType\";\r\nimport { MarketProperties } from \"./MarketProperties\";\r\nimport { WebClientData } from \"./WebClientData\";\r\nimport { OperatingSystemType } from \"cms-models-msn/configuration/types/OperatingSystemType\";\r\nimport { UrlUtility } from \"../utilities/UrlUtility\";\r\nimport { localStorage } from \"../utilities/WebStorage\";\r\nimport { tryParseJson } from \"../utilities/Parsing\";\r\nimport { KeyValueArray } from \"../utilities\";\r\n\r\n/**\r\n * Format used for activity ID stored in storage\r\n */\r\nexport type StoredActivityId = {\r\n /**\r\n * ID value\r\n */\r\n id: string,\r\n\r\n /**\r\n * Timestamp of when value was stored\r\n */\r\n ts: number,\r\n\r\n /**\r\n * Flag inidicating if the ID was used in a previous page (stale)\r\n */\r\n previouslyUsed?: boolean\r\n};\r\n\r\n/**\r\n * JSON data contract / interface for settings in the element that are part of the data-client-settings attribute.\r\n */\r\nexport interface IClientSettings {\r\n aid: string,\r\n apptype: string,\r\n apps_locale: string,\r\n audienceMode?: AudienceModeType,\r\n browser?: IPcsBrowserScope,\r\n configRootUrl?: string,\r\n deviceFormFactor?: DeviceFormFactorType,\r\n domain?: string,\r\n env: Environment,\r\n featureFlags?: any,\r\n contentId?: string,\r\n\r\n /** The schema://domain to be used for the main feed URL */\r\n feedBaseDomain?: string,\r\n\r\n categoryKey?: string,\r\n functionalonly_cookie_experience: boolean,\r\n functional_cookie_patterns: string,\r\n functional_cookies: string,\r\n geo_city?: string,\r\n geo_country?: string,\r\n geo_countryname?: string;\r\n geo_lat: string,\r\n geo_long: string,\r\n geo_subdivision?: string,\r\n geo_zip?: string,\r\n locale?: ILocale,\r\n market?: MarketProperties,\r\n os?: OperatingSystemType,\r\n pagetype?: string,\r\n\r\n /** Query params in the format \"?key=value&...\" as observed from the PCS origin server */\r\n queryparams?: string,\r\n\r\n static_page?: string,\r\n verticalKey?: string,\r\n\r\n /** cache busting identifier sent by pcs */\r\n cbid?: string\r\n\r\n /** Peregrine Build version sent by PCS */\r\n v?: string\r\n}\r\n\r\nexport const EnterpiseFlightId = \"prg-enterpriseblended-t\";\r\nexport const OfficeDefaultPivotFlightId = \"prg-officedefault-t\";\r\n\r\n/**\r\n * Class for getting the head data information.\r\n */\r\nclass HeadData {\r\n /**\r\n * The single instance of the HeadData class.\r\n * @type {HeadData}\r\n */\r\n private static _instance: HeadData;\r\n\r\n private anonCookieName: string;\r\n private locale: string;\r\n private marketDir: string;\r\n private currentFlights: string;\r\n private clientSettings: IClientSettings;\r\n private enableCMSPPEConfigs: boolean = false;\r\n private userIsSignedIn: boolean; // Always signed out on server side: https://dev.azure.com/microsoft/OS/_workitems/edit/25344027\r\n private isPreload: boolean;\r\n private headElement: any;\r\n private htmlElement: any;\r\n private isAppcache: boolean;\r\n private isEnterprise: boolean;\r\n private isOfficeDefaultPivot: boolean;\r\n private isServiceWorkerCache: boolean;\r\n private ssoComplete: boolean;\r\n private aadState: boolean;\r\n\r\n private locationSearch: string;\r\n\r\n // TODO: Task 24890741: refactor this class to use the current singleton pattern with ES6 modules\r\n // This will also clean up these getters/setters\r\n public get Locale(): string { return this.locale; }\r\n public get MarketDir(): string { return this.marketDir; }\r\n public get CurrentFlights(): string { return this.currentFlights || \"\"; }\r\n public get ClientSettings(): IClientSettings { return this.clientSettings; }\r\n public get EnableCMSPPEConfigs(): boolean { return this.enableCMSPPEConfigs; }\r\n public get UserIsSignedIn(): boolean { return this.userIsSignedIn; }\r\n public get IsPreload(): boolean { return this.isPreload; }\r\n public get IsAppCache(): boolean { return this.isAppcache; }\r\n public get IsEnterprise(): boolean { return this.isEnterprise; }\r\n public get IsOfficeDefaultPivot(): boolean { return this.isOfficeDefaultPivot; }\r\n public get IsServiceWorkerCache(): boolean { return this.isServiceWorkerCache; }\r\n\r\n // TODO: Dependencies that some client side code expects headData to specify but doesn't due to PCS\r\n public get AnonCookieName(): string { return this.anonCookieName; }\r\n public get SsoComplete(): boolean { return this.ssoComplete; }\r\n public get AadState(): boolean { return this.aadState; }\r\n\r\n // For testing purposes add setters\r\n public set AnonCookieName(value: string) { this.anonCookieName = value; }\r\n public set LocaleName(value: string) { this.locale = value; }\r\n public set MarketDir(value: string) { this.marketDir = value; }\r\n public set CurrentFlights(value: string) { this.currentFlights = value; }\r\n public set ClientSettings(value: IClientSettings) { this.clientSettings = value; }\r\n public set IsEnterprise(value: boolean) { this.isEnterprise = value; }\r\n public set IsOfficeDefaultPivot(value: boolean) { this.isOfficeDefaultPivot = value; }\r\n public set UserIsSignedIn(value: boolean) { this.userIsSignedIn = value; }\r\n\r\n /**\r\n * Initialize the head data instance, on server side provide the client info & client settings\r\n * @param {WebClientData} clientData Data object containing both client info and settings\r\n */\r\n private constructor(clientData?: WebClientData) {\r\n this.initializeHeadData(clientData);\r\n }\r\n\r\n /**\r\n * Returns singleton class instance.\r\n * @returns {HeadData}\r\n */\r\n public static getInstance(): HeadData { return HeadData._instance || (HeadData._instance = new HeadData()); }\r\n\r\n /**\r\n * Reset singleton class instance with passed in info and client settings. Used on server side to reset HeadData for each request.\r\n * @param {WebClientData} clientData Data object containing both client info and settings\r\n * @returns {HeadData}\r\n */\r\n public static resetInstance(clientData?: WebClientData): HeadData {\r\n HeadData._instance = new HeadData(clientData);\r\n headData = HeadData._instance;\r\n return HeadData._instance;\r\n }\r\n\r\n /**\r\n * Initializes head data. If WebClientData is provided use that, otherwise do client side initialization.\r\n * @param {WebClientData} clientData - Data object containing both client info and settings\r\n */\r\n public initializeHeadData(clientData?: WebClientData): void {\r\n if (clientData) {\r\n // Data is passed in only from Render Service under Node.JS environment since there is no DOM.\r\n this.initializeFromData(clientData);\r\n return;\r\n }\r\n\r\n this.locationSearch = getLocationSearch();\r\n this.htmlElement = canUseDOM() ? getDocumentElementsByTagName(htmlElementIds.html)[0] : null;\r\n this.headElement = canUseDOM() ? getDocumentElementsByTagName(htmlElementIds.head)[0] : null;\r\n\r\n if (!this.htmlElement || !this.headElement) {\r\n return;\r\n }\r\n\r\n // We always initialize from DOM first because\r\n // even if we are in an appcache/service worker case, we still need some data from the DOM\r\n // and we will fallback to DOM if there are no items found in storage\r\n this.initializeFromDom();\r\n\r\n // Attempt to override with local storage item when in appcache scenario\r\n // In service worker scenario, just update the storage activity id\r\n if (this.htmlElement.getAttribute(applicationCacheConstants.manifestAttributeName)) {\r\n this.isAppcache = true;\r\n this.initializeFromStorage();\r\n } else if (window && window.navigator && window.navigator.serviceWorker && window.navigator.serviceWorker.controller) {\r\n this.isServiceWorkerCache = true;\r\n this.updateStorageActivityId();\r\n }\r\n\r\n // Below items are common for both scenarios\r\n const language = this.htmlElement.getAttribute(lang);\r\n this.locale = language && language.toLowerCase() || \"\";\r\n\r\n const marketDir = this.htmlElement.getAttribute(dir);\r\n this.marketDir = marketDir && marketDir.toLocaleLowerCase() || \"\";\r\n\r\n this.setQueryItemProvidedValues();\r\n\r\n // Note: This isn't currently being stamped by PCS\r\n let headDataJs = this.headElement.getAttribute(js);\r\n if (headDataJs) {\r\n const headJs = <{ anonckname: string, signedin: number }>tryParseJson(headDataJs);\r\n this.anonCookieName = headJs.anonckname;\r\n this.userIsSignedIn = headJs.signedin === 1;\r\n }\r\n\r\n // Checks if current request is background preload request\r\n if (UrlUtility.getQueryParameterByName(\"backgroundpreload\", this.locationSearch)) {\r\n this.isPreload = true;\r\n }\r\n\r\n // Determine if we are in Enterprise version or not\r\n this.setIsEnterprise();\r\n\r\n // Determine if Office is the default pivot\r\n this.setIsOfficeDefaultPivot();\r\n }\r\n\r\n /**\r\n * Helper that gets the current's page stored last used activityID (if there is one)\r\n */\r\n public getCurrentPageTypeStoredActivityId(): StoredActivityId {\r\n const storedActivities = localStorage.getItem(applicationCacheConstants.storedLastUsedActivityIdKey) || \"\";\r\n const storedActivityIds = tryParseJson(storedActivities);\r\n\r\n return (storedActivityIds && storedActivityIds[headData.ClientSettings.pagetype]) || null;\r\n }\r\n\r\n /**\r\n * Initializes the client settings and info from client data passed in externally (render service query param)\r\n * @param {WebClientData} clientData Data object containing both client info and settings\r\n */\r\n private initializeFromData(clientData: WebClientData): void {\r\n this.clientSettings =
tryParseJson(clientData.clientSettings);\r\n\r\n this.setFlights(clientData.clientInfo);\r\n\r\n this.setQueryItemProvidedValues();\r\n\r\n this.locale = clientData.language && clientData.language.toLowerCase() || \"\";\r\n this.marketDir = clientData.marketDir && clientData.marketDir.toLocaleLowerCase() || \"\";\r\n\r\n // Determine if we are in Enterprise version or not\r\n this.setIsEnterprise();\r\n\r\n // Determine if Office is the default pivot\r\n this.setIsOfficeDefaultPivot();\r\n }\r\n\r\n /**\r\n * Initializes the client settings and info from DOM element\r\n */\r\n private initializeFromDom(): void {\r\n let dataClientSettings = this.headElement.getAttribute(clientSettings);\r\n if (dataClientSettings) {\r\n this.clientSettings = tryParseJson(dataClientSettings);\r\n\r\n // If clientSettings.pagetype does not exist, try getting from data-pagetype.\r\n // For Peregrine full spa page: pagetype is part of data-client-settings. There is no data-pagetype.\r\n // For Prime/Hybrid, pagetype is outside of data-client-settings and it belongs to data-pagetype\r\n if (!this.clientSettings.pagetype) {\r\n const pageTypeFromSettings = this.headElement.getAttribute(pagetypeSettings);\r\n this.clientSettings.pagetype = pageTypeFromSettings === null ? undefined : pageTypeFromSettings;\r\n }\r\n }\r\n this.setFlights(this.headElement.getAttribute(info));\r\n }\r\n\r\n /**\r\n * Initializes headData client settings and info from the value found in storage\r\n * and if none is found, fallbacks to using the DOM element\r\n */\r\n private initializeFromStorage(): void {\r\n const responseFromStorage = localStorage.getItem(applicationCacheConstants.storedHeadDataKey);\r\n const parsedResponseFromStorage = tryParseJson(responseFromStorage);\r\n\r\n // If there is nothing store, then fallback to the DOM\r\n if (!parsedResponseFromStorage) {\r\n return;\r\n }\r\n\r\n const currentPageStoredHeadData = parsedResponseFromStorage[this.clientSettings.pagetype];\r\n\r\n // We don't have an entry for the current page\r\n if (!currentPageStoredHeadData) {\r\n return;\r\n }\r\n\r\n const storedClientSettings = currentPageStoredHeadData[\"clientSettings\"];\r\n const storedFlights = currentPageStoredHeadData[\"info\"];\r\n\r\n // The stored head data is corrupt so we fallback to DOM\r\n if (!storedClientSettings || !storedFlights) {\r\n return;\r\n }\r\n\r\n this.clientSettings = storedClientSettings;\r\n this.setFlights(storedFlights);\r\n this.updateStorageActivityId();\r\n }\r\n\r\n /**\r\n * Update the last used activity ID in storage\r\n */\r\n private updateStorageActivityId(): void {\r\n if (!this.clientSettings.aid) {\r\n return;\r\n }\r\n\r\n const existingLastUsedActivityIds = tryParseJson(localStorage.getItem(applicationCacheConstants.storedLastUsedActivityIdKey)) || {};\r\n const currentPageLastUsedActivityId: StoredActivityId = existingLastUsedActivityIds[this.clientSettings.pagetype];\r\n\r\n // If the current pages last used activity ID matches the one for the current page head data\r\n // then we have re-used this. Mark it as such but don't override the timestamp\r\n if (currentPageLastUsedActivityId && (currentPageLastUsedActivityId.id === this.clientSettings.aid)) {\r\n currentPageLastUsedActivityId.previouslyUsed = true;\r\n existingLastUsedActivityIds[this.clientSettings.pagetype] = currentPageLastUsedActivityId;\r\n } else {\r\n // If they don't match then that means we haven't used this so store the new value.\r\n const activityIdToStore: StoredActivityId = { id: this.clientSettings.aid, ts: (new Date()).getTime() };\r\n existingLastUsedActivityIds[this.clientSettings.pagetype] = activityIdToStore;\r\n }\r\n\r\n // Update the last used activity ID in storage\r\n localStorage.setItem(applicationCacheConstants.storedLastUsedActivityIdKey, JSON.stringify(existingLastUsedActivityIds));\r\n }\r\n\r\n /**\r\n * Parses flights from provided string (if in proper format of f:{flights})\r\n * and sets it to the headData object\r\n */\r\n private setFlights(flightString: string): void {\r\n // The comma separated list of flights enabled in current request\r\n this.currentFlights = ((/f:\\s*([^;]+)/i.exec(flightString) || {})[1] || \"\").toLowerCase();\r\n }\r\n\r\n /**\r\n * Determines if we are in Enterprise version based on clientSettings and currentFlights\r\n */\r\n private setIsEnterprise(): void {\r\n // We know we are in the Enterpise version of the page when both the audience mode is set to Enterprise\r\n // and the correct flight id is set.\r\n this.IsEnterprise = this.clientSettings &&\r\n this.currentFlights &&\r\n this.currentFlights.includes(EnterpiseFlightId) &&\r\n this.clientSettings.audienceMode === AudienceModeType.Enterprise;\r\n }\r\n\r\n /**\r\n * Read query items to determine the headdata variable values.\r\n */\r\n private setQueryItemProvidedValues(): void {\r\n const queryItems = UrlUtility.getParamsWithItems(getLocationSearch());\r\n const cmsItem = queryItems.find(item => item.key === \"cms\");\r\n if (cmsItem && cmsItem.value === \"ppe\") {\r\n this.enableCMSPPEConfigs = true;\r\n }\r\n \r\n // Test override to add flights for scope purposes\r\n this.setCurrentFlightsTestOverride(queryItems);\r\n }\r\n\r\n /**\r\n * Overrides currentFlights when hostname is localhost. Used for testing.\r\n */\r\n private setCurrentFlightsTestOverride(queryItems: KeyValueArray): void {\r\n if (getLocationHostname().toLowerCase().includes(\"localhost\") && queryItems) {\r\n const flights = queryItems.find(item => item.key === \"flights\");\r\n if (flights) {\r\n this.currentFlights = flights.value;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Determines if Office is the default pivot based on flight id.\r\n */\r\n private setIsOfficeDefaultPivot(): void {\r\n // There is work scheduled to have \"sticky\" pivots stored in some form of local storage which will\r\n // replace this check. Until then, the only way to know if Office is the default pivot is to check\r\n // for this flight id\r\n this.IsOfficeDefaultPivot = this.currentFlights && this.currentFlights.includes(OfficeDefaultPivotFlightId);\r\n }\r\n}\r\n\r\nexport const getHeadData = HeadData.getInstance;\r\n\r\n// headData can be reinitialized through resetHeadData.\r\nexport let headData = HeadData.getInstance();\r\n\r\n/**\r\n * Export function to reset headData based on WebClientData\r\n */\r\nexport const resetHeadData = HeadData.resetInstance;","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { IActionPayload } from \"./IActionPayload\";\r\nimport { IDataConnector } from \"../connectors\";\r\nimport PageBase from \"../pages/PageBase\";\r\n\r\n/**\r\n * Helper function to create an action payload\r\n * @param connector The connector (if applicable) where the action will be dispatched\r\n * @param type The Action Type (name of the action)\r\n * @param args Arguments to be passed to the action\r\n * @param experienceInstanceId If defined, the id of an experience instance, that will be used by action receiver\r\n */\r\nexport function getActionPayload(connector: IDataConnector, type: string, args: any[], experienceInstanceId: string): IActionPayload {\r\n let stateKey: string = undefined;\r\n if (connector) {\r\n if (!connector.parentNamespace) {\r\n stateKey = connector.namespace;\r\n } else {\r\n stateKey = connector.parentNamespace + \".\" + connector.namespace;\r\n }\r\n }\r\n\r\n return {\r\n key: stateKey,\r\n experienceInstanceId: experienceInstanceId,\r\n type: type,\r\n params: args\r\n };\r\n}\r\n\r\n/**\r\n * Helper function to dispatch an action either to a connector's namespaced store, or to the root store for the entire app.\r\n * @param connector The connector (if applicable) where the action will be dispatched\r\n * @param payload The action payload\r\n */\r\nexport function dispatchAction(connector: IDataConnector, payload: IActionPayload): any {\r\n\r\n // Dispatch the action\r\n if (connector) {\r\n return connector.store.dispatch(payload);\r\n } else {\r\n return PageBase.getInstance().store.dispatch(payload);\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\n\r\n/**\r\n * Cancellation Token class.\r\n * @class\r\n */\r\nexport class ActionDispatchCancellationToken implements IActionDispatchCancellationToken {\r\n /** Backing variable for the isCancellationRequested property\r\n * @type {boolean}\r\n */\r\n private isCancelled: boolean;\r\n\r\n /**\r\n * Creates an instance of the `ActionDispatchCancellationToken` class.\r\n * @constructor\r\n */\r\n constructor() {\r\n this.isCancelled = false;\r\n }\r\n\r\n /**\r\n * Helper method to cater for a null or undefined token.\r\n * A null or undefined token means cancellation cannot be requested, so it is equivalent to false\r\n * @method\r\n * @param {IActionDispatchCancellationToken} cancellationToken Optional cancellation token to be checked for undefined, null or cancellation requested\r\n * @returns {boolean}\r\n */\r\n public static isCancellationRequested(cancellationToken?: IActionDispatchCancellationToken): boolean {\r\n return !(cancellationToken === undefined || cancellationToken === null || !cancellationToken.isCancellationRequested);\r\n }\r\n\r\n /** The cancel method.\r\n * @method\r\n */\r\n public cancel(): void {\r\n this.isCancelled = true;\r\n }\r\n\r\n /** getter for the isCancellationRequested property\r\n * @property\r\n * @returns {boolean} Whether cancellation has been requested or not.\r\n */\r\n public get isCancellationRequested(): boolean {\r\n return this.isCancelled;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { dispatchAction, getActionPayload } from \"./ActionDispatchHelper\";\r\n\r\nimport { ActionDispatchCancellationToken } from \"./ActionDispatchCancellationToken\";\r\nimport { ConnectorConstants } from \"../constants/ConnectorConstants\";\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\nimport { IActionPayload } from \"./IActionPayload\";\r\nimport { Observer } from \"./ActionObserver\";\r\nimport { PerfTimeline } from '@msnews/diagnostics';\r\n\r\n/**\r\n * Class that wraps the sending of a action to a connector (i.e. dispatch) with an explicit method, so that in the consuming code\r\n * it is obvious that the action is being \"sent\"\r\n * @class\r\n */\r\nexport abstract class ActionSenderBase {\r\n /**\r\n * Property which is a function that will send an action to the connector.\r\n */\r\n public get send(): TActionSignature {\r\n return (this.dispatchAction());\r\n }\r\n\r\n /**\r\n * Creates an instance of the `ActionSender` class.\r\n * @constructor\r\n * @param {string} type The action type.\r\n * @param {IActionDispatchCancellationToken} cancellationToken Optional cancellation token, which can be used to cancel an in flight action\r\n */\r\n constructor(\r\n protected type: string,\r\n private observers: Observer[],\r\n private cancellationToken?: IActionDispatchCancellationToken) { }\r\n\r\n /**\r\n * Method to get dispatcher and payload\r\n * @param args - the arguments being dispatched\r\n * @returns dispatch result metadata\r\n */\r\n protected abstract getDispatchResult(args: any[]): { payload: IActionPayload, result: any };\r\n\r\n /**\r\n * Gets the perf timeline object if applicable\r\n */\r\n protected abstract tryGetPerfTimeline(): PerfTimeline;\r\n\r\n /**\r\n * Method that returns an action sender function to send the action.\r\n * @method\r\n * @return {TActionSignature} return value is a function to send to action.\r\n */\r\n private dispatchAction(): TActionSignature {\r\n return function (): any {\r\n if (!ActionDispatchCancellationToken.isCancellationRequested(this.cancellationToken)) {\r\n\r\n const perfTimeline = this.tryGetPerfTimeline();\r\n let actionEndMeasure = perfTimeline && perfTimeline.startMeasure(\"action\", this.type).endMeasure;\r\n\r\n const { payload, dispatchResult } = this.getDispatchResult(Array.prototype.slice.call(arguments));\r\n\r\n // Call any observers\r\n this.observers.forEach(o => {\r\n try {\r\n // Call the observer\r\n o.observer(payload);\r\n } catch (error) {\r\n console.log(`Error calling observer: ${JSON.stringify(o)}, with error: ${error}`);\r\n }\r\n\r\n // If there is a connector, dispatch an action to it, forcing it to re-render\r\n if (o.connector) {\r\n let renderActionPayload = getActionPayload(o.connector, ConnectorConstants.renderAction, [], undefined);\r\n dispatchAction(o.connector, renderActionPayload);\r\n }\r\n });\r\n\r\n if (actionEndMeasure) {\r\n actionEndMeasure();\r\n }\r\n\r\n // Return the dispatch result\r\n return dispatchResult;\r\n } else {\r\n // Don't dispatch the action because it has been canceled\r\n return;\r\n }\r\n };\r\n }\r\n\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { dispatchAction, getActionPayload } from \"./ActionDispatchHelper\";\r\n\r\nimport { ActionSenderBase } from \"./ActionSenderBase\";\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\nimport { IActionPayload } from \"./IActionPayload\";\r\nimport { IDataConnector } from \"../connectors\";\r\nimport { Observer } from \"./ActionObserver\";\r\nimport { PerfTimeline } from '@msnews/diagnostics';\r\n\r\n/**\r\n * Class that wraps the sending of a action to a connector (i.e. dispatch) with an explicit method, so that in the consuming code\r\n * it is obvious that the action is being \"sent\"\r\n * @class\r\n */\r\nexport class ActionSender extends ActionSenderBase {\r\n\r\n /**\r\n * Creates an instance of the `ActionSender` class.\r\n * @constructor\r\n * @param {string} type The action type.\r\n * @param {IDataConnector} connector The connector instance to dispatch the action to.\r\n * @param {IActionDispatchCancellationToken} cancellationToken Optional cancellation token, which can be used to cancel an in flight action\r\n */\r\n constructor(\r\n type: string,\r\n observers: Observer[],\r\n private connector: IDataConnector,\r\n cancellationToken?: IActionDispatchCancellationToken) {\r\n\r\n super(type, observers, cancellationToken);\r\n }\r\n\r\n /**\r\n * Core dispatch implementation for {GlobalActionSender}\r\n * @param args - the arguments being dispatched\r\n * @returns dispatch result metadata\r\n */\r\n protected getDispatchResult(args: any[]): { payload: IActionPayload, result: any } {\r\n let payload = getActionPayload(this.connector, this.type, args, undefined);\r\n let result = dispatchAction(this.connector, payload);\r\n return { payload, result };\r\n }\r\n\r\n /**\r\n * Gets the perf timeline if applicable\r\n */\r\n protected tryGetPerfTimeline(): PerfTimeline {\r\n return this.connector.perfTimeline;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { PerfTimeline, tryGetPerfTimeline } from '@msnews/diagnostics';\r\nimport { dispatchAction, getActionPayload } from \"./ActionDispatchHelper\";\r\n\r\nimport { ActionSenderBase } from \"./ActionSenderBase\";\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\nimport { IActionPayload } from './IActionPayload';\r\nimport { Observer } from \"./ActionObserver\";\r\n\r\n/**\r\n * Class that wraps the sending of a action globally to all connectors\r\n * @export\r\n * @class\r\n */\r\nexport class GlobalActionSender extends ActionSenderBase {\r\n\r\n /**\r\n * Creates an instance of the `GlobalActionSender` class.\r\n * @constructor\r\n * @param {string} type The action type.\r\n * @param {string} experienceInstanceId Optional experienceInstanceId of the experience that is originating the action.\r\n * @param {IActionDispatchCancellationToken} cancellationToken Optional cancellation token, which can be used to cancel an in flight action.\r\n */\r\n constructor(\r\n type: string,\r\n observers: Observer[],\r\n private experienceInstanceId?: string,\r\n cancellationToken?: IActionDispatchCancellationToken) {\r\n\r\n super(type, observers, cancellationToken);\r\n }\r\n\r\n /**\r\n * Core dispatch implementation for {GlobalActionSender}\r\n * @param args - the arguments being dispatched\r\n * @returns dispatch result metadata\r\n */\r\n protected getDispatchResult(args: any[]): { payload: IActionPayload, result: any } {\r\n let payload = getActionPayload(undefined, this.type, args, this.experienceInstanceId);\r\n let result = dispatchAction(undefined, payload);\r\n return { payload, result };\r\n }\r\n\r\n /**\r\n * Gets the perf timeline if applicable\r\n */\r\n protected tryGetPerfTimeline(): PerfTimeline {\r\n return tryGetPerfTimeline(\"GlobalActionSender\", this.experienceInstanceId || \"unknown\");\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ActionObserver, Observer } from \".\";\r\n\r\nimport { ActionSender } from \"./ActionSender\";\r\nimport { GlobalActionSender } from \"./GlobalActionSender\";\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\nimport { IActionMap } from \"./IActionMap\";\r\nimport { IDataConnector } from \"../connectors/IDataConnector\";\r\nimport PageBase from \"../pages\";\r\n\r\n/**\r\n * Class that maps Action to its callback function type.\r\n * Provides the method to get action creator which returns callback function to send to action.\r\n * Callback function dispatches the action payload.\r\n * @class\r\n */\r\nexport class ActionMap implements IActionMap {\r\n\r\n /**\r\n * An array of registered action observers\r\n */\r\n private observers: Observer[] = [];\r\n\r\n /**\r\n * Creates an instance of the `ActionMap` class.\r\n * @constructor\r\n * @param {string} type The action type, which is part of the IActionMap contract.\r\n */\r\n constructor(public type: string) {\r\n }\r\n\r\n /**\r\n * Method that returns an action sender function that can be used to send/dispatch the action to a specific connector\r\n * @method\r\n * @param {IDataConnector | string} connector The connector instance to send the action to, or the connector namespace. If the param type\r\n * is string, then the connector instance will be looked up, and used if found.\r\n * @param {IActionDispatchCancellationToken} cancellationToken If passed in and cancellation has been requested, then nothing is dispatched.\r\n * @return {TActionSignature} return value is an object with a send method, which is used to send the action.\r\n */\r\n public getActionSender(connector: IDataConnector | string, cancellationToken?: IActionDispatchCancellationToken): ActionSender | undefined {\r\n let connectorInstance: IDataConnector = undefined;\r\n if (typeof(connector) === \"string\") {\r\n // Find the connector with the matching namespace\r\n connectorInstance = PageBase.getInstance().rootReducer.connector(connector);\r\n } else {\r\n connectorInstance = connector;\r\n }\r\n\r\n if (connectorInstance) {\r\n return new ActionSender(this.type, this.observers, connectorInstance, cancellationToken);\r\n }\r\n }\r\n\r\n /**\r\n * Method that returns an action sender function that can be used to send/dispatch the action globally to all connectors\r\n * @method\r\n * @param {string} experienceInstanceId An optional experienceInstanceId, that will get passed along in the action payload.\r\n * It can then be used by the receiving reducer to determine if the action should be handled.\r\n * @param {IActionDispatchCancellationToken} cancellationToken If passed in and cancellation has been requested, then nothing is dispatched.\r\n * @return {TActionSignature} return value is an object with a send method, which is used to send the action.\r\n */\r\n public getGlobalActionSender(experienceInstanceId?: string, cancellationToken?: IActionDispatchCancellationToken): GlobalActionSender {\r\n return new GlobalActionSender(this.type, this.observers, experienceInstanceId, cancellationToken);\r\n }\r\n\r\n /**\r\n * Method that registers a new observer for this action. The observer will be called after the action is dispatched\r\n * @method\r\n * @param {ActionObserver} observer The observer to be added to the list of observers that will be called when the action completes\r\n */\r\n public registerObserver(observer: ActionObserver, connector?: IDataConnector): void {\r\n this.observers.push({ observer: observer, connector: connector });\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n// Defines constants used in telemetry beacons\r\n\r\nexport default {\r\n // logSamplingRate was configured via %app_error_log_sampling_rate% in Prime. Hardcoding \"0\" here.\r\n logSamplingRate: \"0\",\r\n FireTelemetry: \"fireTelemetryBeacon\",\r\n GET: \"GET\",\r\n POST: \"POST\",\r\n Ctag: \"ctag\",\r\n Comscore: \"scorecard\",\r\n OTF: \"udc\",\r\n Exp: \"EX:\",\r\n ResetIdx: \"resetTelemetryEventIndex\"\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { KeyValueArray, KeyValuePair, Utility } from \"./Utility\";\r\nimport { findIndex, isArray, isEmpty, isString, trimEnd, trimStart } from \"lodash-es\";\r\n\r\nimport { StringMap } from \"../types\";\r\nimport { getLocationOrigin } from \"@msnews/isomorphic-util\";\r\n\r\nexport namespace UrlUtility {\r\n\r\n /**\r\n * Characters that, if present on a url, will make prime routing misbehave\r\n *\r\n * These are the characters we know cause problems:\r\n * - spaces\r\n * - slashes\r\n * - punctuation: !?.:\r\n * - ampersands\r\n *\r\n * As we don't know all the offending characters, we are just removing every character that is not alphanumeric\r\n */\r\n const primeForbiddenCharacters: RegExp = /[^A-Za-z0-9]+/g;\r\n\r\n /**\r\n * Parse parameters from the given URL\r\n * @param {string} url - the URL to parse for parameters\r\n * @param {boolean} decodeComponents - flag to indicate whether the query param key and value should be URL decoded\r\n * @returns {KeyValueArray} - the parsed query key/value collection\r\n */\r\n export function getParamsFromUrl(url: string, decodeComponents: boolean = false): KeyValueArray {\r\n if (!isString(url)) {\r\n return null;\r\n }\r\n\r\n let queryString: string = (url || \"\").split(\"?\")[1];\r\n return getParams(queryString, decodeComponents);\r\n }\r\n\r\n /**\r\n * Decode the given URL encoded string that may contain plus signs\r\n * @param {string} val - The value to decode.\r\n * @returns {string} - the decoded value\r\n */\r\n function decodeURIComponentWithPlusSign(val: string): string {\r\n val = val.replace(/\\+/g, \" \");\r\n val = decodeURIComponent(val);\r\n return val;\r\n }\r\n\r\n /**\r\n * Encode uri components in a way that won't break prime routing system\r\n * @param uriComponent the uriComponent to be encoded\r\n */\r\n export function encodeURIComponentForPrime(uriComponent: string): string {\r\n return encodeURIComponent(uriComponent.replace(primeForbiddenCharacters, \"-\"));\r\n }\r\n\r\n /**\r\n * Parse parameters from the given query string\r\n * @param {string} queryString - the query string to parse for parameters\r\n * @param {boolean} decodeComponents - flag to indicate whether the query param key and value should be URL decoded\r\n * @returns {KeyValueArray} - the parsed query key/value collection\r\n */\r\n export function getParams(queryString: string, decodeComponents: boolean = false): KeyValueArray {\r\n\r\n let params: KeyValueArray = [];\r\n\r\n if (queryString) {\r\n // remove hash part.\r\n queryString = queryString.split(\"#\")[0];\r\n let queryArray = queryString.split(\"&\");\r\n for (let ndx = 0; ndx < queryArray.length; ndx++) {\r\n let parts = queryArray[ndx].split(\"=\");\r\n let queryKey = parts[0];\r\n let queryValue = parts[1];\r\n\r\n if (decodeComponents) {\r\n queryKey = decodeURIComponentWithPlusSign(queryKey);\r\n if (queryValue) {\r\n queryValue = decodeURIComponentWithPlusSign(queryValue);\r\n }\r\n }\r\n\r\n // Don't allow for duplicate query string parameter keys. Take the last one\r\n let newParam: KeyValuePair = { key: queryKey, value: queryValue };\r\n let existingParam = findIndex(params, (entry) => entry.key === newParam.key);\r\n if (existingParam === -1) {\r\n params.push(newParam);\r\n } else {\r\n params[existingParam] = newParam;\r\n }\r\n }\r\n }\r\n return params;\r\n }\r\n\r\n /**\r\n * Parse parameters from the given query string, allowing for multiple item=key:value\r\n * @param {string} queryString - the query string to parse for parameters\r\n * @returns {KeyValueArray} - the parsed query key/value collection\r\n */\r\n export function getParamsWithItems(queryString: string): KeyValueArray {\r\n let params: KeyValueArray = [];\r\n\r\n if (queryString) {\r\n // Remove the leading ? if it is present\r\n if (queryString.startsWith(\"?\")) {\r\n queryString = queryString.substring(1);\r\n }\r\n\r\n // split on the hashes.\r\n queryString = queryString.split(\"#\")[0];\r\n let queryArray = queryString.split(\"&\");\r\n for (let ndx = 0; ndx < queryArray.length; ndx++) {\r\n let parts = queryArray[ndx].split(\"=\");\r\n let queryKey = parts[0];\r\n let queryValue = parts[1];\r\n\r\n // If the query key is \"item\", and the query values is key:value, then convert the\r\n // value into the actual key/value\r\n if (queryKey.toLowerCase() === \"item\") {\r\n let queryItems = queryValue.split(\":\");\r\n if (queryItems.length === 2) {\r\n queryKey = queryItems[0];\r\n queryValue = queryItems[1];\r\n }\r\n }\r\n\r\n // Don't allow for duplicate query string parameter keys. Take the last one\r\n let newParam: KeyValuePair = { key: queryKey, value: queryValue };\r\n let existingParam = params.findIndex((entry) => entry.key === newParam.key);\r\n if (existingParam === -1) {\r\n params.push(newParam);\r\n } else {\r\n params[existingParam] = newParam;\r\n }\r\n }\r\n }\r\n return params;\r\n }\r\n\r\n /**\r\n * Utility method to extract query string param in url.\r\n *\r\n * @export\r\n * @param {string} name - query param name\r\n * @returns {string} - query param value\r\n */\r\n export function getQueryParameterByName(name: string, href: string): string {\r\n\r\n // TODO: exposing this method for accessing a single parameter can be used\r\n // extremely inefficiently (for example if invoked multiple times to get parameters\r\n // from a single URL). Instead we should deprecate this and export getParamsObj\r\n // and use that throughout.\r\n\r\n let value = getParamsObj(href)[name];\r\n return (value !== undefined)\r\n ? value\r\n : null;\r\n }\r\n\r\n /**\r\n * Check if given url string is a valid url.\r\n * Returns true when url string is a valid url, otherwise false.\r\n *\r\n * @export\r\n * @param url {string} - Url string value to check\r\n * @param validateScheme {boolean} - Should scheme validation be forced\r\n * @return {boolean}\r\n */\r\n export function isValidUrl(url: string, validateScheme: boolean): boolean {\r\n return (isString(url) &&\r\n (url.length > 0) &&\r\n (!validateScheme ||\r\n validateScheme && url.indexOf(\"http\") === 0));\r\n }\r\n\r\n /**\r\n * Converts a keyValueArray into a set of query string parameters\r\n *\r\n * @export\r\n * @param {any} - params to be converted\r\n * @return {string}\r\n */\r\n export function keyValueArrayToQueryString(params: KeyValueArray): string {\r\n // Validate we have a nonempty array\r\n if (!isArray(params) || isEmpty(params)) {\r\n return \"\";\r\n }\r\n\r\n // Filter for valid keyValue entries, and then map them into key==value strings\r\n // joined with an &\r\n const queryString: string = params.filter(kv =>\r\n Utility.isKeyValuePair(\r\n kv,\r\n (key) => typeof (key) === \"string\",\r\n (value) => typeof (value) === \"string\"))\r\n .map(kv => kv.key + \"=\" + kv.value)\r\n .join(\"&\");\r\n\r\n return queryString;\r\n }\r\n\r\n /**\r\n * Helper method to parse the given URLs query parameters to a lookup dictionary\r\n * @param url - the URL string with the query params to parse\r\n * @returns The {StringMap} containing the key/value pairs, or empty object.\r\n */\r\n function getParamsObj(url: string): StringMap {\r\n let paramsObj = {};\r\n let paramArray = getParamsFromUrl(url, true);\r\n if (paramArray && paramArray.length) {\r\n paramArray.forEach(keyValuePair =>\r\n paramsObj[keyValuePair.key] = keyValuePair.value);\r\n }\r\n return paramsObj;\r\n }\r\n\r\n /**\r\n * For the given `url`, it appends the `subPath` to it.\r\n * It takes propers care to forward slashes characters\r\n * at the end of `url` and at the start of `subPath` parameters\r\n * @param url a valid url\r\n * @param subPath the path which is appended to `url`\r\n * @returns an URL object which is the `url` appended by `subPath`\r\n */\r\n export function joinSubpathToURL(url: URL, subPath: string): URL {\r\n const href = url.href;\r\n const trimmedEndSlashFromHref = trimEnd(href, \"/\");\r\n const trimmedStartSlashFromSubpath = trimStart(subPath, \"/\");\r\n return new URL(`${trimmedEndSlashFromHref}/${trimmedStartSlashFromSubpath}`);\r\n }\r\n\r\n /**\r\n * Updates a search parameter in the given url to map to a new value\r\n * Does not modify the url if the given search param doesn't exist\r\n * @param url the url to update\r\n * @param key the name of the search param to be updated\r\n * @param value the new value for the given search param\r\n * @returns {URL} the updated URL\r\n */\r\n export function updateSearchParam(url: URL, key: string, value: string): URL {\r\n // Note that the searchParams data member may not be compatible with older browser versions\r\n // see https://caniuse.com/#search=searchparams\r\n if (url && url.searchParams && url.searchParams.get(key)) {\r\n url.searchParams.set(key, value);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Appends a search parameter to the given url\r\n * @param url the url to modify\r\n * @param key the name of the search param to be appended\r\n * @param value the new value for the given search param\r\n * @returns {URL} the modified URL\r\n */\r\n export function appendSearchParam(url: URL, key: string, value: string, fallback?: boolean): URL {\r\n if (url) {\r\n if (url.searchParams || fallback) {\r\n url.searchParams.append(key, value);\r\n } else {\r\n // TODO Bug 22390312: [Peregrine] UrlUtility appendSearchParam needs more robust polyfill\r\n url = new URL(url.href + (url.search.indexOf(\"?\") >= 0 ? \"&\" : \"?\") + key + \"=\" + value);\r\n }\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Returns an absolute URL if a relative on is passed in, or returns the passed in URL if already absolute\r\n * @param partialUrl The relative or absolute URL\r\n * @returns {string} the absolute URL\r\n */\r\n export function getAbsoluteUrl(partialUrl: string): string {\r\n if (partialUrl.indexOf('://') > 0 || partialUrl.indexOf('//') === 0) {\r\n return partialUrl;\r\n } else {\r\n return getLocationOrigin() + partialUrl;\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * locationHref of page\r\n */\r\nexport const locationHref = (typeof(window) !== \"undefined\" ? window.location.href : \"\");\r\n\r\n/**\r\n * localStorage key prefix for render cache object\r\n */\r\nexport const storagePrefix = `lastKnown_`;\r\n\r\n/**\r\n * localStorage key prefix for render cache expiration timestamp\r\n */\r\nexport const expirationPrefix = `timestamp_`;\r\n\r\n/**\r\n * localStorage key for JSS Map object\r\n */\r\nexport const jssMapKey = `${storagePrefix}${locationHref}_jssmap`;\r\n\r\n/**\r\n * localStorage key for render cache object\r\n */\r\nexport const renderCacheKey = `${storagePrefix}${locationHref}`;\r\n\r\n/**\r\n * localStorage key for render cache expiration timestamp\r\n */\r\nexport const renderCacheExpirationKey = `${expirationPrefix}${locationHref}`;\r\n\r\n/**\r\n * render-cache expiration time in ms\r\n * 86400000 = 24 hours in milliseconds\r\n */\r\nexport const defaultExpirationTimeMs = 86400000;\r\n\r\n/**\r\n * River Render Cache ClassName\r\n */\r\nexport const riverRcClassName = \"river-rc\";","// © Microsoft Corporation. All rights reserved.\r\n/// Adds basic dom manipulation functions to an object defined as \"dom\"\r\n\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\n\r\nvar doc = canUseDOM() ? document : null;\r\nvar otherWhitespaceRegex = /[\\n\\t]/g;\r\nvar trimRegex = /(^\\s+)|(\\s+$)/mg;\r\n\r\n// curly brace needs to be on the return line otherwise build with throw an error\r\nexport default {\r\n attr: function (elem, attr) {\r\n // getAttribute(attr, 2) causes IE to only report correct values for href.\r\n // IE reports href values for IMG tags without an href property\r\n // see http://reference.sitepoint.com/javascript/Element/getAttribute\r\n // see bug #1131443\r\n return elem && (elem.getAttribute ? elem.getAttribute(attr, 2) : elem[attr]) || \"\";\r\n },\r\n name: function (elem) {\r\n return elem && elem.nodeName || \"\";\r\n },\r\n text: function (elem) {\r\n return (elem && (elem.textContent || elem.innerText) || \"\").replace(trimRegex, \"\");\r\n },\r\n children: function (elem) {\r\n return elem && elem.children || [];\r\n },\r\n parent: function (elem) {\r\n return elem && elem.parentNode;\r\n },\r\n getElementsByTagName: function (name) {\r\n return doc ? doc.getElementsByTagName(name) : [];\r\n },\r\n create: function (name) {\r\n return doc ? doc.createElement(name) : null;\r\n },\r\n containsClass: function (element, className) {\r\n /// \r\n /// Looks for the className in element and returns true/false based on result.\r\n /// \r\n /// element - Element where className to be searched for.\r\n /// className - Class name to be looked for.\r\n /// \r\n /// \r\n return element && ((\" \" + (element.className || element.getAttribute(\"class\")) + \" \")\r\n .replace(otherWhitespaceRegex, \" \").indexOf(\" \" + className + \" \") > -1);\r\n },\r\n getTarget: function (event) {\r\n return event && (event.customTarget || event.target || event.srcElement) || doc;\r\n }\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Constants that are used throughout the library\r\n */\r\nexport namespace ConnectorConstants {\r\n /**\r\n * The key within a state JSON document used to store a connectors individual state\r\n */\r\n export const connectorStateKey: string = \"_@STATE@_\";\r\n\r\n export const renderAction: string = \"@@connector-view/RENDER\";\r\n\r\n export const dataConnectorMergeInitAction: string = \"@@data-connector/MERGE-INIT\";\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n// Usage:\r\n// pass data to any callback that has subscribed to the event\r\n// mediator.pub(event, data);\r\n//\r\n// call the callback whenever this event is published\r\n// mediator.sub(event, callback)\r\n//\r\n// pass data to any callback that has subscribed to this event and channel\r\n// mediator.pubChannel(event, channel, data);\r\n//\r\n// call the callback whenever this event is published to this channel\r\n// mediator.subChannel(event, channel, callback)\r\n//\r\n// Think of pub/sub as using their own channel, useful for 1 ofs or app communication.\r\n// Channels are useful when multiple copies of the same widget want to communicate.\r\n\r\n/// Constructor for mediator object\r\n/// Mediator object\r\n\r\n/// Default publish subscribe where all non-channel-specific events are managed\r\n// @ts-ignore\r\nvar defaultPubSub = new PublishSubscribe();\r\nvar channels = {};\r\nexport default {\r\n pub: defaultPubSub.pub,\r\n sub: defaultPubSub.sub,\r\n unsub: defaultPubSub.unsub,\r\n pubChannel: function (event, channel, data)\r\n {\r\n /// Publishes event to channel subscribers only\r\n /// Event to subscribe to\r\n /// Name of the channel\r\n /// Data to pass to the callback\r\n getChannel(channel).pub(event, data);\r\n },\r\n subChannel: function (event, channel, callback)\r\n {\r\n /// Subscribes to event published on a specific channel\r\n /// Event to subscribe to\r\n /// Name of the channel\r\n /// Function to call when the event is fired\r\n getChannel(channel).sub(event, callback);\r\n },\r\n unsubChannel: function (event, channel, callback)\r\n {\r\n /// Unsubscribe from an event published on a specific channel\r\n /// Event to subscribe to\r\n /// Name of the channel\r\n /// Function to call when the event is fired\r\n getChannel(channel).unsub(event, callback);\r\n }\r\n};\r\n\r\nfunction getChannel(channel)\r\n{\r\n /// Gets a channel from the collection of mediator channels\r\n /// ID of the channel\r\n /// Channel requested or new channel if not exist\r\n if (!channels[channel])\r\n {\r\n // @ts-ignore\r\n channels[channel] = new PublishSubscribe();\r\n }\r\n return channels[channel];\r\n}\r\n\r\nfunction PublishSubscribe()\r\n{\r\n /// PublishSubscribe factory\r\n /// PubSub Object\r\n var pubMap = {};\r\n return {\r\n pub: function (event, data)\r\n {\r\n /// Passes data to any callback that has subscribed to the event\r\n /// Event being published\r\n /// Data to pass to the callback\r\n var callbacks = pubMap[event];\r\n\r\n if (callbacks)\r\n {\r\n for (var ndx = 0; ndx < callbacks.length; ndx++)\r\n {\r\n callbacks[ndx](data);\r\n }\r\n }\r\n },\r\n sub: function (event, callback)\r\n {\r\n /// Subscribes the callback to this event\r\n /// Event to subscribe to\r\n /// Function to call when the event is fired\r\n if (typeof callback == \"function\")\r\n {\r\n var listeners = pubMap[event];\r\n\r\n if (!listeners)\r\n {\r\n listeners = [];\r\n pubMap[event] = listeners;\r\n }\r\n listeners.push(callback);\r\n }\r\n },\r\n unsub: function (event, callback)\r\n {\r\n /// Unsubscribes a callback from an event\r\n /// Event to unsubscribe from\r\n /// Function to unsubscribe from the event\r\n var listeners = pubMap[event];\r\n\r\n if (listeners)\r\n {\r\n for (var ndx = 0; ndx < listeners.length; ndx++)\r\n {\r\n if (listeners[ndx] === callback)\r\n {\r\n listeners.splice(ndx--, 1);\r\n }\r\n }\r\n }\r\n }\r\n };\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Client side properties that Render Service sends to initialize RequestData.\r\n * These properties are typically passed via query param to the render service.\r\n * On the client side these are available and populated through the DOM.\r\n */\r\nexport interface RequestProps {\r\n\r\n /**\r\n * URL for the original client request.\r\n */\r\n href: string;\r\n\r\n /**\r\n * Width of client browser window.\r\n */\r\n innerWidth: number;\r\n\r\n /**\r\n * Height of client browser window.\r\n */\r\n innerHeight: number;\r\n\r\n /**\r\n * Device pixel ratio of client.\r\n */\r\n devicePixelRatio: number;\r\n\r\n /**\r\n * CSS Grid support of the client browser.\r\n */\r\n canUseCssGrid: boolean;\r\n\r\n /**\r\n * Request Id.\r\n */\r\n requestId: number;\r\n}\r\n\r\n/**\r\n * Singleton class to store client browser data sent through query param to Render Service.\r\n * This is only used under server environment.\r\n */\r\nclass RequestData {\r\n /**\r\n * The single instance of the RequestData class.\r\n * @type {RequestData}\r\n */\r\n private static _instance: RequestData = null;\r\n\r\n /**\r\n * URL object to be used to store original request url.\r\n */\r\n public readonly url: URL;\r\n\r\n /**\r\n * Inner width of browser from the original request.\r\n */\r\n public readonly innerWidth: number;\r\n\r\n /**\r\n * Inner height of browser from the original request.\r\n */\r\n public readonly innerHeight: number;\r\n\r\n /**\r\n * Device pixel ratio from the original request.\r\n */\r\n public readonly devicePixelRatio: number;\r\n\r\n /**\r\n * Boolean flag that represents if CSS Grid is supported by the browser from the original request.\r\n */\r\n public readonly canUseCssGrid: boolean;\r\n\r\n /**\r\n * Request Id.\r\n */\r\n public readonly requestId: number;\r\n\r\n /**\r\n * Initialize the request data instance with passed in client properties\r\n */\r\n private constructor(data: RequestProps) {\r\n this.url = new URL(data.href);\r\n this.innerWidth = data.innerWidth;\r\n this.innerHeight = data.innerHeight;\r\n this.devicePixelRatio = data.devicePixelRatio;\r\n this.canUseCssGrid = data.canUseCssGrid;\r\n this.requestId = data.requestId;\r\n }\r\n\r\n /**\r\n * Returns singleton class instance.\r\n * @returns RequestData\r\n */\r\n public static getInstance(): RequestData {\r\n if (global[\"TEST_ENV\"] && !RequestData._instance) {\r\n resetRequestData({\r\n href: \"http://localhost:8080/\",\r\n innerWidth: 1024,\r\n innerHeight: 768,\r\n devicePixelRatio: 1,\r\n canUseCssGrid: false,\r\n requestId: 0\r\n });\r\n }\r\n\r\n if (!RequestData._instance) {\r\n // Throw error if the request data has not been set as this should never be the case.\r\n // This likely highlights that the request data was not initialized when handling a\r\n // request when server side rendering.\r\n throw new Error(\"Request data is not initialized yet through ResetInstance.\");\r\n }\r\n return RequestData._instance;\r\n }\r\n\r\n /**\r\n * Reset singleton class instance with passed in info and client settings\r\n * @returns RequestData\r\n */\r\n public static resetInstance(data: RequestProps): RequestData {\r\n RequestData._instance = new RequestData(data);\r\n return RequestData._instance;\r\n }\r\n}\r\n\r\n/**\r\n * Export function to reset the request data singleton.\r\n * This must be used to set the request data.\r\n */\r\nexport const resetRequestData = RequestData.resetInstance;\r\n\r\n/**\r\n * Export get instance function for testing\r\n */\r\nexport const getRequestData = () => (RequestData.getInstance());","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { AadData, clientId, oneServiceScope } from \"./Enterprise\";\r\nimport { AccountType, AppType, AudienceModeType, AuthCookieName } from \"@msnews/experiences-constants\";\r\nimport { EnterpriseOneServiceApi, appAnonCookieExistsCookieName, childCookieName, rootElementId, serviceUrl, telemetryId, trackPageProduct, trackPageType } from \"../constants\";\r\nimport { Environment, getEnvironmentFromString } from \"./Environment\";\r\nimport { HostPage, IHostPage } from \"./HostPage\";\r\nimport { canUseDOM, getDocumentElementById, getLocationHref, getLocationOrigin, getLocationSearch } from \"@msnews/isomorphic-util\";\r\nimport { getCookie, getMuidCookie } from \"../utilities/CookieUtility\";\r\n\r\nimport { Market } from \"./Market\";\r\nimport { PageRequestTargetScope } from \"./PageRequestTargetScope\";\r\nimport { PlatformType } from \"cms-models-msn/configuration/types/PlatformType\";\r\nimport { UrlUtility } from \"../utilities/UrlUtility\";\r\nimport { Utility } from \"../utilities/Utility\";\r\nimport { headData } from \"./HeadData\";\r\nimport { isString } from \"lodash-es\";\r\nimport { logger } from \"@msnews/diagnostics\";\r\n\r\n/**\r\n * chrome\r\n * The chrome API is not defined in Typescript\r\n */\r\ndeclare global {\r\n // tslint:disable-next-line: completed-docs\r\n interface Window { chrome: any; }\r\n}\r\n\r\n/**\r\n * Page level experience tracking info\r\n */\r\nexport interface ITrackInfo {\r\n sitePage: {\r\n page_product: string,\r\n page_type: string\r\n }\r\n}\r\n\r\nexport class AppEnvironment {\r\n /**\r\n * The single instance of the AppEnvironment class.\r\n * @type {AppEnvironment}\r\n */\r\n private static _instance: AppEnvironment;\r\n\r\n /**\r\n * the activity id for the current page view\r\n */\r\n private activityId: string;\r\n\r\n /**\r\n * Base url for the content service, endpoints/queries are appended for specific content calls.\r\n * This is an akamai url for highly cacheable content.\r\n * Possible values are enumerated on ContentServiceConfig.ts\r\n *\r\n * @private\r\n * @type {string}\r\n * @memberof AppEnvironment\r\n */\r\n private contentServiceUrlBase: URL;\r\n\r\n private currentRequestTargetScope: PageRequestTargetScope;\r\n\r\n private currentMarket: Market;\r\n private hostPage: IHostPage;\r\n\r\n /** The hostname to use for content links. */\r\n private currentContentLinkHost: string;\r\n\r\n /**\r\n * Indicates that the page is running as an FRE page (i.e. the url contains fre=1)\r\n * Does not indicate that the FRE itself is currently displayed over the page.\r\n */\r\n private isFrePage: boolean;\r\n\r\n /**\r\n * Base for the service url, endpoints/queries are appended for specific service calls.\r\n * This is the OneService url used for personalized content.\r\n * Possible values are enumerated on OneServiceConfig.ts\r\n *\r\n * @private\r\n * @type {string}\r\n * @memberof AppEnvironment\r\n */\r\n private serviceUrlBase: URL;\r\n\r\n /**\r\n * Base URL for the feed service\r\n */\r\n private feedServiceUrlBase: URL;\r\n\r\n /**\r\n * The account type of the page user\r\n * Currently this is only implemented for the Anaheim New Tab Pages\r\n */\r\n private accountType: AccountType;\r\n\r\n /**\r\n * The aad data for the current page user\r\n */\r\n private aadDataPromise: Promise;\r\n\r\n private appType: string;\r\n private authCookieName: AuthCookieName;\r\n private buildVersion: string;\r\n\r\n private environmentConfigUrl: URL;\r\n\r\n private rootTelemetryId: number;\r\n private trackInfo: ITrackInfo;\r\n private userId: string;\r\n private countryCode: string;\r\n private latitude: string;\r\n private longitude: string;\r\n private environment: Environment;\r\n private featureFlags: any;\r\n private disableCachingConfigs: boolean;\r\n private enableConfigService: boolean;\r\n private isMultiConfigRetrievalEnabled: boolean;\r\n private configServiceBaseUrl: URL;\r\n private disableContentPreviewCache: boolean;\r\n private disableContentCacheIDBRead: boolean;\r\n private disableContentListCache: boolean;\r\n private disableContentListCacheIDBRead: boolean;\r\n private sendFeedCallActivityIdInHeader: boolean;\r\n\r\n /** True if query string has appropriate debug flag */\r\n private isDebug: boolean;\r\n\r\n /** True if query string has appropriate flag to show msnCreatorDashboard (msnDash=) */\r\n private showMnsCreatorDashboard: boolean;\r\n\r\n /** Config Root Url */\r\n private configRootUrl: URL;\r\n\r\n /** Cache busting identifier received from pcs */\r\n private cacheBustingIdentifier: string;\r\n\r\n /**\r\n * ActivityId value from initial server response, use telemetry's requestId instead for associating with current page client navigation\r\n */\r\n public get ActivityId(): string { return this.activityId; }\r\n\r\n /**\r\n * Getter for the base url for the content service, endpoints/queries are appended for specific content calls.\r\n * This is an akamai url for highly cacheable content.\r\n * Possible values are enumerated on ContentServiceConfig.ts\r\n *\r\n * @readonly\r\n * @type {URL}\r\n * @memberof AppEnvironment\r\n */\r\n public get EnvironmentConfigUrl(): URL {\r\n // If I mutate the same object, I will need to revert to the original state somewhere.\r\n // For safety reason, it is better to use a new Object\r\n const url = new URL(\"\", this.environmentConfigUrl);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.config\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.config\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.config\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Getter for the base url for the content service, endpoints/queries are appended for specific content calls.\r\n * This is an akamai url for highly cacheable content.\r\n * Possible values are enumerated on ContentServiceConfig.ts\r\n *\r\n * @readonly\r\n * @type {URL}\r\n * @memberof AppEnvironment\r\n */\r\n public get ContentServiceUrlBase(): URL {\r\n // If I mutate the same object, I will need to revert to the original state somewhere.\r\n // For safety reason, it is better to use a new Object\r\n const url = new URL(\"\", this.contentServiceUrlBase);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.content\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.content\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.content\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n public get CurrentRequestTargetScope(): PageRequestTargetScope { return this.currentRequestTargetScope; }\r\n public get CurrentMarket(): Market { return this.currentMarket; }\r\n public get Environment(): Environment { return this.environment; }\r\n public get HostPage(): IHostPage { return this.hostPage; }\r\n public get AppType(): string { return this.appType; }\r\n public get AuthCookieName(): AuthCookieName { return this.authCookieName; }\r\n public get AccountType(): AccountType { return this.accountType; }\r\n public get AadDataPromise(): Promise { return this.aadDataPromise; }\r\n public get BuildVersion(): string { return this.buildVersion; }\r\n\r\n /** True if query string has appropriate debug flag */\r\n public get IsDebug(): boolean { return this.isDebug; }\r\n\r\n /** True if query string has appropriate flag to show msnCreatorDashboard (msnDash=) */\r\n public get ShowMnsCreatorDashboard(): boolean { return this.showMnsCreatorDashboard; }\r\n\r\n /**\r\n * Gets the host to use when linking to content.\r\n */\r\n public get contentLinkHost(): string { return this.currentContentLinkHost; }\r\n\r\n /**\r\n * Getter for the base for the service url, endpoints/queries are appended for specific service calls.\r\n * This is the oneservice url used for personalized content.\r\n * Possible values are enumerated on OneServiceConfig.ts\r\n *\r\n * @type {URL}\r\n * @memberof AppEnvironment\r\n */\r\n public get ServiceUrlBase(): URL {\r\n const url = new URL(\"\", this.serviceUrlBase);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.service\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.service\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.service\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Base URL for the feed service\r\n */\r\n public get FeedServiceUrlBase(): URL {\r\n if (!this.feedServiceUrlBase) {\r\n return null;\r\n }\r\n\r\n const url = new URL(\"\", this.feedServiceUrlBase);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.service\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.service\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.service\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Base URL for the enterprise service\r\n */\r\n public get EnterpriseServiceUrlBase(): URL {\r\n const url = new URL(\"\", EnterpriseOneServiceApi);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.service\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.service\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.service\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n public get IsFrePage(): boolean { return this.isFrePage; }\r\n\r\n public get RootTelemetryId(): number { return this.rootTelemetryId; }\r\n public get TrackInfo(): ITrackInfo { return this.trackInfo; }\r\n public get UserId(): string { return this.userId; }\r\n\r\n /**\r\n * This is the switch to turn on/off indexed db operation used as a caching layer in config resolver (Resolver.ts)\r\n */\r\n public get DisableCachingConfigs(): boolean { return this.disableCachingConfigs; }\r\n\r\n /**\r\n * This is the switch to turn on/off config service operation in Resolver.ts\r\n */\r\n public get EnableConfigService(): boolean { return this.enableConfigService; }\r\n\r\n /**\r\n * This indicates whether we will use CMS PPE configs or not\r\n */\r\n public get EnableCMSPPEConfigs(): boolean { return headData && headData.EnableCMSPPEConfigs; }\r\n\r\n /**\r\n * Check whether multi config retrieval is supported.\r\n */\r\n public get IsMultiConfigRetrievalEnabled(): boolean { return this.isMultiConfigRetrievalEnabled; }\r\n\r\n /**\r\n * This is the switch to turn on/off content preview caching in core/cache/ContentPreview.ts\r\n */\r\n public get DisableContentPreviewCache(): boolean {\r\n return this.disableContentPreviewCache;\r\n }\r\n\r\n /**\r\n * Returns a flag indicating whether the one service feed fetch call should send activityID\r\n * in the request header or as a QSP in the URL (current behavior is via QSP).\r\n */\r\n public get SendFeedCallActivityIdInHeader(): boolean {\r\n return this.sendFeedCallActivityIdInHeader;\r\n }\r\n\r\n /**\r\n * This is the switch to turn off hydrating content preview cache from IndexedDB.\r\n * Default is false\r\n */\r\n public get DisableContentCacheIDBRead(): boolean {\r\n const queryParamOverride = UrlUtility.getQueryParameterByName(\"disableContentCacheIDBRead\", getLocationSearch());\r\n\r\n if (queryParamOverride) {\r\n return queryParamOverride === \"true\";\r\n }\r\n\r\n return this.disableContentCacheIDBRead;\r\n }\r\n\r\n /**\r\n * This is the switch to turn on/off content list caching in core/cache/ContentPreview.ts\r\n */\r\n public get DisableContentListCache(): boolean {\r\n return this.disableContentListCache;\r\n }\r\n\r\n /**\r\n * This is the switch to turn off hydrating content list cache from IndexedDB.\r\n * Default is false\r\n */\r\n public get DisableContentListCacheIDBRead(): boolean {\r\n const queryParamOverride = UrlUtility.getQueryParameterByName(\"disableContentListCacheIDBRead\", getLocationSearch());\r\n\r\n if (queryParamOverride) {\r\n return queryParamOverride === \"true\";\r\n }\r\n\r\n return this.disableContentListCacheIDBRead;\r\n }\r\n\r\n /**\r\n * Get base url of Config Service.\r\n */\r\n public get ConfigServiceBaseUrl(): URL { return this.configServiceBaseUrl; }\r\n\r\n /**\r\n * This returns feature flags client settings stamped by PCS.\r\n */\r\n public get FeatureFlags(): any { return this.featureFlags; }\r\n\r\n /**\r\n * This returns config root url\r\n */\r\n public get ConfigRootUrl(): URL {\r\n if (!this.configRootUrl) {\r\n return null;\r\n }\r\n\r\n const url = new URL(\"\", this.configRootUrl);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.config\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.config\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.config\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Returns cache busting identifier from PCS.\r\n */\r\n public get CacheBustingIdentifier(): string { return this.cacheBustingIdentifier; }\r\n\r\n /**\r\n * Returns the country code. For example \"br\"\r\n */\r\n public get CountryCode(): string { return this.countryCode; }\r\n\r\n //// FIXME: hyphen has a second 'h'\r\n //// Bug 24228723: [Peregrine] ActivityIdLowerCaseNoHypens misspells \"Hyphen\"\r\n /**\r\n * Gets the Activity ID in lower case and without any hyphens. This helper method should be where parity with Prime is required.\r\n * Use telemetry's requestId instead for associating with current page client navigation\r\n */\r\n public get ActivityIdLowerCaseNoHypens(): string { return ((headData && headData.ClientSettings && headData.ClientSettings.aid) || \"\").toLowerCase(); }\r\n\r\n /**\r\n * Returns the latitude. For example \"42.361145\"\r\n */\r\n public get Latitude(): string { return this.latitude; }\r\n\r\n /**\r\n * Returns the longitude. For example \"-71.057083\"\r\n */\r\n public get Longitude(): string { return this.longitude; }\r\n\r\n public set ActivityId(value: string) { this.activityId = value; }\r\n public set CountryCode(value: string) { this.countryCode = value; }\r\n public set CurrentMarket(value: Market) { this.currentMarket = value; }\r\n public set CurrentRequestTargetScope(value: PageRequestTargetScope) { this.currentRequestTargetScope = value; }\r\n public set Environment(value: Environment) { this.environment = value; }\r\n public set HostPage(value: IHostPage) { this.hostPage = value; }\r\n public set RootTelemetryId(value: number) { this.rootTelemetryId = value; }\r\n public set TrackInfo(value: ITrackInfo) { this.trackInfo = value; }\r\n public set UserId(value: string) { this.userId = value; }\r\n public set AuthCookieName(value: AuthCookieName) { this.authCookieName = value; }\r\n public set AccountType(value: AccountType) { this.accountType = value; }\r\n public set AadDataPromise(value: Promise) { this.aadDataPromise = value; }\r\n\r\n /**\r\n * Initialize the AppEnvironment singleton instance.\r\n * @param _serviceUrl Optional URL to initialize the ServiceUrlBase.\r\n * @param _configServiceUrlBase ConfigServiceUrlBase provided during server side rendering this is the ServiceFabric ClusterRegionUrl.\r\n */\r\n private constructor(_serviceUrl: URL, _configServiceUrlBase: string) {\r\n this.initializeAppEnvironment(_serviceUrl, _configServiceUrlBase);\r\n }\r\n\r\n /**\r\n * Returns singleton class instance.\r\n * @returns {AppEnvironment}\r\n */\r\n public static getInstance(serviceUrl: URL = null, configServiceUrlBase: string = null): AppEnvironment {\r\n return AppEnvironment._instance || (AppEnvironment._instance = new AppEnvironment(serviceUrl, configServiceUrlBase));\r\n }\r\n\r\n /**\r\n * Reinitialize the singleton class instance.\r\n * @param serviceUrl OneService service url to initialize to.\r\n * @param configServiceUrlBase Config service url to initialize to.\r\n * @returns {AppEnvironment}\r\n */\r\n public static resetInstance(serviceUrl: URL = null, configServiceUrlBase: string = null): AppEnvironment {\r\n AppEnvironment._instance = new AppEnvironment(serviceUrl, configServiceUrlBase);\r\n appEnvironment = AppEnvironment._instance;\r\n return AppEnvironment._instance;\r\n }\r\n\r\n /**\r\n * Initializes App environment. This is normally only called by the constructor (singleton pattern)\r\n * It is made public so that it can be also called by test code.\r\n */\r\n public initializeAppEnvironment(_serviceUrl?: URL, configServiceUrlBase?: string): void {\r\n\r\n let environmentFromHeadData: Environment = null;\r\n const clientSettings = headData && headData.ClientSettings;\r\n\r\n if (clientSettings) {\r\n this.activityId = this.tryReformatGuid(clientSettings.aid);\r\n this.buildVersion = clientSettings.v;\r\n this.currentMarket = (headData.Locale || clientSettings.apps_locale) as Market;\r\n this.countryCode = clientSettings.geo_country;\r\n this.latitude = clientSettings.geo_lat;\r\n this.longitude = clientSettings.geo_long;\r\n this.configRootUrl = clientSettings.configRootUrl ? new URL(\"\", clientSettings.configRootUrl) : null;\r\n environmentFromHeadData = getEnvironmentFromString(clientSettings.env);\r\n\r\n this.setAccountType();\r\n this.appType = clientSettings.apptype || \"\";\r\n this.authCookieName = this.getAuthCookieName();\r\n\r\n this.featureFlags = clientSettings.featureFlags;\r\n\r\n this.disableCachingConfigs =\r\n this.featureFlags && this.featureFlags.disableCachingConfigs\r\n ? this.featureFlags.disableCachingConfigs === \"true\"\r\n : false;\r\n\r\n this.enableConfigService =\r\n this.featureFlags && this.featureFlags.enableConfigService\r\n ? this.featureFlags.enableConfigService === \"true\"\r\n : true;\r\n\r\n this.disableContentPreviewCache =\r\n this.featureFlags && this.featureFlags.disableContentPreviewCache\r\n ? this.featureFlags.disableContentPreviewCache === \"true\"\r\n : false;\r\n\r\n this.disableContentCacheIDBRead = this.featureFlags && this.featureFlags.disableContentCacheIDBRead\r\n ? this.featureFlags.disableContentCacheIDBRead === \"true\"\r\n : false;\r\n\r\n this.disableContentListCache =\r\n this.featureFlags && this.featureFlags.disableContentListCache\r\n ? this.featureFlags.disableContentListCache === \"true\"\r\n : false;\r\n\r\n this.disableContentListCacheIDBRead = this.featureFlags && this.featureFlags.disableContentListCacheIDBRead\r\n ? this.featureFlags.disableContentListCacheIDBRead === \"true\"\r\n : false;\r\n\r\n // Hardcode flight details for experimentation sake\r\n // Use feature flag as a switch to disable the feature, since we may not be able to stop the flight itself (will need a PCS deployment)\r\n this.sendFeedCallActivityIdInHeader = this.featureFlags && this.featureFlags.disableActivityIdInHeader && this.featureFlags.disableActivityIdInHeader === \"true\"\r\n ? false\r\n : headData.CurrentFlights && (headData.CurrentFlights.indexOf(\"prg-edge-t4\") !== -1);\r\n\r\n this.cacheBustingIdentifier = clientSettings.cbid;\r\n }\r\n\r\n const rootElement = canUseDOM() ? getDocumentElementById(rootElementId) : null;\r\n const locationHref = getLocationHref();\r\n const locationOrigin = getLocationOrigin();\r\n\r\n // env is read from\r\n // - query string param env, if present\r\n // - headData.ClientSettings.env\r\n // - defaults to prod otherwise\r\n const envQSOverwrite = getEnvironmentFromString(UrlUtility.getQueryParameterByName(\"env\", locationHref));\r\n this.environment =\r\n envQSOverwrite\r\n || environmentFromHeadData\r\n || Environment.prod;\r\n\r\n this.serviceUrlBase = _serviceUrl || (rootElement && rootElement.getAttribute(serviceUrl) && new URL(\"\", rootElement.getAttribute(serviceUrl))) || new URL(\"\", \"https://assets.msn.com/service/\");\r\n\r\n // If PCS sent the feed base domain, use it for the feed URL base\r\n // or else default to host page rooted URL.\r\n this.feedServiceUrlBase = new URL(\"./service/\", clientSettings && clientSettings.feedBaseDomain ? clientSettings.feedBaseDomain : locationOrigin);\r\n\r\n // Get the hostPage from the request url\r\n this.hostPage = HostPage.getHostPageFromUrl(locationHref);\r\n\r\n // Determine if the page is running as an FRE page\r\n this.isFrePage = (UrlUtility.getQueryParameterByName(\"fre\", locationHref) === \"1\");\r\n\r\n // Get the UserMuid from the muid cookie\r\n const muidCookie: string = getMuidCookie();\r\n if (isString(muidCookie)) {\r\n logger.log(\"u: m-\" + muidCookie);\r\n this.userId = \"m-\" + muidCookie;\r\n }\r\n\r\n // Get attributes from the head (full page Peregrine experience) or from the spa \"root\" element (PrimeHybrid case)\r\n // TODO, determine where in the element attributes these values should be set\r\n this.rootTelemetryId = rootElement ? Number(rootElement.getAttribute(telemetryId)) : 0;\r\n const trackPageProd = rootElement && rootElement.getAttribute(trackPageProduct);\r\n const trackPageTypeVal = rootElement && rootElement.getAttribute(trackPageType);\r\n this.trackInfo = { sitePage: { page_product: trackPageProd, page_type: trackPageTypeVal } };\r\n\r\n this.contentServiceUrlBase = new URL(\"\", \"https://assets.msn.com/content/\");\r\n\r\n this.currentContentLinkHost = this.createContentLinkHost();\r\n\r\n this.setTargetScope();\r\n\r\n this.isMultiConfigRetrievalEnabled = this.useMultiConfigsRetrieval();\r\n\r\n const baseUrl = this.getConfigServiceBaseUrl(this.isMultiConfigRetrievalEnabled, configServiceUrlBase);\r\n this.configServiceBaseUrl = baseUrl ? new URL(\"\", baseUrl) : null;\r\n\r\n this.environmentConfigUrl = new URL(\"\", \"https://assets.msn.com/config/v1/\");\r\n\r\n this.isDebug = ((UrlUtility.getQueryParameterByName(\"debug\", locationHref) || \"\").toLowerCase() in { \"1\": 1, \"true\": 1 })\r\n || (UrlUtility.getQueryParameterByName(\"item\", locationHref) || \"\").toLowerCase().indexOf(\"/debug\") > 0;\r\n\r\n this.showMnsCreatorDashboard = UrlUtility.getQueryParameterByName(\"mnsDash\", locationHref) != null;\r\n }\r\n\r\n /**\r\n * Get config service base url\r\n * @param isMultiConfigRetrievalEnabled if multiple config retrieval is supported.\r\n * @param configServiceUrlBase externally configured config service url (from SSR environment)\r\n * @returns {string} - config service base url.\r\n */\r\n private getConfigServiceBaseUrl(isMultiConfigRetrievalEnabled: boolean = true, configServiceUrlBase?: string): string {\r\n const relativePath = `/resolver/api/resolve/${isMultiConfigRetrievalEnabled ? `v2/` : ``}configindex/`;\r\n\r\n if (configServiceUrlBase) {\r\n // When doing server side rendering the ClusterRegionUrl env variable should be set, use this to avoid calls to CRS going outside of the cluster.\r\n return configServiceUrlBase + relativePath;\r\n } else if (process.env.WEBPACK_DEV_SERVER || this.environment === Environment.int) {\r\n // int and localhost to use int.msn.com for config service.\r\n return \"https://int.msn.com\" + relativePath;\r\n } else {\r\n return getLocationOrigin() ? getLocationOrigin() + relativePath : null;\r\n }\r\n }\r\n\r\n /**\r\n * Function checks if ConfigService should return multiple configs\r\n * @returns true if supported else false.\r\n */\r\n private useMultiConfigsRetrieval(): boolean {\r\n const urlQuery = getLocationSearch();\r\n if (urlQuery) {\r\n const param = UrlUtility.getQueryParameterByName(\"isMultiConfigRetrievalEnabled\", urlQuery);\r\n if (param) {\r\n return param.toLocaleLowerCase() === \"true\";\r\n }\r\n }\r\n\r\n // PCS flag to turn on/off multi config retrieval.\r\n if (this.featureFlags\r\n && this.featureFlags.isMultiConfigRetrievalEnabled) {\r\n return this.featureFlags.isMultiConfigRetrievalEnabled === \"true\";\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the auth cookie name based on the app type of the page\r\n * @returns {AuthCookieName} - the name of the auth cookie to use\r\n */\r\n private getAuthCookieName(): AuthCookieName {\r\n const clientSettings = headData && headData.ClientSettings;\r\n const appType: AppType = (clientSettings.apptype || \"\") as AppType;\r\n let authCookieName: AuthCookieName;\r\n switch (appType) {\r\n case AppType.Hub:\r\n case AppType.MicrosoftNews:\r\n case AppType.Views:\r\n authCookieName = AuthCookieName.Anon;\r\n break;\r\n case AppType.Edge:\r\n case AppType.EdgeChromium:\r\n case AppType.MMX:\r\n case AppType.Office:\r\n default:\r\n authCookieName = AuthCookieName.AppAnon;\r\n }\r\n\r\n return authCookieName;\r\n }\r\n\r\n /**\r\n * Sets the AccountType for the current user\r\n */\r\n private setAccountType(): void {\r\n // TODO: Currently signed in status is not available on the server side\r\n // Tracking work item: https://dev.azure.com/microsoft/OS/_workitems/edit/24489062\r\n if (!canUseDOM() || !window.chrome || !window.chrome.authPrivate || !window.chrome.authPrivate.getPrimaryAccountInfo) {\r\n this.AccountType = AccountType.SignedOut;\r\n return;\r\n }\r\n window.chrome.authPrivate.getPrimaryAccountInfo((accountInfo) => {\r\n if (!accountInfo) {\r\n this.AccountType = AccountType.SignedOut;\r\n return;\r\n }\r\n\r\n const accountType: string = accountInfo.account_type;\r\n if (accountType === \"AAD\") {\r\n this.AccountType = AccountType.AAD;\r\n this.setAadDataPromise(accountInfo);\r\n return;\r\n }\r\n\r\n if (accountType === \"MSA\") {\r\n this.AccountType = AccountType.MSA;\r\n return;\r\n }\r\n\r\n this.AccountType = AccountType.SignedOut;\r\n });\r\n }\r\n\r\n /**\r\n * Sets the AadDataPromise for the current user if an aad account\r\n */\r\n private setAadDataPromise(accountInfo: any): void {\r\n this.AadDataPromise = new Promise((resolve) => {\r\n const tokenAcquireParameters = {\r\n account_id: accountInfo.account_id,\r\n account_type: accountInfo.account_type,\r\n client_id: clientId,\r\n scope_or_resource: oneServiceScope\r\n };\r\n\r\n window.chrome.authPrivate.acquireAccessTokenSilently(tokenAcquireParameters, (acquireResult) => {\r\n resolve({\r\n token: acquireResult.access_token,\r\n errorInfo: acquireResult.error_info,\r\n isSuccess: acquireResult.is_success,\r\n isValid: acquireResult.is_token_valid\r\n });\r\n });\r\n })\r\n }\r\n\r\n /**\r\n * Determines the content link host to use.\r\n * @returns The content link host.\r\n */\r\n private createContentLinkHost(): string {\r\n const topLevelDomain = this.currentMarket === Market.ZHCN ? \"cn\" : \"com\";\r\n return \"www.msn.\" + topLevelDomain;\r\n }\r\n\r\n /**\r\n * Reformats the given guid without dashes to a guid string with dashes.\r\n * @param {string} guid - The guid without dashes.\r\n * @returns {string} - The reformatted GUI with dashes.\r\n */\r\n private tryReformatGuid(guid: string): string {\r\n if (guid && guid.length === 32) {\r\n // use a regex to extract the specific substrings to reformat the guid\r\n const matches = guid.match(/(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})/i);\r\n if (matches) {\r\n // join all the captured groups from 1-5 to format the final guid string\r\n guid = matches.slice(1).join(\"-\");\r\n }\r\n }\r\n\r\n return guid;\r\n }\r\n\r\n /**\r\n * Sets target scope for current request.\r\n */\r\n private setTargetScope(): void {\r\n if (!headData || !headData.ClientSettings) {\r\n return;\r\n }\r\n\r\n // If user is signed in and \"child\" Cookie exists - set Kids audience mode, otherwise use PCS provided Audience mode.\r\n const audienceMode = getCookie(appAnonCookieExistsCookieName) && getCookie(childCookieName) ? AudienceModeType.Kids : headData.ClientSettings.audienceMode;\r\n\r\n const { browser, deviceFormFactor, domain, locale, os, pagetype } = headData.ClientSettings;\r\n\r\n this.currentRequestTargetScope = {\r\n audienceMode: audienceMode,\r\n browser: browser,\r\n deviceFormFactor: deviceFormFactor,\r\n domain: domain,\r\n locale: locale,\r\n os: os,\r\n platform: PlatformType.Web,\r\n pageType: pagetype\r\n };\r\n\r\n // if locale is not defined in client settings, try reading it from headData for backward compatibility\r\n if (!this.currentRequestTargetScope.locale && Utility.stringHasData(headData.Locale)) {\r\n const locale = headData.Locale.split(\"-\");\r\n if (locale.length > 1) {\r\n this.currentRequestTargetScope.locale = {\r\n language: locale[0],\r\n // Some spartan locale are in format \"ha-latn-ng\". Here the market is \"ng\" and language is \"ha\"\r\n market: locale[locale.length - 1]\r\n };\r\n }\r\n }\r\n\r\n if (Utility.stringHasData(headData.CurrentFlights)) {\r\n this.currentRequestTargetScope.pageExperiments = headData.CurrentFlights.split(\",\");\r\n }\r\n }\r\n}\r\n\r\nexport const getAppEnvironment = AppEnvironment.getInstance;\r\n\r\n// appEnvironment can be reinitialized for server side rendering through resetAppEnvironment.\r\nexport let appEnvironment = AppEnvironment.getInstance();\r\n\r\nexport const resetAppEnvironment = AppEnvironment.resetInstance;","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Attempts to parse a given string to a JSON object\r\n * @param {string} jsonString - The string to parse.\r\n * @returns {any} - the parsed object if successful, or null otherwise.\r\n */\r\nexport function tryParseJson(jsonString: string): any {\r\n try {\r\n return JSON.parse(jsonString);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** Attempts to parse the given value as a integer and if failed will return the defaultValue.\r\n * @param {string} value - The value to parse.\r\n * @param {number} defaultValue - The default value to return if parsing fails\r\n * @returns {number} the parsed value if it was a valid number or otherwise the default value if specified.\r\n */\r\nexport function tryParseInt(value: string, defaultValue: number): number {\r\n let n = parseInt(value);\r\n return isNaN(n) ? defaultValue : n;\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { AppError, AppErrorPropertyBag, Severity } from \"./AppErrorTracker\";\r\n\r\n/**\r\n * This file contains the list of errors to log to the server for each feature.\r\n * We are centralizing errors here to make sure we do not have any dupes\\conflicts.\r\n * The idea is that each feature would have their own range of values.\r\n *\r\n * IMPORTANT: Please do not add strings to this file. Please map messages to send in your\r\n * code.\r\n */\r\n\r\n/**\r\n * All app errors are set to create IcM ticket by default unless specified in individual error code otherwise.\r\n */\r\nconst severity = Severity.Alert;\r\n\r\n// Webpack defines the BUILD_NUMBER of client code build number.\r\ndeclare var BUILD_NUMBER: string;\r\n\r\n/**\r\n * Get build number from web pack. If not present, return empty\r\n */\r\nconst pb: AppErrorPropertyBag = {\r\n build: typeof BUILD_NUMBER === \"undefined\"\r\n ? \"\"\r\n : BUILD_NUMBER\r\n};\r\n\r\n/** Represents a ServiceUI related error */\r\nexport const ServiceUiError: AppError = {\r\n id: 5100,\r\n source: \"ServiceUiComm.ts\",\r\n severity,\r\n pb\r\n};\r\n\r\n/** Represents a Top Sites related error */\r\nexport const TopSitesError: AppError = {\r\n id: 8010,\r\n source: \"TopSites.tsx\",\r\n severity,\r\n pb\r\n};\r\n\r\n/** Represents a Top Sites error when there are zero rendered top sites */\r\nexport const ZeroTopSitesError: AppError = {\r\n id: 8011,\r\n source: \"TopSites.connector.ts\",\r\n severity,\r\n pb\r\n};\r\n\r\n/** Curated sites list is empty */\r\nexport const CuratedSitesEmpty: AppError = {\r\n id: 8012,\r\n source: \"TopSites.connector.ts\",\r\n severity,\r\n pb\r\n};\r\n\r\nconst TopSitesEdgeConnectorFileName: string = \"TopSitesEdge.connector.tsx\";\r\nconst TopSitesEdgeStorageFileName: string = \"TopSitesStorage.ts\";\r\n\r\nexport const TopSitesEdgeAppErrors = {\r\n ZeroTopSitesError: {\r\n id: 8013,\r\n source: TopSitesEdgeConnectorFileName,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n CuratedSitesEmpty: {\r\n id: 8014,\r\n source: TopSitesEdgeStorageFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n ComponentMountFailed: {\r\n id: 8015,\r\n source: TopSitesEdgeConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n ErrorFetchingRichTopSitesDataCollectionFromCms: {\r\n id: 8016,\r\n source: TopSitesEdgeStorageFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst TopSitesEdgeNextConnectorFileName: string = \"TopSitesEdgeNext.connector.tsx\";\r\n\r\nexport const TopSitesEdgeNextAppErrors = {\r\n\r\n /** The React component failed to mount */\r\n ComponentMountFailed: {\r\n id: 8020,\r\n source: TopSitesEdgeNextConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Represents a Top Sites error when there are zero rendered top sites */\r\n ZeroTopSitesError: {\r\n id: 8021,\r\n source: TopSitesEdgeNextConnectorFileName,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nexport const TopSiteDialogAppErrors = {\r\n /** The React component failed to mount */\r\n TopSitesDialogFailedToMount: {\r\n id: 8025,\r\n source: \"TopSitesDialog.tsx\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst OneServiceCardProviderFileName: string = \"OneServiceCardProvider.ts\";\r\n\r\nexport const OneServiceCardProviderAppErrors = {\r\n OneServiceResponseWasNullOrErroneous: {\r\n id: 8031,\r\n source: OneServiceCardProviderFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n ErrorFetchingOneServiceResponse: {\r\n id: 8032,\r\n source: OneServiceCardProviderFileName,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n\r\n InvalidJsonInOneServiceResponse: {\r\n id: 8033,\r\n source: OneServiceCardProviderFileName,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n\r\n InvalidFeedListInOneServiceResponse: {\r\n id: 8034,\r\n source: OneServiceCardProviderFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n RiverConfigurationIssue: {\r\n id: 8035,\r\n source: OneServiceCardProviderFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load views river content based on current vertical/category. */\r\n QueryInterestContentFetchError: {\r\n id: 8036,\r\n source: OneServiceCardProviderFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n StaticContentLoaded: {\r\n id: 8037,\r\n source: OneServiceCardProviderFileName,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst OneServiceDailyBriefApi: string = \"dailyBriefServiceClient.ts\";\r\n\r\nexport const DailyBriefServiceClientAppErrors = {\r\n OneServiceResponseWasNullOrErroneous: {\r\n id: 8038,\r\n source: OneServiceDailyBriefApi,\r\n severity,\r\n pb\r\n },\r\n\r\n OneServiceArticleListWasNullOrErroneous: {\r\n id: 8039,\r\n source: OneServiceDailyBriefApi,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ContentPreviewSourceFile = \"ContentPreview.connector.ts\";\r\nconst ContentPreviewDataSourceFile = \"ContentPreviewData.ts\";\r\nconst ExternalContentMapperHelperFile = \"ExternalContentMapperHelper.ts\";\r\n\r\nexport const ContentPreviewAppErrors = {\r\n\r\n ErrorWhileFetchingContentPreviewContent: {\r\n id: 8041,\r\n source: ContentPreviewDataSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n InvalidResponseFromContentPreviewFetch: {\r\n id: 8042,\r\n source: ContentPreviewDataSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n InvalidResponseFromContentPreviewResponseJson: {\r\n id: 8043,\r\n source: ContentPreviewDataSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n ErrorWhileInitializingAsyncContentPreviewContent: {\r\n id: 8044,\r\n source: ContentPreviewSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n InvalidOrMissingContentId: {\r\n id: 8045,\r\n source: ContentPreviewDataSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n MissingDataForExternalContent: {\r\n id: 8046,\r\n source: ExternalContentMapperHelperFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst RiverSourceFile = \"River.connector.ts\";\r\n\r\nexport const RiverAppErrors = {\r\n UnknownMetadataReceivedFromRiverCardProvider: {\r\n id: 8051,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n RiverContentProviderFetchException: {\r\n id: 8052,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n UnableToSelectSectionTemplateForGivenChildExperiences: {\r\n id: 8053,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n InvalidConfig: {\r\n id: 8054,\r\n source: RiverSourceFile,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n\r\n ChildLoadError: {\r\n id: 8056,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n InitialDataLoadError: {\r\n id: 8057,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Warning for when the ordinal children we get from config contains a duplicate instance id. */\r\n DuplicateInstanceIdWarning: {\r\n id: 8058,\r\n source: RiverSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst UserInitiatedPageRefreshSourceFile = \"UserInitiatedPageRefresh.ts\";\r\nexport const UserInitiatedPageRefreshErrors = {\r\n Default: {\r\n id: 8060,\r\n source: UserInitiatedPageRefreshSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst PivotContentSourceFile = \"PivotContent.connector.ts\";\r\nexport const PivotContentErrors = {\r\n LoadFailure: {\r\n id: 8070,\r\n source: PivotContentSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst PivotsNavSourceFile = \"PivotsNav.connector.ts\";\r\nexport const PivotsNavErrors = {\r\n TopicDataConnectorUnavailable: {\r\n id: 8075,\r\n source: PivotsNavSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n NavigationDataConnectorUnavailable: {\r\n id: 8076,\r\n source: PivotsNavSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n DynamicPivotsHelperLoaderFailed: {\r\n id: 8077,\r\n source: PivotsNavSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n LayoutPreferenceDataConnectorUnavailable: {\r\n id: 8078,\r\n source: PivotsNavSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Smart list is empty */\r\nexport const SmartListEmpty: AppError = {\r\n id: 8080,\r\n source: \"SmartList.connector.ts\",\r\n severity,\r\n pb\r\n};\r\n\r\n/** Represents BingWebSSO related App errors */\r\nconst BingWebSSOSourceFile = \"BingWebSSO.tsx\";\r\nexport const BingWebSSOAppErrors = {\r\n /** Failed to render bing websso iframe */\r\n BingWebSSORenderFailed: {\r\n id: 8090,\r\n source: BingWebSSOSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** User signed-in to MSA on page but bing SSO returned authentication failed response */\r\n BingWebSSOSignInFailed: {\r\n id: 8091,\r\n source: BingWebSSOSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Bing SSO process did not complete withing required time */\r\n BingWebSSOTimeout: {\r\n id: 8092,\r\n source: BingWebSSOSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst WeatherDataConnectorSourceFile = \"WeatherData.connector.ts\";\r\nexport const WeatherDataAppErrors = {\r\n /** Failed to fetch weather summary */\r\n WeatherSummaryFetchError: {\r\n id: 8100,\r\n source: WeatherDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** No valid Location set from User */\r\n WeatherLocationEmpty: {\r\n id: 8101,\r\n source: WeatherDataConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Not able to read from PDP */\r\n WeatherPDPReadFailed: {\r\n id: 8102,\r\n source: WeatherDataConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Not able to write home location to PDP */\r\n WeatherPDPHomeLocationWriteFailed: {\r\n id: 8103,\r\n source: WeatherDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Not able to write display Unit to PDP */\r\n WeatherPDPDisplayUnitWriteFailed: {\r\n id: 8104,\r\n source: WeatherDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Not able to localize Location */\r\n WeatherLocalizeLocationFailed: {\r\n id: 8105,\r\n source: WeatherDataConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst WeatherCardConnectorSourceFile = \"WeatherCard.connector.ts\";\r\nexport const WeatherCardAppErrors = {\r\n /** Failed to fetch local news */\r\n WeatherLocalNewsFetchError: {\r\n id: 8106,\r\n source: WeatherCardConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Failed to fetch autosuggest for locations */\r\n WeatherAutoSuggestFetchError: {\r\n id: 8107,\r\n source: WeatherCardConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** No valid Location set from User */\r\n WeatherLocationEmpty: {\r\n id: 8108,\r\n source: WeatherCardConnectorSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst SportsPdpServiceClientSourceFile = \"SportsPdpServiceClient.ts\";\r\nexport const SportsCardError = {\r\n /** Failed to fetch league sports pdp */\r\n SportsLeaguePdpFetchError: {\r\n id: 8110,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch league sports pdp */\r\n SportsLeaguePdpInvalidResponse: {\r\n id: 8111,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch players sports pdp */\r\n SportsPlayersPdpFetchError: {\r\n id: 8112,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch players sports pdp */\r\n SportsPlayersPdpInvalidResponse: {\r\n id: 8113,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch teams sports pdp */\r\n SportsTeamsPdpFetchError: {\r\n id: 8114,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch teams sports pdp */\r\n SportsTeamsPdpInvalidResponse: {\r\n id: 8115,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get sports card config */\r\n SportsCardConfigFetchError: {\r\n id: 8116,\r\n source: \"SportsCardConfigReader.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get Team Data */\r\n SportsCardGetFavoriteTeamDataError: {\r\n id: 8117,\r\n source: \"SportsCard.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get Team Data */\r\n SportsCardGetPlayerBioError: {\r\n id: 8118,\r\n source: \"SportsCard.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetLeaguesGamesArrayError: {\r\n id: 8119,\r\n source: \"SportsCard.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetPdpDataFailure: {\r\n id: 8120,\r\n source: \"SportsCard.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetLeagueSeasonYearDataFailure: {\r\n id: 8121,\r\n source: \"SportsCardServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetLocalizedTeamNameDataFailure: {\r\n id: 8122,\r\n source: \"SportsCardServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetTeamDataFailure: {\r\n id: 8123,\r\n source: \"SportsCardServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetLeagueDataFailure: {\r\n id: 8124,\r\n source: \"SportsCardServiceClient.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MoneyCardConnectorFile = \"MoneyCard.connector.ts\";\r\nexport const MoneyCardError = {\r\n /** Failed to get quote summary for user */\r\n MoneyQuoteSummaryGetError: {\r\n id: 8130,\r\n source: MoneyCardConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get quote summaries */\r\n MoneyQuoteSummariesGetError: {\r\n id: 8131,\r\n source: MoneyCardConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get pdp data */\r\n MoneyPdpDataGetErrorFromService: {\r\n id: 8132,\r\n source: \"MoneyPdpServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get pdp data because of invalid response */\r\n MoneyPdpInvalidResponseFromService: {\r\n id: 8133,\r\n source: \"MoneyPdpServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get quote summary response for user from service client */\r\n MoneyQuoteSummaryGetErrorFromService: {\r\n id: 8134,\r\n source: \"MoneyQuotesServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get quote summary response for user from service client because of invalid response */\r\n MoneyQuoteSummaryInvalidResponseFromService: {\r\n id: 8135,\r\n source: \"MoneyQuotesServiceClient.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const TrendingNewsErrors = {\r\n /** Failed to fetch the trending news stories */\r\n DataFetchError: {\r\n id: 8140,\r\n source: \"TrendingNews.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Failed to fetch the backup data for trending news stories */\r\n BackupDataFetchError: {\r\n id: 8141,\r\n source: \"TrendingNews.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ComplexContentPreviewSourceFile = \"ComplexContentPreview.connector.ts\";\r\nexport const ComplexContentPreviewErrors = {\r\n InitError: {\r\n id: 8150,\r\n source: ComplexContentPreviewSourceFile,\r\n severity,\r\n pb\r\n },\r\n LoadError: {\r\n id: 8151,\r\n source: ComplexContentPreviewSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n ContentError: {\r\n id: 8152,\r\n source: ComplexContentPreviewSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const GridSectionAppErrors = {\r\n /** Unable to generate river section cards */\r\n GridSectionCardGenerationError: {\r\n id: 8160,\r\n source: \"GridSection.tsx\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MmxEntryPointFileName: string = \"MMXPage.connector.ts\";\r\n\r\nexport const MmxEntryPointAppErrors = {\r\n /**\r\n * MMX river is not able to load Error Page.\r\n */\r\n MmxErrorPage: {\r\n id: 8170,\r\n source: MmxEntryPointFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Error fetching the APP_ANON cookie on MMX page load\r\n */\r\n ErrorFetchingAppAnonCookie: {\r\n id: 8171,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst irisImageHotspotsFile = \"ImageHotspots.manager.ts\";\r\nexport const BackgroundImageAppErrors = {\r\n /** The Bing Image of the Day failed to load properly */\r\n BingIOTDFailedToLoad: {\r\n id: 8180,\r\n source: \"BingImageOfTheDayProvider.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Error when Iris fails to return Hotspots Data to the client. */\r\n FailedHotspotsDataDelivery: {\r\n id: 8181,\r\n source: irisImageHotspotsFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Hotspots data that was returned failed to validate. */\r\n IncompleteHotspotsContract: {\r\n id: 8182,\r\n source: irisImageHotspotsFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Hotspots data found for the off page navigation failed inspection. */\r\n InvalidOffPageNavCTA: {\r\n id: 8183,\r\n source: irisImageHotspotsFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const SettingsDialogAppErrors = {\r\n /** Failed to get the saved layout preferences */\r\n ReadPreferencesFailed: {\r\n id: 8190,\r\n source: \"SettingsDialogEdgeNext.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch the ConfigData object from the client API */\r\n FetchNtpConfigDataFailed: {\r\n id: 8191,\r\n source: \"SettingsDialogEdgeNextBase.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n ChromiumClientEmbededsearchAPIError: {\r\n id: 8192,\r\n source: \"SettingsDialogEdgeNext.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const EdgePageSettingsAppErrors = {\r\n ServiceUiError: {\r\n id: 8192,\r\n source: \"EdgeSettingsProvider.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MsnSettingMenuConnectorFileName = \"MsnSettingMenuConnector.connector.ts\";\r\n\r\nexport const MsnSettingsMenuAppErrors = {\r\n /** Failed to get feedback dialog connector */\r\n FailedToGetFeedbackDialogConnector: {\r\n id: 8193,\r\n source: MsnSettingMenuConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** Failed to get feedback data connector */\r\n FailedToGetFeedbackDataConnector: {\r\n id: 8194,\r\n source: MsnSettingMenuConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** The Msn settings menu failed to load valid config settings */\r\n MsnSettingsMenuFailedToFetchConfig: {\r\n id: 8195,\r\n source: MsnSettingMenuConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ShowFeedConnectorFileName = \"ShowFeed.connector.ts\";\r\n\r\nexport const ShowFeedAppErrors = {\r\n MissingPageSettings: {\r\n id: 8199,\r\n source: ShowFeedConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n ExpectedDataMissing: {\r\n id: 8198,\r\n source: ShowFeedConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst InfopaneSourceFile = \"Infopane.connector.ts\";\r\nexport const InfopaneErrors = {\r\n InitializeError: {\r\n source: InfopaneSourceFile,\r\n id: 8201,\r\n severity,\r\n pb\r\n },\r\n InvalidConfig: {\r\n source: InfopaneSourceFile,\r\n id: 8202,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const FeedbackDialogAppErrors = {\r\n /** Failed to get feedback data connector */\r\n FailedToGetFeedbackDataConnector: {\r\n id: 8211,\r\n source: \"FeedbackDialog.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const FeedbackLinkAppErrors = {\r\n /** The Feedback link failed to load valid config settings */\r\n FeedbackLinkFailedToFetchConfig: {\r\n id: 8210,\r\n source: \"FeedbackLink.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Failed to get feedback dialog connector */\r\n FailedToGetFeedbackDialogConnector: {\r\n id: 8211,\r\n source: \"FeedbackLink.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Failed to get feedback data connector */\r\n FailedToGetFeedbackDataConnector: {\r\n id: 8212,\r\n source: \"FeedbackLink.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const OneFooterErrors = {\r\n InvalidConfig: {\r\n source: \"OneFooter.connector.ts\",\r\n id: 8220,\r\n severity,\r\n pb\r\n },\r\n /** Failed to get feedback data connector */\r\n FailedToGetFeedbackDataConnector: {\r\n id: 8221,\r\n source: \"OneFooter.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const PoweredByLegendAppErrors = {\r\n /** The PoweredBy legend failed to load expected config settings */\r\n PoweredByLegendInvalidConfig: {\r\n id: 8230,\r\n source: \"PoweredByLegend.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst TabbedInfopaneSourceFile = \"TabbedInfopane.connector.ts\";\r\nexport const TabbedInfopaneErrors = {\r\n InitializeError: {\r\n source: TabbedInfopaneSourceFile,\r\n id: 8250,\r\n severity,\r\n pb\r\n },\r\n InvalidConfig: {\r\n source: TabbedInfopaneSourceFile,\r\n id: 8251,\r\n severity,\r\n pb\r\n },\r\n ChildLoadError: {\r\n source: TabbedInfopaneSourceFile,\r\n id: 8252,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const MeControlAppErrors = {\r\n /** The SSO call failed to return valid SSO sign-in information. */\r\n SSOFailedError: {\r\n id: 8260,\r\n source: \"MeControl.tsx\",\r\n severity,\r\n pb\r\n },\r\n /** The Me Control failed to load */\r\n MeControlLoadFailedError: {\r\n id: 8261,\r\n source: \"MeControl.tsx\",\r\n severity: Severity.HighImpact,\r\n pb\r\n }\r\n};\r\n\r\nconst TabbedInfopaneTabPreviewSourceFile = \"TabbedInfopaneTabPreview.connector.ts\";\r\nexport const TabbedInfopaneTabPreviewErrors = {\r\n InitError: {\r\n source: TabbedInfopaneTabPreviewSourceFile,\r\n id: 8270,\r\n severity,\r\n pb\r\n },\r\n InvalidConfig: {\r\n source: TabbedInfopaneTabPreviewSourceFile,\r\n id: 8271,\r\n severity,\r\n pb\r\n },\r\n LoadError: {\r\n source: TabbedInfopaneTabPreviewSourceFile,\r\n id: 8272,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const HeaderNavigationLogoAppErrors = {\r\n MegaMenuDataError: {\r\n id: 8280,\r\n source: \"HeaderNavigationLogoConnector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst pageClicksTrackerFileName = \"pageClicksTracker.ts\";\r\nexport const PageClickTrackerErrors = {\r\n InvalidResponse: {\r\n id: 8290,\r\n severity: Severity.NoAlert,\r\n source: pageClicksTrackerFileName,\r\n pb\r\n },\r\n FetchFailure: {\r\n id: 8291,\r\n severity: Severity.NoAlert,\r\n source: pageClicksTrackerFileName,\r\n pb\r\n }\r\n};\r\n\r\nconst TargetingSystemSourceFile = \"TargetingSystem.ts\";\r\nexport const TargetingSystemAppErrors = {\r\n GeneralError: {\r\n id: 8310,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n TopLevelDataMissing: {\r\n id: 8311,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n TrackingDataUPSMissing: {\r\n id: 8312,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n AppEnvironmentValuesMissing: {\r\n id: 8313,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n CallingOneServiceFailed: {\r\n id: 8314,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n CallingUPSServiceFailed: {\r\n id: 8315,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst CoachmarkSourceFile = \"Coachmark.connector.ts\";\r\nconst CoachmarkTSX = \"Coachmark.tsx\";\r\nexport const CoachmarkAppErrors = {\r\n GeneralError: {\r\n id: 8320,\r\n source: CoachmarkTSX,\r\n severity,\r\n pb\r\n },\r\n NotPlaceable: {\r\n id: 8321,\r\n source: CoachmarkTSX,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n NotFoundComponent: {\r\n id: 8322,\r\n source: CoachmarkSourceFile,\r\n severity,\r\n pb\r\n },\r\n CoachmarkDataConnectorUndefined: {\r\n id: 8323,\r\n source: CoachmarkSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst CoachmarkDataConnectorSourceFile = \"CoachmarkData.connector.ts\";\r\nconst CoachmarkPayloadSourceFile = \"CoachmarkPayload.ts\";\r\nconst IrisHandlerSourceFile = \"IrisHandler.ts\";\r\nexport const CoachmarkDataAppErrors = {\r\n InvalidCoachmarkMessage: {\r\n id: 8324,\r\n source: CoachmarkPayloadSourceFile,\r\n severity,\r\n pb\r\n },\r\n IrisDataConnectorUndefined: {\r\n id: 8325,\r\n source: IrisHandlerSourceFile,\r\n severity,\r\n pb\r\n },\r\n NoSurfaceFoundForCampaign: {\r\n id: 8326,\r\n source: IrisHandlerSourceFile,\r\n severity,\r\n pb\r\n },\r\n ErrorFoundForSurface: {\r\n id: 8327,\r\n source: IrisHandlerSourceFile,\r\n severity,\r\n pb\r\n },\r\n TelemetryInfoUndefined: {\r\n id: 8328,\r\n source: CoachmarkDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n EventTypeUndefined: {\r\n id: 8329,\r\n source: CoachmarkDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n IrisActionUndefined: {\r\n id: 8330,\r\n source: CoachmarkDataConnectorSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst SpotlightPreviewSourceFile = \"SpotlightPreview.connector.ts\";\r\n\r\nexport const SpotlightPreviewAppErrors = {\r\n ErrorWhileFetchingSpotlightPreviewCardInfo: {\r\n id: 8401,\r\n source: SpotlightPreviewSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n NoServiceContextMetadata: {\r\n id: 8402,\r\n source: SpotlightPreviewSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst SpotlightSourceFile = \"Spotlight.connector.ts\";\r\nexport const SpotlightErrors = {\r\n UnknownError: {\r\n id: 8500,\r\n source: SpotlightSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n ContentFetchError: {\r\n id: 8501,\r\n source: SpotlightSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const CommentsErrors: {[key: string]: AppError} = {\r\n NoPost: {\r\n id: 8510,\r\n source: \"Comments.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const CardActionErrors = {\r\n /** Error catch in base CardAction experience container */\r\n CardActionBaseExperienceError: {\r\n id: 8600,\r\n source: \"CardAction.tsx\",\r\n severity,\r\n pb\r\n },\r\n /** Post action failed (Like/Dislike) */\r\n CardActionPostActionError: {\r\n id: 8601,\r\n source: \"CarActionServiceClient.tsx\",\r\n severity,\r\n pb\r\n },\r\n /** Delete action failed (Unlike/Undislike) */\r\n CardActionDeleteActionError: {\r\n id: 8602,\r\n source: \"CardActionServiceClient.tsx\",\r\n severity,\r\n pb\r\n },\r\n /** Get action failed (GetPublisherDetails) */\r\n CardActionGetActionError: {\r\n id: 8603,\r\n source: \"CardActionServiceClient.tsx\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ContentRelatedSourceFile = \"ContentRelated.connector.ts\";\r\nexport const ContentRelatedErrors = {\r\n /**\r\n * Missing source Id error\r\n */\r\n MissingSourceIdError: {\r\n id: 8700,\r\n source: ContentRelatedSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Invalid sourceIdError\r\n */\r\n InvalidSourceIdError: {\r\n id: 8701,\r\n source: ContentRelatedSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Related contents feed fetch error\r\n */\r\n ContentRelatedFeedFetchError: {\r\n id: 8702,\r\n source: ContentRelatedSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst Cookies = \"Cookies.ts\";\r\nexport const CookieRelatedErrors = {\r\n SharedStateConnectorNull: {\r\n id: 8840,\r\n source: Cookies,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst CookieConsentBannerHelper = \"MsccCookieConsentHelper.ts\";\r\nexport const CookieConsentBannerHelperErrors = {\r\n FailedToParseStaticsUrls: {\r\n id: 8810,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n ScriptsNotFound: {\r\n id: 8811,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n StyleSheetsNotFound: {\r\n id: 8812,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n FailedToMountScript: {\r\n id: 8813,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n FailedToMountStyleSheet: {\r\n id: 8814,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents IFrame related errors */\r\nconst IFrameSourceFile = \"IFrame.tsx\";\r\nexport const IFrameErrors = {\r\n /** Message recieved by event listener not from expected origin */\r\n IFrameUnallowedOriginMessage: {\r\n id: 8820,\r\n source: IFrameSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const RightRailCarouselAppErrors = {\r\n NoChildrenExperienceFoundError: {\r\n id: 8830,\r\n source: \"RightRailCarousel.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const BreakingNewsErrors = {\r\n /** Error fetching Breaking News content */\r\n ContentFetchError: {\r\n id: 8901,\r\n source: \"BreakingNews.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Error fetching Blowout content */\r\n BlowoutDocumentFetchError: {\r\n id: 8902,\r\n source: \"BreakingNews.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const BlowoutErrors = {\r\n /** Error fetching Blowout content */\r\n ContentFetchError: {\r\n id: 8921,\r\n source: \"Blowout.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const OverlayErrors: { [name: string]: AppError } = {\r\n /** Error loading experience */\r\n LoadExperienceError: {\r\n id: 8941,\r\n source: \"Overlay.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const ViewsCommonAppErrors = {\r\n /** Invalid intra article component metadata passed. */\r\n InvalidIntraArticleDataError: {\r\n id: 9001,\r\n source: \"IntraArticleHelper.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch from data api. */\r\n DataFetchError: {\r\n id: 9002,\r\n source: \"ViewsServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Invalid content markup encountered. */\r\n InvalidDocumentContentError: {\r\n id: 9003,\r\n source: \"ViewsUtility.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load views paddle data from data api. */\r\n ViewsPaddleDataLoadError: {\r\n id: 9004,\r\n source: \"ViewsPaddle.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Error during app initialization for views page experience. */\r\n ViewsErrorPage: {\r\n id: 9005,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Error during mapping provider data for views content header experience */\r\n ProviderMapperError: {\r\n id: 9006,\r\n source: \"ViewContentHeader.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const LegacySharingToolbarAppErrors = {\r\n /** Failed to invoke legacy sharing toolbar. */\r\n LegacySharingToolbarInvokeError: {\r\n id: 9100,\r\n source: \"SharingHelper.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load sharing toolbar. */\r\n SharingToolbarLoadError: {\r\n id: 9101,\r\n source: \"LegacySharingToolbar.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Invalid source content id passed in. */\r\n InvalidContentIdError: {\r\n id: 9102,\r\n source: \"LegacySharingToolbar.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents ContentActionsToolbar experience related errors */\r\nconst ContentActionsToolbarConnectorSourceFile = \"ContentActionToolbar.connector.ts\";\r\nconst ContentActionsToolbarSourceFile = \"ContentActionToolbar.tsx\";\r\nconst ContentActionsToolbarServiceClientSourceFile = \"ContentActionToolbarServiceClient.tsx\";\r\nexport const ContentActionsToolbarAppErrors = {\r\n /** Failed to load sharing toolbar - 9120 */\r\n ContentActionsSharingToolbarLoadError: {\r\n id: 9120,\r\n source: ContentActionsToolbarConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Error fetching article data - 9121 */\r\n ContentActionsArticleDatafetchError: {\r\n id: 9121,\r\n source: ContentActionsToolbarConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Base Experience error - 9122 */\r\n ContentActionsBaseExperienceError: {\r\n id: 9122,\r\n source: ContentActionsToolbarSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Get content views action failed (getContentViewsRequest) - 9123 */\r\n ContentActionsGetDocumentDataError: {\r\n id: 9123,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Get content status action failed (getContentStatusRequest) - 9124 */\r\n ContentActionsGetContentStatusActionError: {\r\n id: 9124,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Delete action failed (Unlike/Undislike) - 9125 */\r\n ContentActionsDeleteActionError: {\r\n id: 9125,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Post action failed (Like/Dislike) - 9126 */\r\n ContentActionsPostActionError: {\r\n id: 9126,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Prime hybrid error loading the experience - 9127 */\r\n ContentActionsExperienceLoadError: {\r\n id: 9127,\r\n source: ContentActionsToolbarSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Missing vert/horiz placeholder to flip toolbar - 9128 */\r\n ContentActionsFlipToolbarError: {\r\n id: 9128,\r\n source: ContentActionsToolbarSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Failed fetching contentStatus - 9129 */\r\n ContentActionsContentStatusFetchError: {\r\n id: 9129,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Failed fetching contentPreview - 9130 */\r\n ContentActionsContentPreviewFetchError: {\r\n id: 9130,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nexport const ContentSharingToolbarAppErrors = {\r\n ContentSharingToolbarInitializationError: {\r\n id: 9150,\r\n source: \"ContentSharingToolbar.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const ContentProviderAppErrors = {\r\n /** Invalid source article/gallery id passed in. */\r\n InvalidSourceIdError: {\r\n id: 9200,\r\n source: \"ContentProvider.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch provider details. */\r\n ProviderDetailsFetchError: {\r\n id: 9201,\r\n source: \"ContentProvider.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch provider feed. */\r\n ProviderFeedFetchError: {\r\n id: 9202,\r\n source: \"ContentProvider.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Invalid layout template passed in. */\r\n InvalidLayoutTemplate: {\r\n id: 9203,\r\n source: \"ContentProvider.templates.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** ApplicationCache related messages */\r\nconst refreshHeadDataFile = \"Appcache/RefreshHeadData.ts\";\r\nconst edgeAppCacheHelperFile = \"Appcache/EdgeApplicationCacheHelper.ts\";\r\n\r\nexport const ApplicationCacheMessages = {\r\n FailedToFetchHeadData: {\r\n id: 9310,\r\n source: refreshHeadDataFile,\r\n severity,\r\n pb\r\n },\r\n CatastrophicFailedToFetchHeadData: {\r\n id: 9311,\r\n source: refreshHeadDataFile,\r\n severity,\r\n pb\r\n },\r\n StaleActivityIdEncountered: {\r\n id: 9312,\r\n source: refreshHeadDataFile,\r\n severity,\r\n pb\r\n },\r\n /**\r\n * The current DOM that is in AppCache doesn't match what should be getting served\r\n * to the user due to the existence of the ntps cookie that defines what the locale should be.\r\n * In this case, we must bypass AppCache to get the proper DOM from PCS.\r\n */\r\n LocaleMismatch: {\r\n id: 9313,\r\n source: edgeAppCacheHelperFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /**\r\n * Our checks determining we need to bypass appcache for the user are failing\r\n * to detect that the appcache refresh has succeeded. We've tried, for the current page view, to\r\n * bypass without any success.\r\n */\r\n RapidAppcacheForcedRefreshes: {\r\n id: 9314,\r\n source: edgeAppCacheHelperFile,\r\n severity,\r\n pb\r\n },\r\n FailedToReadFromStorage: {\r\n id: 9315,\r\n source: refreshHeadDataFile,\r\n severity,\r\n pb\r\n },\r\n FailedToWriteToStorage: {\r\n id: 9316,\r\n source: refreshHeadDataFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ViewsGallerySourceFile = \"ViewsGallery.connector.ts\";\r\nexport const ViewsGalleryAppErrors = {\r\n /** Invalid gallery id passed. */\r\n InvalidGalleryIdError: {\r\n id: 10001,\r\n source: ViewsGallerySourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load gallery data. */\r\n GalleryDataLoadError: {\r\n id: 10010,\r\n source: ViewsGallerySourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load images. */\r\n GalleryImagesLoadError: {\r\n id: 10020,\r\n source: ViewsGallerySourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst SlideShowConnectorFile = \"SlideShow.connector.ts\";\r\nconst SlideShowCarouselFile = \"SlideShowCarousel.tsx\";\r\nexport const SlideShowAppErrors = {\r\n /** Invalid slideshow id passed. */\r\n InvalidSlideShowIdError: {\r\n id: 10100,\r\n source: SlideShowConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load slideshow data. */\r\n SlideShowDataLoadError: {\r\n id: 10110,\r\n source: SlideShowConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load images. */\r\n SlideShowImagesLoadError: {\r\n id: 10120,\r\n source: SlideShowConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to ads refresh. */\r\n SlideShowAdsRefreshError: {\r\n id: 10130,\r\n source: SlideShowCarouselFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load image. */\r\n SlideShowImageLoadFailed: {\r\n id: 10135,\r\n source: SlideShowCarouselFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const VideoListAppErrors = {\r\n /** Failed to load the video list data. */\r\n VideoListDataLoadError: {\r\n id: 11001,\r\n source: \"VideoList.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst VideoContentSourceFile: string = \"VideoContent.connector.ts\";\r\nexport const VideoContentAppErrors = {\r\n /** Failed to load the video content data. */\r\n InvalidResponseFromVideoContentResponseJson: {\r\n id: 11101,\r\n source: VideoContentSourceFile,\r\n severity\r\n },\r\n /** Failed to fetch the video content data from server. */\r\n ErrorWhileFetchingContentPreviewContent: {\r\n id: 11102,\r\n source: VideoContentSourceFile,\r\n severity\r\n }\r\n};\r\n\r\nconst ViewsArticleSourceFile = \"ViewsArticle.connector.ts\";\r\nexport const ViewsArticleAppErrors = {\r\n /** Invalid article id passed. */\r\n InvalidArticleIdError: {\r\n id: 12001,\r\n source: ViewsArticleSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load article data. */\r\n ArticleDataLoadError: {\r\n id: 12002,\r\n source: ViewsArticleSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load intra-article component. */\r\n IntraArticleComponentLoadError: {\r\n id: 12003,\r\n source: ViewsArticleSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to invoke inline gallery experience. */\r\n InlineGalleryInvokeError: {\r\n id: 12004,\r\n source: ViewsArticleSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const InterestsSearchAppErrors = {\r\n /** Received non 200 from OneService */\r\n ErrorResponseFromOneService: {\r\n id: 13000,\r\n source: \"InterestsSearchServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Received a response from 200 but didn't have expected structure */\r\n ErrorResponseFromOneServiceIsInvalid: {\r\n id: 13001,\r\n source: \"InterestsSearchServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n /**\r\n * When building the XFeed URL for one of the suggestion items,\r\n * we weren't able to build a valid URL\r\n */\r\n InvalidUrlFoundForElement: {\r\n id: 13002,\r\n source: \"InterestsSearch.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /**\r\n * When building the XFeed URL for one of the suggestion items,\r\n * we weren't able to build a valid URL\r\n */\r\n SelectedItemNotFoundInSuggestions: {\r\n id: 13003,\r\n source: \"InterestsSearch.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /**\r\n * When building the XFeed URL for one of the suggestion items,\r\n * we weren't able to build a valid URL\r\n */\r\n SelectedItemIsInvalid: {\r\n id: 13004,\r\n source: \"InterestsSearch.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst EdgeHeaderConnectorFileName: string = \"EdgeHeader.connector.ts\";\r\n\r\nexport const EdgeHeaderAppErrors = {\r\n /** The BingImageData Connector was not loaded */\r\n BingImageDataConnectorNotLoaded: {\r\n id: 8240,\r\n source: EdgeHeaderConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MicrosoftNewsPageConnectorFileName: string = \"MicrosoftNewsPage.connector.ts\";\r\n\r\nexport const MicrosoftNewsPageAppErrors = {\r\n /** The BingImageData Connector was not loaded */\r\n BingImageDataConnectorNotLoaded: {\r\n id: 8241,\r\n source: MicrosoftNewsPageConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst InterestsConnectorFileName: string = \"Interests.connector.ts\";\r\nconst XfeedConnectorFileName: string = \"Xfeed.connector.ts\";\r\nexport const InterestsAppErrors = {\r\n /** We could not retrieve the list of Topics from OneService */\r\n InterestsRetrieveTopicsError: {\r\n id: 13100,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not retrieve the user's list of Followed Topics from OneService */\r\n InterestsRetrieveFollowedTopicsError: {\r\n id: 13101,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not retrieve the user's list of Muted Publishers from OneService */\r\n InterestsRetrieveMutedPublishersError: {\r\n id: 13102,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not UnMute a Muted Publisher */\r\n InterestsUnMutePublisherError: {\r\n id: 13103,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not follow a new interests topic */\r\n InterestsFollowTopicError: {\r\n id: 13104,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not unfollow an interests topic */\r\n InterestsUnfollowTopicError: {\r\n id: 13105,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** TopicState should not be undefined */\r\n InterestsTopicStateUndefined: