--- a/browser/modules/DirectoryLinksProvider.jsm
+++ b/browser/modules/DirectoryLinksProvider.jsm
@@ -10,28 +10,25 @@ const Ci = Components.interfaces;
const Cc = Components.classes;
const Cu = Components.utils;
const XMLHttpRequest =
Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1", "nsIXMLHttpRequest");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/Timer.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
"resource://gre/modules/NewTabUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm")
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
- "resource://gre/modules/UpdateChannel.jsm");
XPCOMUtils.defineLazyGetter(this, "gTextDecoder", () => {
return new TextDecoder();
});
// The filename where directory links are stored locally
const DIRECTORY_LINKS_FILE = "directoryLinks.json";
const DIRECTORY_LINKS_TYPE = "application/json";
@@ -45,61 +42,25 @@ const PREF_SELECTED_LOCALE = "general.us
const PREF_DIRECTORY_SOURCE = "browser.newtabpage.directory.source";
// The preference that tells where to send click/view pings
const PREF_DIRECTORY_PING = "browser.newtabpage.directory.ping";
// The preference that tells if newtab is enhanced
const PREF_NEWTAB_ENHANCED = "browser.newtabpage.enhanced";
-// Only allow explicitly approved frecent sites with display name
-const ALLOWED_FRECENT_SITES = new Map([
- [ 'airdroid.com,android-developers.blogspot.com,android.com,androidandme.com,androidapplications.com,androidapps.com,androidauthority.com,androidcentral.com,androidcommunity.com,androidfilehost.com,androidforums.com,androidguys.com,androidheadlines.com,androidpit.com,androidpolice.com,androidspin.com,androidtapp.com,androinica.com,droid-life.com,droidforums.net,droidviews.com,droidxforums.com,forum.xda-developers.com,phandroid.com,play.google.com,shopandroid.com,talkandroid.com,theandroidsoul.com,thedroidguy.com,videodroid.org',
- 'Technology' ],
- [ 'assurancewireless.com,att.com,attsavings.com,boostmobile.com,budgetmobile.com,consumercellular.com,credomobile.com,gosmartmobile.com,h2owirelessnow.com,lycamobile.com,lycamobile.us,metropcs.com,myfamilymobile.com,polarmobile.com,qlinkwireless.com,republicwireless.com,sprint.com,straighttalk.com,t-mobile.com,tracfonewireless.com,verizonwireless.com,virginmobile.com,virginmobile.com.au,virginmobileusa.com,vodafone.co.uk,vodafone.com,vzwshop.com',
- 'Mobile Phone' ],
- [ 'addons.mozilla.org,air.mozilla.org,blog.mozilla.org,bugzilla.mozilla.org,developer.mozilla.org,etherpad.mozilla.org,forums.mozillazine.org,hacks.mozilla.org,hg.mozilla.org,mozilla.org,planet.mozilla.org,quality.mozilla.org,support.mozilla.org,treeherder.mozilla.org,wiki.mozilla.org',
- 'Mozilla' ],
- [ '3dprint.com,4sysops.com,access-programmers.co.uk,accountingweb.com,addictivetips.com,adweek.com,afterdawn.com,akihabaranews.com,anandtech.com,appsrumors.com,arstechnica.com,belkin.com,besttechinfo.com,betanews.com,bgr.com,botcrawl.com,breakingmuscle.com,canonrumors.com,cheap-phones.com,chip.de,chip.eu,cio.com,citeworld.com,cleanpcremove.com,cnet.com,commentcamarche.net,computer.org,computerhope.com,computershopper.com,computerweekly.com,contextures.com,coolest-gadgets.com,crn.com,csoonline.com,daniweb.com,data.com,datacenterknowledge.com,ddj.com,devicemag.com,digitaltrends.com,dottech.org,dpreview.com,dslreports.com,edugeek.net,eetimes.com,engadget.com,epic.com,eurekalert.org,eweek.com,experts-exchange.com,extremetech.com,fosshub.com,freesoftwaremagazine.com,funkyspacemonkey.com,futuremark.com,gadgetreview.com,ghacks.net,gizmodo.co.uk,gizmodo.com,globalsecurity.org,greenbot.com,gunup.com,guru3d.com,head-fi.org,hexus.net,hothardware.com,howtoforge.com,idg.com.au,idigitaltimes.com,idownloadblog.com,ihackmyi.com,ilounge.com,infomine.com,informationweek.com,intellireview.com,intomobile.com,iphonehacks.com,ismashphone.com,isource.com,it168.com,itechpost.com,itpro.co.uk,itworld.com,jailbreaknation.com,kioskea.net,laptoping.com,laptopmag.com,lightreading.com,livescience.com,malwaretips.com,mediaroom.com,mobilemag.com,modmyi.com,modmymobile.com,mophie.com,mozillazine.org,neoseeker.com,neowin.net,newscientist.com,newsoxy.com,nextadvisor.com,notebookcheck.com,notebookreview.com,nvidia.com,nwc.com,orafaq.com,osdir.com,osxdaily.com,our-hometown.com,pcadvisor.co.uk,pchome.net,pcmag.com,pconline.com.cn,pcpop.com,pcpro.co.uk,pcreview.co.uk,pcrisk.com,pcwelt.de,phonerebel.com,phonescoop.com,physorg.com,pocket-lint.com,post-theory.com,prnewswire.co.uk,prnewswire.com,programming4.us,quickpwn.com,readwrite.com,redmondpie.com,redorbit.com,reviewed.com,safer-networking.org,sciencedaily.com,sciencenews.org,scientificamerican.com,scientificblogging.com,sciverse.com,servicerow.com,sinfuliphone.com,singularityhub.com,slashdot.org,slashgear.com,softonic.com,softonic.com.br,softonic.fr,sophos.com,space.com,sparkfun.com,speedguide.net,stuff.tv,techdailynews.net,techdirt.com,techeblog.com,techhive.com,techie-buzz.com,technewsworld.com,techniqueworld.com,technobuffalo.com,technologyreview.com,technologytell.com,techpowerup.com,techpp.com,techrepublic.com,techshout.com,techweb.com,techworld.com,techworld.com.au,techworldtweets.com,telecomfile.com,tgdaily.com,theinquirer.net,thenextweb.com,theregister.co.uk,thermofisher.com,theverge.com,thewindowsclub.com,tomsguide.com,tomshardware.com,tomsitpro.com,toptenreviews.com,trustedreviews.com,tuaw.com,tweaktown.com,ubergizmo.com,unwiredview.com,venturebeat.com,wccftech.com,webmonkey.com,webpronews.com,windows7codecs.com,windowscentral.com,windowsitpro.com,windowstechies.com,winsupersite.com,wired.co.uk,wired.com,wp-themes.com,xda-developers.com,xml.com,zdnet.com,zmescience.com,zol.com.cn',
- 'Technology' ],
- [ '9to5mac.com,appadvice.com,apple.com,appleinsider.com,appleturns.com,appsafari.com,cultofmac.com,everymac.com,insanelymac.com,iphoneunlockspot.com,isource.com,itunes.apple.com,lowendmac.com,mac-forums.com,macdailynews.com,macenstein.com,macgasm.net,macintouch.com,maclife.com,macnews.com,macnn.com,macobserver.com,macosx.com,macpaw.com,macrumors.com,macsales.com,macstories.net,macupdate.com,macuser.co.uk,macworld.co.uk,macworld.com,maxiapple.com,spymac.com,theapplelounge.com',
- 'Technology' ],
- [ 'alistapart.com,answers.microsoft.com,backpack.openbadges.org,blog.chromium.org,caniuse.com,codefirefox.com,codepen.io,css-tricks.com,css3generator.com,cssdeck.com,csswizardry.com,devdocs.io,docs.angularjs.org,ghacks.net,github.com,html5demos.com,html5rocks.com,html5test.com,iojs.org,khanacademy.org,l10n.mozilla.org,learn.jquery.com,marketplace.firefox.com,mozilla-hispano.org,mozillians.org,news.ycombinator.com,npmjs.com,packagecontrol.io,quirksmode.org,readwrite.com,reps.mozilla.org,smashingmagazine.com,stackoverflow.com,status.modern.ie,teamtreehouse.com,tutorialspoint.com,udacity.com,validator.w3.org,w3.org,w3cschool.cc,w3schools.com,whatcanidoformozilla.org',
- 'Web Development' ],
- [ 'classroom.google.com,codecademy.com,elearning.ut.ac.id,khanacademy.org,learn.jquery.com,teamtreehouse.com,tutorialspoint.com,udacity.com,w3cschool.cc,w3schools.com',
- 'Web Education' ],
- [ 'abebooks.co.uk,abebooks.com,alibris.com,allaboutcircuits.com,allyoucanbooks.com,answersingenesis.org,artnet.com,audiobooks.com,barnesandnoble.com,barnesandnobleinc.com,bartleby.com,betterworldbooks.com,biggerbooks.com,bncollege.com,bookbyte.com,bookdepository.com,bookfinder.com,bookrenter.com,booksamillion.com,booksite.com,boundless.com,brookstone.com,btol.com,calibre-ebook.com,campusbookrentals.com,casadellibro.com,cbomc.com,cengagebrain.com,chapters.indigo.ca,christianbook.com,ciscopress.com,coursesmart.com,cqpress.com,crafterschoice.com,crossings.com,cshlp.org,deseretbook.com,directtextbook.com,discountmags.com,doubledaybookclub.com,doubledaylargeprint.com,doverpublications.com,ebooks.com,ecampus.com,fellabooks.net,fictionwise.com,flatworldknowledge.com,grolier.com,harpercollins.com,hayhouse.com,historybookclub.com,hpb.com,hpbmarketplace.com,interweave.com,iseeme.com,katiekazoo.com,knetbooks.com,learnoutloud.com,librarything.com,literaryguild.com,lulu.com,lww.com,macmillan.com,magazines.com,mbsdirect.net,militarybookclub.com,mypearsonstore.com,mysteryguild.com,netplaces.com,noble.com,novelguide.com,onespirit.com,oxfordjournals.org,paperbackswap.com,papy.co.jp,peachpit.com,penguin.com,penguingroup.com,pimsleur.com,powells.com,qpb.com,quepublishing.com,reviews.com,rhapsodybookclub.com,rodalestore.com,royalsocietypublishing.org,sagepub.com,scrubsmag.com,sfbc.com,simonandschuster.com,simonandschuster.net,simpletruths.com,teach12.net,textbooks.com,textbookx.com,thegoodcook.com,thriftbooks.com,tlsbooks.com,toshibabookplace.com,tumblebooks.com,urbookdownload.com,valorebooks.com,valuemags.com,wwnorton.com,zoobooks.com',
- 'Literature' ],
- [ 'aceshowbiz.com,aintitcoolnews.com,askkissy.com,askmen.com,atraf.co.il,audioboom.com,beamly.com,blippitt.com,bollywoodlife.com,bossip.com,buzzlamp.com,celebdirtylaundry.com,celebfocus.com,celebitchy.com,celebrity-gossip.net,celebrityabout.com,celebwild.com,chisms.net,concertboom.com,crushable.com,cultbox.co.uk,dailyentertainmentnews.com,dayscafe.com,deadline.com,deathandtaxesmag.com,diaryofahollywoodstreetking.com,digitalspy.com,egotastic.com,empirenews.net,enelbrasero.com,everydaycelebs.com,ew.com,extratv.com,facade.com,fanaru.com,fhm.com,geektyrant.com,glamourpage.com,heatworld.com,hlntv.com,hollyscoop.com,hollywoodreporter.com,hollywoodtuna.com,hypable.com,infotransfer.net,insideedition.com,interaksyon.com,jezebel.com,justjared.com,justjaredjr.com,komando.com,koreaboo.com,maxgo.com,maxim.com,maxviral.com,mediatakeout.com,mosthappy.com,moviestalk.com,my.ology.com,ngoisao.net,nofilmschool.com,nolocreo.com,octane.tv,ouchpress.com,people.com,peopleenespanol.com,perezhilton.com,pinkisthenewblog.com,platotv.tv,playbill.com,playbillvault.com,playgroundmag.net,popeater.com,popnhop.com,popsugar.co.uk,popsugar.com,purepeople.com,radaronline.com,rantchic.com,reshareworthy.com,rinkworks.com,ripbird.com,sara-freder.com,screenjunkies.com,soapcentral.com,soapoperadigest.com,sobadsogood.com,splitsider.com,starcasm.net,starpulse.com,straightfromthea.com,stupidcelebrities.net,stupiddope.com,tbn.org,theawesomedaily.com,theawl.com,thefrisky.com,thefw.com,theresacaputo.com,thezooom.com,tvnotas.com.mx,twanatells.com,vanswarpedtour.com,vietgiaitri.com,viral.buzz,vulture.com,wakavision.com,worthytales.net,wwtdd.com,younghollywood.com',
- 'Entertainment News' ],
- [ '247wallst.com,4-traders.com,advfn.com,agweb.com,allbusiness.com,barchart.com,barrons.com,beckershospitalreview.com,benzinga.com,bizjournals.com,bizsugar.com,bloomberg.com,bloomberglaw.com,business-standard.com,businessinsider.com,businessinsider.com.au,businesspundit.com,businessweek.com,businesswire.com,cboe.com,cheatsheet.com,chicagobusiness.com,cjonline.com,cnbc.com,cnnmoney.com,cqrcengage.com,dailyfinance.com,dailyfx.com,dealbreaker.com,djindexes.com,dowjones.com,easierstreetdaily.com,economist.com,economyandmarkets.com,economywatch.com,edweek.org,eleconomista.es,entrepreneur.com,etfdailynews.com,etfdb.com,ewallstreeter.com,fastcolabs.com,fastcompany.com,financeformulas.net,financialpost.com,flife.de,forbes.com,forexpros.com,fortune.com,foxbusiness.com,ft.com,ftpress.com,fx-exchange.com,hbr.org,howdofinance.com,ibtimes.com,inc.com,investopedia.com,investors.com,investorwords.com,journalofaccountancy.com,kiplinger.com,lendingandcredit.net,lfb.org,mainstreet.com,markettraders.com,marketwatch.com,maxkeiser.com,minyanville.com,ml.com,moneycontrol.com,moneymappress.com,moneynews.com,moneysavingexpert.com,morningstar.com,mortgagenewsdaily.com,motleyfool.com,mt.co.kr,nber.org,nyse.com,oilprice.com,pewsocialtrends.org,principal.com,qz.com,rantfinance.com,realclearmarkets.com,recode.net,reuters.ca,reuters.co.in,reuters.co.uk,reuters.com,rttnews.com,seekingalpha.com,smallbiztrends.com,streetinsider.com,thecheapinvestor.com,theeconomiccollapseblog.com,themoneyconverter.com,thestreet.com,tickertech.com,tradingeconomics.com,updown.com,valuewalk.com,wikinvest.com,wsj.com,zacks.com',
- 'Financial News' ],
- [ '10tv.com,8newsnow.com,9news.com,abc.net.au,abc7.com,abc7chicago.com,abcnews.go.com,aclu.org,activistpost.com,ajc.com,al.com,alan.com,alarab.net,aljazeera.com,americanthinker.com,app.com,aristeguinoticias.com,azcentral.com,baltimoresun.com,becomingminimalist.com,beforeitsnews.com,bigstory.ap.org,blackamericaweb.com,bloomberg.com,bloombergview.com,boston.com,bostonherald.com,breitbart.com,buffalonews.com,c-span.org,canada.com,cbs46.com,cbsnews.com,chicagotribune.com,chron.com,citizensvoice.com,citylab.com,cleveland.com,cnn.com,coed.com,countercurrentnews.com,courant.com,ctvnews.ca,dailyherald.com,dailynews.com,dallasnews.com,delawareonline.com,democratandchronicle.com,democraticunderground.com,democrats.org,denverpost.com,desmoinesregister.com,dispatch.com,elcomercio.pe,english.aljazeera.net,examiner.com,farsnews.com,firstcoastnews.com,firstpost.com,firsttoknow.com,foreignpolicy.com,foxnews.com,freebeacon.com,freep.com,fresnobee.com,gazette.com,global.nytimes.com,heraldtribune.com,hindustantimes.com,hngn.com,humanevents.com,huzlers.com,indiatimes.com,indystar.com,irishtimes.com,jacksonville.com,jpost.com,jsonline.com,kansascity.com,kctv5.com,kentucky.com,kickerdaily.com,king5.com,kmov.com,knoxnews.com,kpho.com,kvue.com,kwqc.com,kxan.com,lainformacion.com,latimes.com,ldnews.com,lex18.com,linternaute.com,livemint.com,lostateminor.com,m24.ru,macleans.ca,manchestereveningnews.co.uk,marinecorpstimes.com,masslive.com,mavikocaeli.com.tr,mcall.com,medium.com,mentalfloss.com,mercurynews.com,metro.us,miamiherald.com,militarytimes.com,mk.ru,mlive.com,mondotimes.com,montrealgazette.com,msnbc.com,msnewsnow.com,mynews13.com,mysanantonio.com,mysuncoast.com,nbclosangeles.com,nbcnewyork.com,nbcphiladelphia.com,ndtv.com,newindianexpress.com,news.cincinnati.com,news.google.com,news.msn.com,news.yahoo.com,news10.net,news8000.com,newsday.com,newsdaymarketing.net,newsen.com,newsmax.com,newsobserver.com,newsok.com,newsru.ua,newstatesman.com,newszoom.com,nj.com,nola.com,northjersey.com,nouvelobs.com,npr.org,nwfdailynews.com,nwitimes.com,nydailynews.com,nytimes.com,observer.com,ocregister.com,okcfox.com,omaha.com,onenewspage.com,ontheissues.org,oregonlive.com,orlandosentinel.com,palmbeachpost.com,pe.com,pennlive.com,philly.com,pilotonline.com,polar.com,post-gazette.com,postandcourier.com,presstelegram.com,presstv.ir,propublica.org,providencejournal.com,realclearpolitics.com,recorderonline.com,reporterdock.com,reporterherald.com,respublica.al,reuters.com,rg.ru,roanoke.com,sacbee.com,scmp.com,scnow.com,sdpnoticias.com,seattletimes.com,semana.com,sfgate.com,sharepowered.com,sinembargo.mx,slate.com,sltrib.com,sotomayortv.com,sourcewatch.org,spectator.co.uk,squaremirror.com,star-telegram.com,staradvertiser.com,startribune.com,statesman.com,stltoday.com,streetwise.co,stuff.co.nz,success.com,suffolknewsherald.com,sun-sentinel.com,sunnewsnetwork.ca,suntimes.com,supernewschannel.com,surenews.com,svoboda.org,syracuse.com,tampabay.com,tbd.com,telegram.com,telegraph.co.uk,tennessean.com,the-open-mind.com,theadvocate.com,theage.com.au,theatlantic.com,thebarefootwriter.com,theblaze.com,thecalifornian.com,thedailysheeple.com,thefix.com,theintelligencer.net,thelocal.com,thenational.ae,thenewstribune.com,theparisreview.org,thereporter.com,therepublic.com,thestar.com,thetelegram.com,thetimes.co.uk,theuspatriot.com,time.com,timescall.com,timesdispatch.com,timesleaderonline.com,timesofisrael.com,toledoblade.com,toprightnews.com,townhall.com,tpnn.com,trendolizer.com,triblive.com,tribune.com.pk,tricities.com,troymessenger.com,trueactivist.com,truthandaction.org,tsn.ua,tulsaworld.com,twincities.com,upi.com,usatoday.com,utsandiego.com,vagazette.com,viralwomen.com,vitalworldnews.com,voasomali.com,vox.com,washingtonexaminer.com,washingtonpost.com,watchdog.org,wave3.com,wavy.com,wbay.com,wbtw.com,wcpo.com,wctrib.com,wdtn.com,weeklystandard.com,westernjournalism.com,wfsb.com,wgrz.com,whas11.com,winonadailynews.com,wishtv.com,wistv.com,wkbn.com,wkow.com,wlfi.com,wmtw.com,wmur.com,wopular.com,world-top-news.com,worldnews.com,wplol.us,wpsdlocal6.com,wptz.com,wric.com,wsmv.com,wthitv.com,wthr.com,wtnh.com,wtol.com,wtsp.com,wvec.com,wwlp.com,wwltv.com,wyff4.com,yonhapnews.co.kr,yourbreakingnews.com',
- 'News' ],
- [ '2k.com,360game.vn,4399.com,a10.com,activision.com,addictinggames.com,alawar.com,alienwarearena.com,anagrammer.com,andkon.com,aq.com,arcadeprehacks.com,arcadeyum.com,arcgames.com,archeagegame.com,armorgames.com,askmrrobot.com,battle.net,battlefieldheroes.com,bigfishgames.com,bigpoint.com,bioware.com,bluesnews.com,boardgamegeek.com,bollyheaven.com,bubblebox.com,bukkit.org,bungie.net,buycraft.net,callofduty.com,candystand.com,cda.pl,challonge.com,championselect.net,cheapassgamer.com,cheatcc.com,cheatengine.org,cheathappens.com,chess.com,civfanatics.com,clashofclans-tools.com,clashofclansbuilder.com,comdotgame.com,commonsensemedia.org,coolrom.com,crazygames.com,csgolounge.com,curse.com,d20pfsrd.com,destructoid.com,diablofans.com,diablowiki.net,didigames.com,dota2.com,dota2lounge.com,dressupgames.com,dulfy.net,ebog.com,elderscrollsonline.com,elitedangerous.com,elitepvpers.com,emuparadise.me,enjoydressup.com,escapegames24.com,escapistmagazine.com,eventhubs.com,eveonline.com,farming-simulator.com,feed-the-beast.com,flashgames247.com,flightrising.com,flipline.com,flonga.com,freegames.ws,freeonlinegames.com,fresh-hotel.org,friv.com,friv.today,fullypcgames.net,funny-games.biz,funtrivia.com,futhead.com,g2a.com,gamasutra.com,game-debate.com,game-oldies.com,game321.com,gamebaby.com,gamebaby.net,gamebanana.com,gamefaqs.com,gamefly.com,gamefront.com,gamegape.com,gamehouse.com,gameinformer.com,gamejolt.com,gamemazing.com,gamemeteor.com,gamerankings.com,gamersgate.com,games-msn.com,games-workshop.com,games.com,games2girls.com,gamesbox.com,gamesfreak.net,gametop.com,gametracker.com,gametrailers.com,gamezhero.com,gbatemp.net,geforce.com,gematsu.com,giantbomb.com,girl.me,girlsgames123.com,girlsplay.com,gog.com,gogames.me,gonintendo.com,goodgamestudios.com,gosugamers.net,greenmangaming.com,gtaforums.com,gtainside.com,guildwars2.com,hackedarcadegames.com,hearthpwn.com,hirezstudios.com,hitbox.tv,hltv.org,howrse.com,icy-veins.com,indiedb.com,jayisgames.com,jigzone.com,joystiq.com,juegosdechicas.com,kabam.com,kbhgames.com,kerbalspaceprogram.com,king.com,kixeye.com,kizi.com,kogama.com,kongregate.com,kotaku.com,lolcounter.com,lolking.net,lolnexus.com,lolpro.com,lolskill.net,lootcrate.com,lumosity.com,mafa.com,mangafox.me,mangapark.com,mariowiki.com,maxgames.com,megagames.com,metacritic.com,mindjolt.com,minecraft.net,minecraftforum.net,minecraftservers.org,minecraftskins.com,mineplex.com,miniclip.com,mmo-champion.com,mmobomb.com,mmohuts.com,mmorpg.com,mmosite.com,mobafire.com,moddb.com,modxvm.com,mojang.com,moshimonsters.com,mousebreaker.com,moviestarplanet.com,mtgsalvation.com,muchgames.com,myonlinearcade.com,myplaycity.com,myrealgames.com,mythicspoiler.com,n4g.com,newgrounds.com,nexon.net,nexusmods.com,ninjakiwi.com,nintendo.com,nintendoeverything.com,nintendolife.com,nitrome.com,nosteam.ro,notdoppler.com,noxxic.com,operationsports.com,origin.com,ownedcore.com,pacogames.com,pathofexile.com,pcgamer.com,pch.com,pcsx2.net,penny-arcade.com,planetminecraft.com,plarium.com,playdota.com,playpink.com,playsides.com,playstationlifestyle.net,playstationtrophies.org,pog.com,pokemon.com,polygon.com,popcap.com,primarygames.com,probuilds.net,ps3hax.net,psnprofiles.com,psu.com,qq.com,r2games.com,resourcepack.net,retrogamer.com,rewardtv.com,riotgames.com,robertsspaceindustries.com,roblox.com,robocraftgame.com,rockpapershotgun.com,rockstargames.com,roosterteeth.com,runescape.com,schoolofdragons.com,screwattack.com,scufgaming.com,segmentnext.com,shacknews.com,shockwave.com,shoryuken.com,siliconera.com,silvergames.com,skydaz.com,smashbros.com,solomid.net,starcitygames.com,starsue.net,steamcommunity.com,steamgifts.com,strategywiki.org,supercheats.com,surrenderat20.net,swtor.com,tankionline.com,tcgplayer.com,teamfortress.com,teamliquid.net,tetrisfriends.com,thesims3.com,thesimsresource.com,thetechgame.com,topg.org,totaljerkface.com,toucharcade.com,transformice.com,trueachievements.com,twcenter.net,twitch.tv,twoplayergames.org,unity3d.com,vg247.com,vgchartz.com,videogamesblogger.com,warframe.com,warlight.net,warthunder.com,watchcartoononline.com,websudoku.com,wildstar-online.com,wildtangent.com,wineverygame.com,wizards.com,worldofsolitaire.com,worldoftanks.com,wowhead.com,wowprogress.com,wowwiki.com,xbox.com,xbox360iso.com,xboxachievements.com,xfire.com,xtremetop100.com,y8.com,yoyogames.com,zybez.net,zynga.com',
- 'Video Game' ],
- [ 'chat.com,fring.com,hello.firefox.com,skype.com,viber.com,vonage.com',
- 'Video Chat' ],
-]);
-
// Only allow link urls that are http(s)
const ALLOWED_LINK_SCHEMES = new Set(["http", "https"]);
// Only allow link image urls that are https or data
const ALLOWED_IMAGE_SCHEMES = new Set(["https", "data"]);
// The frecency of a directory link
const DIRECTORY_FRECENCY = 1000;
-// The frecency of a suggested link
-const SUGGESTED_FRECENCY = Infinity;
-
-// Default number of times to show a link
-const DEFAULT_FREQUENCY_CAP = 5;
-
// Divide frecency by this amount for pings
const PING_SCORE_DIVISOR = 10000;
// Allowed ping actions remotely stored as columns: case-insensitive [a-z0-9_]
const PING_ACTIONS = ["block", "click", "pin", "sponsored", "sponsored_link", "unpin", "view"];
/**
* Singleton that serves as the provider of directory links.
@@ -118,31 +79,16 @@ let DirectoryLinksProvider = {
// download default interval is 24 hours in milliseconds
_downloadIntervalMS: 86400000,
/**
* A mapping from eTLD+1 to an enhanced link objects
*/
_enhancedLinks: new Map(),
- /**
- * A mapping from site to remaining number of views
- */
- _frequencyCaps: new Map(),
-
- /**
- * A mapping from site to a list of suggested link objects
- */
- _suggestedLinks: new Map(),
-
- /**
- * A set of top sites that we can provide suggested links for
- */
- _topSitesWithSuggestedLinks: new Set(),
-
get _observedPrefs() Object.freeze({
enhanced: PREF_NEWTAB_ENHANCED,
linksURL: PREF_DIRECTORY_SOURCE,
matchOSLocale: PREF_MATCH_OS_LOCALE,
prefSelectedLocale: PREF_SELECTED_LOCALE,
}),
get _linksURL() {
@@ -236,32 +182,19 @@ let DirectoryLinksProvider = {
_removePrefsObserver: function DirectoryLinksProvider_removeObserver() {
for (let pref in this._observedPrefs) {
let prefName = this._observedPrefs[pref];
Services.prefs.removeObserver(prefName, this);
}
},
- _cacheSuggestedLinks: function(link) {
- if (!link.frecent_sites || "sponsored" == link.type) {
- // Don't cache links that don't have the expected 'frecent_sites' or are sponsored.
- return;
- }
- for (let suggestedSite of link.frecent_sites) {
- let suggestedMap = this._suggestedLinks.get(suggestedSite) || new Map();
- suggestedMap.set(link.url, link);
- this._suggestedLinks.set(suggestedSite, suggestedMap);
- }
- },
-
_fetchAndCacheLinks: function DirectoryLinksProvider_fetchAndCacheLinks(uri) {
// Replace with the same display locale used for selecting links data
uri = uri.replace("%LOCALE%", this.locale);
- uri = uri.replace("%CHANNEL%", UpdateChannel.get());
let deferred = Promise.defer();
let xmlHttp = new XMLHttpRequest();
let self = this;
xmlHttp.onload = function(aResponse) {
let json = this.responseText;
if (this.status && this.status != 200) {
@@ -333,67 +266,46 @@ let DirectoryLinksProvider = {
if ((Date.now() - this._lastDownloadMS) > this._downloadIntervalMS) {
return true;
}
return false;
},
/**
* Reads directory links file and parses its content
- * @return a promise resolved to an object with keys 'directory' and 'suggested',
- * each containing a valid list of links,
- * or {'directory': [], 'suggested': []} if read or parse fails.
+ * @return a promise resolved to valid list of links or [] if read or parse fails
*/
_readDirectoryLinksFile: function DirectoryLinksProvider_readDirectoryLinksFile() {
- let emptyOutput = {directory: [], suggested: [], enhanced: []};
return OS.File.read(this._directoryFilePath).then(binaryData => {
let output;
try {
+ let locale = this.locale;
let json = gTextDecoder.decode(binaryData);
- let linksObj = JSON.parse(json);
- output = {directory: linksObj.directory || [],
- suggested: linksObj.suggested || [],
- enhanced: linksObj.enhanced || []};
+ let list = JSON.parse(json);
+ output = list[locale];
}
catch (e) {
Cu.reportError(e);
}
- return output || emptyOutput;
+ return output || [];
},
error => {
Cu.reportError(error);
- return emptyOutput;
+ return [];
});
},
/**
* Report some action on a newtab page (view, click)
* @param sites Array of sites shown on newtab page
* @param action String of the behavior to report
* @param triggeringSiteIndex optional Int index of the site triggering action
* @return download promise
*/
reportSitesAction: function DirectoryLinksProvider_reportSitesAction(sites, action, triggeringSiteIndex) {
- // Check if the suggested tile was shown
- if (action == "view") {
- sites.slice(0, triggeringSiteIndex + 1).forEach(site => {
- let {targetedSite, url} = site.link;
- if (targetedSite) {
- this._decreaseFrequencyCap(url, 1);
- }
- });
- }
- // Use up all views if the user clicked on a frequency capped tile
- else if (action == "click") {
- let {targetedSite, url} = sites[triggeringSiteIndex].link;
- if (targetedSite) {
- this._decreaseFrequencyCap(url, DEFAULT_FREQUENCY_CAP);
- }
- }
-
let newtabEnhanced = false;
let pingEndPoint = "";
try {
newtabEnhanced = Services.prefs.getBoolPref(PREF_NEWTAB_ENHANCED);
pingEndPoint = Services.prefs.getCharPref(PREF_DIRECTORY_PING);
}
catch (ex) {}
@@ -444,29 +356,21 @@ let DirectoryLinksProvider = {
return this._fetchAndCacheLinksIfNecessary();
},
/**
* Get the enhanced link object for a link (whether history or directory)
*/
getEnhancedLink: function DirectoryLinksProvider_getEnhancedLink(link) {
// Use the provided link if it's already enhanced
- return link.enhancedImageURI && link ? link :
+ return link.enhancedImageURI && link ||
this._enhancedLinks.get(NewTabUtils.extractSite(link.url));
},
/**
- * Get the display name of an allowed frecent sites. Returns undefined for a
- * unallowed frecent sites.
- */
- getFrecentSitesName(sites) {
- return ALLOWED_FRECENT_SITES.get(sites.join(","));
- },
-
- /**
* Check if a url's scheme is in a Set of allowed schemes
*/
isURLAllowed: function DirectoryLinksProvider_isURLAllowed(url, allowed) {
// Assume no url is an allowed url
if (!url) {
return true;
}
@@ -480,247 +384,58 @@ let DirectoryLinksProvider = {
},
/**
* Gets the current set of directory links.
* @param aCallback The function that the array of links is passed to.
*/
getLinks: function DirectoryLinksProvider_getLinks(aCallback) {
this._readDirectoryLinksFile().then(rawLinks => {
- // Reset the cache of suggested tiles and enhanced images for this new set of links
+ // Reset the cache of enhanced images for this new set of links
this._enhancedLinks.clear();
- this._frequencyCaps.clear();
- this._suggestedLinks.clear();
- let validityFilter = function(link) {
+ return rawLinks.filter(link => {
// Make sure the link url is allowed and images too if they exist
return this.isURLAllowed(link.url, ALLOWED_LINK_SCHEMES) &&
this.isURLAllowed(link.imageURI, ALLOWED_IMAGE_SCHEMES) &&
this.isURLAllowed(link.enhancedImageURI, ALLOWED_IMAGE_SCHEMES);
- }.bind(this);
-
- rawLinks.suggested.filter(validityFilter).forEach((link, position) => {
- // Only allow suggested links with approved frecent sites
- let name = this.getFrecentSitesName(link.frecent_sites);
- if (name == undefined) {
- return;
- }
-
- link.targetedName = name;
- link.lastVisitDate = rawLinks.suggested.length - position;
-
- // We cache suggested tiles here but do not push any of them in the links list yet.
- // The decision for which suggested tile to include will be made separately.
- this._cacheSuggestedLinks(link);
- this._frequencyCaps.set(link.url, DEFAULT_FREQUENCY_CAP);
- });
-
- rawLinks.enhanced.filter(validityFilter).forEach((link, position) => {
- link.lastVisitDate = rawLinks.enhanced.length - position;
-
+ }).map((link, position) => {
// Stash the enhanced image for the site
if (link.enhancedImageURI) {
this._enhancedLinks.set(NewTabUtils.extractSite(link.url), link);
}
- });
- let links = rawLinks.directory.filter(validityFilter).map((link, position) => {
- link.lastVisitDate = rawLinks.directory.length - position;
link.frecency = DIRECTORY_FRECENCY;
+ link.lastVisitDate = rawLinks.length - position;
return link;
});
-
- // Allow for one link suggestion on top of the default directory links
- this.maxNumLinks = links.length + 1;
-
- return links;
}).catch(ex => {
Cu.reportError(ex);
return [];
- }).then(links => {
- aCallback(links);
- this._populatePlacesLinks();
- });
+ }).then(aCallback);
},
init: function DirectoryLinksProvider_init() {
this._setDefaultEnhanced();
this._addPrefsObserver();
// setup directory file path and last download timestamp
this._directoryFilePath = OS.Path.join(OS.Constants.Path.localProfileDir, DIRECTORY_LINKS_FILE);
this._lastDownloadMS = 0;
-
- NewTabUtils.placesProvider.addObserver(this);
-
return Task.spawn(function() {
// get the last modified time of the links file if it exists
let doesFileExists = yield OS.File.exists(this._directoryFilePath);
if (doesFileExists) {
let fileInfo = yield OS.File.stat(this._directoryFilePath);
this._lastDownloadMS = Date.parse(fileInfo.lastModificationDate);
}
// fetch directory on startup without force
yield this._fetchAndCacheLinksIfNecessary();
}.bind(this));
},
- _handleManyLinksChanged: function() {
- this._topSitesWithSuggestedLinks.clear();
- this._suggestedLinks.forEach((suggestedLinks, site) => {
- if (NewTabUtils.isTopPlacesSite(site)) {
- this._topSitesWithSuggestedLinks.add(site);
- }
- });
- this._updateSuggestedTile();
- },
-
- /**
- * Updates _topSitesWithSuggestedLinks based on the link that was changed.
- *
- * @return true if _topSitesWithSuggestedLinks was modified, false otherwise.
- */
- _handleLinkChanged: function(aLink) {
- let changedLinkSite = NewTabUtils.extractSite(aLink.url);
- let linkStored = this._topSitesWithSuggestedLinks.has(changedLinkSite);
-
- if (!NewTabUtils.isTopPlacesSite(changedLinkSite) && linkStored) {
- this._topSitesWithSuggestedLinks.delete(changedLinkSite);
- return true;
- }
-
- if (this._suggestedLinks.has(changedLinkSite) &&
- NewTabUtils.isTopPlacesSite(changedLinkSite) && !linkStored) {
- this._topSitesWithSuggestedLinks.add(changedLinkSite);
- return true;
- }
- return false;
- },
-
- _populatePlacesLinks: function () {
- NewTabUtils.links.populateProviderCache(NewTabUtils.placesProvider, () => {
- this._handleManyLinksChanged();
- });
- },
-
- onLinkChanged: function (aProvider, aLink) {
- // Make sure NewTabUtils.links handles the notification first.
- setTimeout(() => {
- if (this._handleLinkChanged(aLink)) {
- this._updateSuggestedTile();
- }
- }, 0);
- },
-
- onManyLinksChanged: function () {
- // Make sure NewTabUtils.links handles the notification first.
- setTimeout(() => {
- this._handleManyLinksChanged();
- }, 0);
- },
-
- /**
- * Record for a url that some number of views have been used
- * @param url String url of the suggested link
- * @param amount Number of equivalent views to decrease
- */
- _decreaseFrequencyCap(url, amount) {
- let remainingViews = this._frequencyCaps.get(url) - amount;
- this._frequencyCaps.set(url, remainingViews);
-
- // Reached the number of views, so pick a new one.
- if (remainingViews <= 0) {
- this._updateSuggestedTile();
- }
- },
-
- /**
- * Chooses and returns a suggested tile based on a user's top sites
- * that we have an available suggested tile for.
- *
- * @return the chosen suggested tile, or undefined if there isn't one
- */
- _updateSuggestedTile: function() {
- let sortedLinks = NewTabUtils.getProviderLinks(this);
-
- if (!sortedLinks) {
- // If NewTabUtils.links.resetCache() is called before getting here,
- // sortedLinks may be undefined.
- return;
- }
-
- // Delete the current suggested tile, if one exists.
- let initialLength = sortedLinks.length;
- if (initialLength) {
- let mostFrecentLink = sortedLinks[0];
- if (mostFrecentLink.targetedSite) {
- this._callObservers("onLinkChanged", {
- url: mostFrecentLink.url,
- frecency: SUGGESTED_FRECENCY,
- lastVisitDate: mostFrecentLink.lastVisitDate,
- type: mostFrecentLink.type,
- }, 0, true);
- }
- }
-
- if (this._topSitesWithSuggestedLinks.size == 0) {
- // There are no potential suggested links we can show.
- return;
- }
-
- // Create a flat list of all possible links we can show as suggested.
- // Note that many top sites may map to the same suggested links, but we only
- // want to count each suggested link once (based on url), thus possibleLinks is a map
- // from url to suggestedLink. Thus, each link has an equal chance of being chosen at
- // random from flattenedLinks if it appears only once.
- let possibleLinks = new Map();
- let targetedSites = new Map();
- this._topSitesWithSuggestedLinks.forEach(topSiteWithSuggestedLink => {
- let suggestedLinksMap = this._suggestedLinks.get(topSiteWithSuggestedLink);
- suggestedLinksMap.forEach((suggestedLink, url) => {
- // Skip this link if we've shown it too many times already
- if (this._frequencyCaps.get(url) <= 0) {
- return;
- }
-
- possibleLinks.set(url, suggestedLink);
-
- // Keep a map of URL to targeted sites. We later use this to show the user
- // what site they visited to trigger this suggestion.
- if (!targetedSites.get(url)) {
- targetedSites.set(url, []);
- }
- targetedSites.get(url).push(topSiteWithSuggestedLink);
- })
- });
-
- // We might have run out of possible links to show
- let numLinks = possibleLinks.size;
- if (numLinks == 0) {
- return;
- }
-
- let flattenedLinks = [...possibleLinks.values()];
-
- // Choose our suggested link at random
- let suggestedIndex = Math.floor(Math.random() * numLinks);
- let chosenSuggestedLink = flattenedLinks[suggestedIndex];
-
- // Add the suggested link to the front with some extra values
- this._callObservers("onLinkChanged", Object.assign({
- frecency: SUGGESTED_FRECENCY,
-
- // Choose the first site a user has visited as the target. In the future,
- // this should be the site with the highest frecency. However, we currently
- // store frecency by URL not by site.
- targetedSite: targetedSites.get(chosenSuggestedLink.url).length ?
- targetedSites.get(chosenSuggestedLink.url)[0] : null
- }, chosenSuggestedLink));
- return chosenSuggestedLink;
- },
-
/**
* Return the object to its pre-init state
*/
reset: function DirectoryLinksProvider_reset() {
delete this.__linksURL;
this._removePrefsObserver();
this._removeObservers();
},
@@ -728,21 +443,21 @@ let DirectoryLinksProvider = {
addObserver: function DirectoryLinksProvider_addObserver(aObserver) {
this._observers.add(aObserver);
},
removeObserver: function DirectoryLinksProvider_removeObserver(aObserver) {
this._observers.delete(aObserver);
},
- _callObservers(methodName, ...args) {
+ _callObservers: function DirectoryLinksProvider__callObservers(aMethodName, aArg) {
for (let obs of this._observers) {
- if (typeof(obs[methodName]) == "function") {
+ if (typeof(obs[aMethodName]) == "function") {
try {
- obs[methodName](this, ...args);
+ obs[aMethodName](this, aArg);
} catch (err) {
Cu.reportError(err);
}
}
}
},
_removeObservers: function() {
--- a/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
+++ b/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
@@ -14,25 +14,22 @@ Cu.import("resource://gre/modules/Promis
Cu.import("resource://gre/modules/Http.jsm");
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
- "resource://gre/modules/NewTabUtils.jsm");
do_get_profile();
const DIRECTORY_LINKS_FILE = "directoryLinks.json";
const DIRECTORY_FRECENCY = 1000;
-const SUGGESTED_FRECENCY = Infinity;
-const kURLData = {"directory": [{"url":"http://example.com","title":"LocalSource"}]};
+const kURLData = {"en-US": [{"url":"http://example.com","title":"LocalSource"}]};
const kTestURL = 'data:application/json,' + JSON.stringify(kURLData);
// DirectoryLinksProvider preferences
const kLocalePref = DirectoryLinksProvider._observedPrefs.prefSelectedLocale;
const kSourceUrlPref = DirectoryLinksProvider._observedPrefs.linksURL;
const kPingUrlPref = "browser.newtabpage.directory.ping";
const kNewtabEnhancedPref = "browser.newtabpage.enhanced";
@@ -49,67 +46,23 @@ const kPingUrl = kBaseUrl + kPingPath;
// app/profile/firefox.js are not avaialble in xpcshell: hence, preset them
Services.prefs.setCharPref(kLocalePref, "en-US");
Services.prefs.setCharPref(kSourceUrlPref, kTestURL);
Services.prefs.setCharPref(kPingUrlPref, kPingUrl);
Services.prefs.setBoolPref(kNewtabEnhancedPref, true);
const kHttpHandlerData = {};
-kHttpHandlerData[kExamplePath] = {"directory": [{"url":"http://example.com","title":"RemoteSource"}]};
+kHttpHandlerData[kExamplePath] = {"en-US": [{"url":"http://example.com","title":"RemoteSource"}]};
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
let gLastRequestPath;
-
-let suggestedTile1 = {
- url: "http://turbotax.com",
- type: "affiliate",
- lastVisitDate: 4,
- frecent_sites: [
- "taxact.com",
- "hrblock.com",
- "1040.com",
- "taxslayer.com"
- ]
-};
-let suggestedTile2 = {
- url: "http://irs.gov",
- type: "affiliate",
- lastVisitDate: 3,
- frecent_sites: [
- "taxact.com",
- "hrblock.com",
- "freetaxusa.com",
- "taxslayer.com"
- ]
-};
-let suggestedTile3 = {
- url: "http://hrblock.com",
- type: "affiliate",
- lastVisitDate: 2,
- frecent_sites: [
- "taxact.com",
- "freetaxusa.com",
- "1040.com",
- "taxslayer.com"
- ]
-};
-let suggestedTile4 = {
- url: "http://sponsoredtile.com",
- type: "sponsored",
- lastVisitDate: 1,
- frecent_sites: [
- "sponsoredtarget.com"
- ]
-}
-let someOtherSite = {url: "http://someothersite.com", title: "Not_A_Suggested_Site"};
-
function getHttpHandler(path) {
let code = 200;
let body = JSON.stringify(kHttpHandlerData[path]);
if (path == kFailPath) {
code = 204;
}
return function(aRequest, aResponse) {
gLastRequestPath = aRequest.path;
@@ -203,441 +156,30 @@ function promiseCleanDirectoryLinksProvi
}
function run_test() {
// Set up a mock HTTP server to serve a directory page
server = new HttpServer();
server.registerPrefixHandler(kExamplePath, getHttpHandler(kExamplePath));
server.registerPrefixHandler(kFailPath, getHttpHandler(kFailPath));
server.start(kDefaultServerPort);
- NewTabUtils.init();
run_next_test();
// Teardown.
do_register_cleanup(function() {
server.stop(function() { });
DirectoryLinksProvider.reset();
Services.prefs.clearUserPref(kLocalePref);
Services.prefs.clearUserPref(kSourceUrlPref);
Services.prefs.clearUserPref(kPingUrlPref);
Services.prefs.clearUserPref(kNewtabEnhancedPref);
});
}
-add_task(function test_updateSuggestedTile() {
- let topSites = ["site0.com", "1040.com", "site2.com", "hrblock.com", "site4.com", "freetaxusa.com", "site6.com"];
-
- // Initial setup
- let data = {"suggested": [suggestedTile1, suggestedTile2, suggestedTile3], "directory": [someOtherSite]};
- let dataURI = 'data:application/json,' + JSON.stringify(data);
-
- let testObserver = new TestFirstRun();
- DirectoryLinksProvider.addObserver(testObserver);
-
- let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
- DirectoryLinksProvider.getFrecentSitesName = () => "";
-
- yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
- let links = yield fetchData();
-
- let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
- NewTabUtils.isTopPlacesSite = function(site) {
- return topSites.indexOf(site) >= 0;
- }
-
- let origGetProviderLinks = NewTabUtils.getProviderLinks;
- NewTabUtils.getProviderLinks = function(provider) {
- return links;
- }
-
- do_check_eq(DirectoryLinksProvider._updateSuggestedTile(), undefined);
-
- function TestFirstRun() {
- this.promise = new Promise(resolve => {
- this.onLinkChanged = (directoryLinksProvider, link) => {
- links.unshift(link);
- let possibleLinks = [suggestedTile1.url, suggestedTile2.url, suggestedTile3.url];
-
- isIdentical([...DirectoryLinksProvider._topSitesWithSuggestedLinks], ["hrblock.com", "1040.com", "freetaxusa.com"]);
- do_check_true(possibleLinks.indexOf(link.url) > -1);
- do_check_eq(link.frecency, SUGGESTED_FRECENCY);
- do_check_eq(link.type, "affiliate");
- resolve();
- };
- });
- }
-
- function TestChangingSuggestedTile() {
- this.count = 0;
- this.promise = new Promise(resolve => {
- this.onLinkChanged = (directoryLinksProvider, link) => {
- this.count++;
- let possibleLinks = [suggestedTile1.url, suggestedTile2.url, suggestedTile3.url];
-
- do_check_true(possibleLinks.indexOf(link.url) > -1);
- do_check_eq(link.type, "affiliate");
- do_check_true(this.count <= 2);
-
- if (this.count == 1) {
- // The removed suggested link is the one we added initially.
- do_check_eq(link.url, links.shift().url);
- do_check_eq(link.frecency, SUGGESTED_FRECENCY);
- } else {
- links.unshift(link);
- do_check_eq(link.frecency, SUGGESTED_FRECENCY);
- }
- isIdentical([...DirectoryLinksProvider._topSitesWithSuggestedLinks], ["hrblock.com", "freetaxusa.com"]);
- resolve();
- }
- });
- }
-
- function TestRemovingSuggestedTile() {
- this.count = 0;
- this.promise = new Promise(resolve => {
- this.onLinkChanged = (directoryLinksProvider, link) => {
- this.count++;
-
- do_check_eq(link.type, "affiliate");
- do_check_eq(this.count, 1);
- do_check_eq(link.frecency, SUGGESTED_FRECENCY);
- do_check_eq(link.url, links.shift().url);
- isIdentical([...DirectoryLinksProvider._topSitesWithSuggestedLinks], []);
- resolve();
- }
- });
- }
-
- // Test first call to '_updateSuggestedTile()', called when fetching directory links.
- yield testObserver.promise;
- DirectoryLinksProvider.removeObserver(testObserver);
-
- // Removing a top site that doesn't have a suggested link should
- // not change the current suggested tile.
- let removedTopsite = topSites.shift();
- do_check_eq(removedTopsite, "site0.com");
- do_check_false(NewTabUtils.isTopPlacesSite(removedTopsite));
- let updateSuggestedTile = DirectoryLinksProvider._handleLinkChanged({
- url: "http://" + removedTopsite,
- type: "history",
- });
- do_check_false(updateSuggestedTile);
-
- // Removing a top site that has a suggested link should
- // remove any current suggested tile and add a new one.
- testObserver = new TestChangingSuggestedTile();
- DirectoryLinksProvider.addObserver(testObserver);
- removedTopsite = topSites.shift();
- do_check_eq(removedTopsite, "1040.com");
- do_check_false(NewTabUtils.isTopPlacesSite(removedTopsite));
- DirectoryLinksProvider.onLinkChanged(DirectoryLinksProvider, {
- url: "http://" + removedTopsite,
- type: "history",
- });
- yield testObserver.promise;
- do_check_eq(testObserver.count, 2);
- DirectoryLinksProvider.removeObserver(testObserver);
-
- // Removing all top sites with suggested links should remove
- // the current suggested link and not replace it.
- topSites = [];
- testObserver = new TestRemovingSuggestedTile();
- DirectoryLinksProvider.addObserver(testObserver);
- DirectoryLinksProvider.onManyLinksChanged();
- yield testObserver.promise;
-
- // Cleanup
- yield promiseCleanDirectoryLinksProvider();
- DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
- NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
- NewTabUtils.getProviderLinks = origGetProviderLinks;
-});
-
-add_task(function test_suggestedLinksMap() {
- let data = {"suggested": [suggestedTile1, suggestedTile2, suggestedTile3, suggestedTile4], "directory": [someOtherSite]};
- let dataURI = 'data:application/json,' + JSON.stringify(data);
-
- yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
- let links = yield fetchData();
-
- // Ensure the suggested tiles were not considered directory tiles.
- do_check_eq(links.length, 1);
- let expected_data = [{url: "http://someothersite.com", title: "Not_A_Suggested_Site", frecency: DIRECTORY_FRECENCY, lastVisitDate: 1}];
- isIdentical(links, expected_data);
-
- // Check for correctly saved suggested tiles data.
- expected_data = {
- "taxact.com": [suggestedTile1, suggestedTile2, suggestedTile3],
- "hrblock.com": [suggestedTile1, suggestedTile2],
- "1040.com": [suggestedTile1, suggestedTile3],
- "taxslayer.com": [suggestedTile1, suggestedTile2, suggestedTile3],
- "freetaxusa.com": [suggestedTile2, suggestedTile3],
- };
- do_check_eq([...DirectoryLinksProvider._suggestedLinks.keys()].indexOf("sponsoredtarget.com"), -1);
-
- DirectoryLinksProvider._suggestedLinks.forEach((suggestedLinks, site) => {
- let suggestedLinksItr = suggestedLinks.values();
- for (let link of expected_data[site]) {
- isIdentical(suggestedLinksItr.next().value, link);
- }
- })
-
- yield promiseCleanDirectoryLinksProvider();
-});
-
-add_task(function test_topSitesWithSuggestedLinks() {
- let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
- DirectoryLinksProvider.getFrecentSitesName = () => "";
-
- let topSites = ["site0.com", "1040.com", "site2.com", "hrblock.com", "site4.com", "freetaxusa.com", "site6.com"];
- let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
- NewTabUtils.isTopPlacesSite = function(site) {
- return topSites.indexOf(site) >= 0;
- }
-
- // Mock out getProviderLinks() so we don't have to populate cache in NewTabUtils
- let origGetProviderLinks = NewTabUtils.getProviderLinks;
- NewTabUtils.getProviderLinks = function(provider) {
- return [];
- }
-
- // We start off with no top sites with suggested links.
- do_check_eq(DirectoryLinksProvider._topSitesWithSuggestedLinks.size, 0);
-
- let data = {"suggested": [suggestedTile1, suggestedTile2, suggestedTile3], "directory": [someOtherSite]};
- let dataURI = 'data:application/json,' + JSON.stringify(data);
-
- yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
- let links = yield fetchData();
-
- // Check we've populated suggested links as expected.
- do_check_eq(DirectoryLinksProvider._suggestedLinks.size, 5);
-
- // When many sites change, we update _topSitesWithSuggestedLinks as expected.
- let expectedTopSitesWithSuggestedLinks = ["hrblock.com", "1040.com", "freetaxusa.com"];
- DirectoryLinksProvider._handleManyLinksChanged();
- isIdentical([...DirectoryLinksProvider._topSitesWithSuggestedLinks], expectedTopSitesWithSuggestedLinks);
-
- // Removing site6.com as a topsite has no impact on _topSitesWithSuggestedLinks.
- let popped = topSites.pop();
- DirectoryLinksProvider._handleLinkChanged({url: "http://" + popped});
- isIdentical([...DirectoryLinksProvider._topSitesWithSuggestedLinks], expectedTopSitesWithSuggestedLinks);
-
- // Removing freetaxusa.com as a topsite will remove it from _topSitesWithSuggestedLinks.
- popped = topSites.pop();
- expectedTopSitesWithSuggestedLinks.pop();
- DirectoryLinksProvider._handleLinkChanged({url: "http://" + popped});
- isIdentical([...DirectoryLinksProvider._topSitesWithSuggestedLinks], expectedTopSitesWithSuggestedLinks);
-
- // Re-adding freetaxusa.com as a topsite will add it to _topSitesWithSuggestedLinks.
- topSites.push(popped);
- expectedTopSitesWithSuggestedLinks.push(popped);
- DirectoryLinksProvider._handleLinkChanged({url: "http://" + popped});
- isIdentical([...DirectoryLinksProvider._topSitesWithSuggestedLinks], expectedTopSitesWithSuggestedLinks);
-
- // Cleanup.
- DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
- NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
- NewTabUtils.getProviderLinks = origGetProviderLinks;
-});
-
-add_task(function test_suggestedAttributes() {
- let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
- NewTabUtils.isTopPlacesSite = () => true;
-
- let frecent_sites = "addons.mozilla.org,air.mozilla.org,blog.mozilla.org,bugzilla.mozilla.org,developer.mozilla.org,etherpad.mozilla.org,forums.mozillazine.org,hacks.mozilla.org,hg.mozilla.org,mozilla.org,planet.mozilla.org,quality.mozilla.org,support.mozilla.org,treeherder.mozilla.org,wiki.mozilla.org".split(",");
- let imageURI = "https://image/";
- let title = "the title";
- let type = "affiliate";
- let url = "http://test.url/";
- let data = {
- suggested: [{
- frecent_sites,
- imageURI,
- title,
- type,
- url
- }]
- };
- let dataURI = "data:application/json," + escape(JSON.stringify(data));
-
- yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
-
- // Wait for links to get loaded
- let gLinks = NewTabUtils.links;
- gLinks.addProvider(DirectoryLinksProvider);
- gLinks.populateCache();
- yield new Promise(resolve => {
- NewTabUtils.allPages.register({
- observe: _ => _,
- update() {
- NewTabUtils.allPages.unregister(this);
- resolve();
- }
- });
- });
-
- // Make sure we get the expected attributes on the suggested tile
- let link = gLinks.getLinks()[0];
- do_check_eq(link.imageURI, imageURI);
- do_check_eq(link.targetedName, "Mozilla");
- do_check_eq(link.targetedSite, frecent_sites[0]);
- do_check_eq(link.title, title);
- do_check_eq(link.type, type);
- do_check_eq(link.url, url);
-
- // Cleanup.
- NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
- gLinks.removeProvider(DirectoryLinksProvider);
- DirectoryLinksProvider.removeObserver(gLinks);
-});
-
-add_task(function test_frequencyCappedSites_views() {
- Services.prefs.setCharPref(kPingUrlPref, "");
- let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
- DirectoryLinksProvider.getFrecentSitesName = () => "";
- let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
- NewTabUtils.isTopPlacesSite = () => true;
-
- let testUrl = "http://frequency.capped/link";
- let targets = ["top.site.com"];
- let data = {
- suggested: [{
- type: "affiliate",
- frecent_sites: targets,
- url: testUrl
- }],
- directory: [{
- type: "organic",
- url: "http://directory.site/"
- }]
- };
- let dataURI = "data:application/json," + JSON.stringify(data);
-
- yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
-
- // Wait for links to get loaded
- let gLinks = NewTabUtils.links;
- gLinks.addProvider(DirectoryLinksProvider);
- gLinks.populateCache();
- yield new Promise(resolve => {
- NewTabUtils.allPages.register({
- observe: _ => _,
- update() {
- NewTabUtils.allPages.unregister(this);
- resolve();
- }
- });
- });
-
- function synthesizeAction(action) {
- DirectoryLinksProvider.reportSitesAction([{
- link: {
- targetedSite: targets[0],
- url: testUrl
- }
- }], action, 0);
- }
-
- function checkFirstTypeAndLength(type, length) {
- let links = gLinks.getLinks();
- do_check_eq(links[0].type, type);
- do_check_eq(links.length, length);
- }
-
- // Make sure we get 5 views of the link before it is removed
- checkFirstTypeAndLength("affiliate", 2);
- synthesizeAction("view");
- checkFirstTypeAndLength("affiliate", 2);
- synthesizeAction("view");
- checkFirstTypeAndLength("affiliate", 2);
- synthesizeAction("view");
- checkFirstTypeAndLength("affiliate", 2);
- synthesizeAction("view");
- checkFirstTypeAndLength("affiliate", 2);
- synthesizeAction("view");
- checkFirstTypeAndLength("organic", 1);
-
- // Cleanup.
- DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
- NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
- gLinks.removeProvider(DirectoryLinksProvider);
- DirectoryLinksProvider.removeObserver(gLinks);
- Services.prefs.setCharPref(kPingUrlPref, kPingUrl);
-});
-
-add_task(function test_frequencyCappedSites_click() {
- Services.prefs.setCharPref(kPingUrlPref, "");
- let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
- DirectoryLinksProvider.getFrecentSitesName = () => "";
- let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
- NewTabUtils.isTopPlacesSite = () => true;
-
- let testUrl = "http://frequency.capped/link";
- let targets = ["top.site.com"];
- let data = {
- suggested: [{
- type: "affiliate",
- frecent_sites: targets,
- url: testUrl
- }],
- directory: [{
- type: "organic",
- url: "http://directory.site/"
- }]
- };
- let dataURI = "data:application/json," + JSON.stringify(data);
-
- yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
-
- // Wait for links to get loaded
- let gLinks = NewTabUtils.links;
- gLinks.addProvider(DirectoryLinksProvider);
- gLinks.populateCache();
- yield new Promise(resolve => {
- NewTabUtils.allPages.register({
- observe: _ => _,
- update() {
- NewTabUtils.allPages.unregister(this);
- resolve();
- }
- });
- });
-
- function synthesizeAction(action) {
- DirectoryLinksProvider.reportSitesAction([{
- link: {
- targetedSite: targets[0],
- url: testUrl
- }
- }], action, 0);
- }
-
- function checkFirstTypeAndLength(type, length) {
- let links = gLinks.getLinks();
- do_check_eq(links[0].type, type);
- do_check_eq(links.length, length);
- }
-
- // Make sure the link disappears after the first click
- checkFirstTypeAndLength("affiliate", 2);
- synthesizeAction("view");
- checkFirstTypeAndLength("affiliate", 2);
- synthesizeAction("click");
- checkFirstTypeAndLength("organic", 1);
-
- // Cleanup.
- DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
- NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
- gLinks.removeProvider(DirectoryLinksProvider);
- DirectoryLinksProvider.removeObserver(gLinks);
- Services.prefs.setCharPref(kPingUrlPref, kPingUrl);
-});
-
add_task(function test_reportSitesAction() {
yield DirectoryLinksProvider.init();
let deferred, expectedPath, expectedPost;
let done = false;
server.registerPrefixHandler(kPingPath, (aRequest, aResponse) => {
if (done) {
return;
}
@@ -811,16 +353,49 @@ add_task(function test_DirectoryLinksPro
yield testObserver.deferred.promise;
DirectoryLinksProvider._removeObservers();
do_check_eq(DirectoryLinksProvider._observers.size, 0);
yield promiseCleanDirectoryLinksProvider();
});
+add_task(function test_linksURL_locale() {
+ let data = {
+ "en-US": [{url: "http://example.com", title: "US"}],
+ "zh-CN": [
+ {url: "http://example.net", title: "CN"},
+ {url:"http://example.net/2", title: "CN2"}
+ ],
+ };
+ let dataURI = 'data:application/json,' + JSON.stringify(data);
+
+ yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
+
+ let links;
+ let expected_data;
+
+ links = yield fetchData();
+ do_check_eq(links.length, 1);
+ expected_data = [{url: "http://example.com", title: "US", frecency: DIRECTORY_FRECENCY, lastVisitDate: 1}];
+ isIdentical(links, expected_data);
+
+ yield promiseDirectoryDownloadOnPrefChange("general.useragent.locale", "zh-CN");
+
+ links = yield fetchData();
+ do_check_eq(links.length, 2)
+ expected_data = [
+ {url: "http://example.net", title: "CN", frecency: DIRECTORY_FRECENCY, lastVisitDate: 2},
+ {url: "http://example.net/2", title: "CN2", frecency: DIRECTORY_FRECENCY, lastVisitDate: 1}
+ ];
+ isIdentical(links, expected_data);
+
+ yield promiseCleanDirectoryLinksProvider();
+});
+
add_task(function test_DirectoryLinksProvider__prefObserver_url() {
yield promiseSetupDirectoryLinksProvider({linksURL: kTestURL});
let links = yield fetchData();
do_check_eq(links.length, 1);
let expectedData = [{url: "http://example.com", title: "LocalSource", frecency: DIRECTORY_FRECENCY, lastVisitDate: 1}];
isIdentical(links, expectedData);
@@ -840,23 +415,18 @@ add_task(function test_DirectoryLinksPro
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, exampleUrl + " ");
// we now should see empty links
newLinks = yield fetchData();
isIdentical(newLinks, []);
yield promiseCleanDirectoryLinksProvider();
});
-add_task(function test_DirectoryLinksProvider_getLinks_noDirectoryData() {
- let data = {
- "directory": [],
- };
- let dataURI = 'data:application/json,' + JSON.stringify(data);
- yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
-
+add_task(function test_DirectoryLinksProvider_getLinks_noLocaleData() {
+ yield promiseSetupDirectoryLinksProvider({locale: 'zh-CN'});
let links = yield fetchData();
do_check_eq(links.length, 0);
yield promiseCleanDirectoryLinksProvider();
});
add_task(function test_DirectoryLinksProvider_getLinks_badData() {
let data = {
"en-US": {
@@ -982,89 +552,89 @@ add_task(function test_DirectoryLinksPro
yield OS.File.writeAtomic(directoryLinksFilePath, '{"en-US":');
let data = yield fetchData();
isIdentical(data, []);
yield promiseCleanDirectoryLinksProvider();
});
add_task(function test_DirectoryLinksProvider_getAllowedLinks() {
- let data = {"directory": [
+ let data = {"en-US": [
{url: "ftp://example.com"},
{url: "http://example.net"},
{url: "javascript:5"},
{url: "https://example.com"},
{url: "httpJUNKjavascript:42"},
{url: "data:text/plain,hi"},
{url: "http/bork:eh"},
]};
let dataURI = 'data:application/json,' + JSON.stringify(data);
yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
let links = yield fetchData();
do_check_eq(links.length, 2);
// The only remaining url should be http and https
- do_check_eq(links[0].url, data["directory"][1].url);
- do_check_eq(links[1].url, data["directory"][3].url);
+ do_check_eq(links[0].url, data["en-US"][1].url);
+ do_check_eq(links[1].url, data["en-US"][3].url);
});
add_task(function test_DirectoryLinksProvider_getAllowedImages() {
- let data = {"directory": [
+ let data = {"en-US": [
{url: "http://example.com", imageURI: "ftp://example.com"},
{url: "http://example.com", imageURI: "http://example.net"},
{url: "http://example.com", imageURI: "javascript:5"},
{url: "http://example.com", imageURI: "https://example.com"},
{url: "http://example.com", imageURI: "httpJUNKjavascript:42"},
{url: "http://example.com", imageURI: "data:text/plain,hi"},
{url: "http://example.com", imageURI: "http/bork:eh"},
]};
let dataURI = 'data:application/json,' + JSON.stringify(data);
yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
let links = yield fetchData();
do_check_eq(links.length, 2);
// The only remaining images should be https and data
- do_check_eq(links[0].imageURI, data["directory"][3].imageURI);
- do_check_eq(links[1].imageURI, data["directory"][5].imageURI);
+ do_check_eq(links[0].imageURI, data["en-US"][3].imageURI);
+ do_check_eq(links[1].imageURI, data["en-US"][5].imageURI);
});
add_task(function test_DirectoryLinksProvider_getAllowedEnhancedImages() {
- let data = {"directory": [
+ let data = {"en-US": [
{url: "http://example.com", enhancedImageURI: "ftp://example.com"},
{url: "http://example.com", enhancedImageURI: "http://example.net"},
{url: "http://example.com", enhancedImageURI: "javascript:5"},
{url: "http://example.com", enhancedImageURI: "https://example.com"},
{url: "http://example.com", enhancedImageURI: "httpJUNKjavascript:42"},
{url: "http://example.com", enhancedImageURI: "data:text/plain,hi"},
{url: "http://example.com", enhancedImageURI: "http/bork:eh"},
]};
let dataURI = 'data:application/json,' + JSON.stringify(data);
yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
let links = yield fetchData();
do_check_eq(links.length, 2);
// The only remaining enhancedImages should be http and https and data
- do_check_eq(links[0].enhancedImageURI, data["directory"][3].enhancedImageURI);
- do_check_eq(links[1].enhancedImageURI, data["directory"][5].enhancedImageURI);
+ do_check_eq(links[0].enhancedImageURI, data["en-US"][3].enhancedImageURI);
+ do_check_eq(links[1].enhancedImageURI, data["en-US"][5].enhancedImageURI);
});
add_task(function test_DirectoryLinksProvider_getEnhancedLink() {
- let data = {"enhanced": [
+ let data = {"en-US": [
{url: "http://example.net", enhancedImageURI: "data:,net1"},
{url: "http://example.com", enhancedImageURI: "data:,com1"},
{url: "http://example.com", enhancedImageURI: "data:,com2"},
]};
let dataURI = 'data:application/json,' + JSON.stringify(data);
yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
let links = yield fetchData();
- do_check_eq(links.length, 0); // There are no directory links.
+ do_check_eq(links.length, 3);
function checkEnhanced(url, image) {
let enhanced = DirectoryLinksProvider.getEnhancedLink({url: url});
do_check_eq(enhanced && enhanced.enhancedImageURI, image);
}
// Get the expected image for the same site
checkEnhanced("http://example.net/", "data:,net1");
@@ -1085,76 +655,27 @@ add_task(function test_DirectoryLinksPro
// Undefined for not enhanced
checkEnhanced("http://sub.example.net/", undefined);
checkEnhanced("http://example.org", undefined);
checkEnhanced("http://localhost", undefined);
checkEnhanced("http://127.0.0.1", undefined);
// Make sure old data is not cached
- data = {"enhanced": [
+ data = {"en-US": [
{url: "http://example.com", enhancedImageURI: "data:,fresh"},
]};
dataURI = 'data:application/json,' + JSON.stringify(data);
yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
links = yield fetchData();
- do_check_eq(links.length, 0); // There are no directory links.
+ do_check_eq(links.length, 1);
checkEnhanced("http://example.net", undefined);
checkEnhanced("http://example.com", "data:,fresh");
});
-add_task(function test_DirectoryLinksProvider_enhancedURIs() {
- let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
- DirectoryLinksProvider.getFrecentSitesName = () => "";
- let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
- NewTabUtils.isTopPlacesSite = () => true;
-
- let data = {
- "suggested": [
- {url: "http://example.net", enhancedImageURI: "data:,net1", title:"SuggestedTitle", frecent_sites: ["test.com"]}
- ],
- "directory": [
- {url: "http://example.net", enhancedImageURI: "data:,net2", title:"DirectoryTitle"}
- ]
- };
- let dataURI = 'data:application/json,' + JSON.stringify(data);
- yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
-
- // Wait for links to get loaded
- let gLinks = NewTabUtils.links;
- gLinks.addProvider(DirectoryLinksProvider);
- gLinks.populateCache();
- yield new Promise(resolve => {
- NewTabUtils.allPages.register({
- observe: _ => _,
- update() {
- NewTabUtils.allPages.unregister(this);
- resolve();
- }
- });
- });
-
- // Check that we've saved the directory tile.
- let links = yield fetchData();
- do_check_eq(links.length, 1);
- do_check_eq(links[0].title, "DirectoryTitle");
- do_check_eq(links[0].enhancedImageURI, "data:,net2");
-
- // Check that the suggested tile with the same URL replaces the directory tile.
- links = gLinks.getLinks();
- do_check_eq(links.length, 1);
- do_check_eq(links[0].title, "SuggestedTitle");
- do_check_eq(links[0].enhancedImageURI, "data:,net1");
-
- // Cleanup.
- DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
- NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
- gLinks.removeProvider(DirectoryLinksProvider);
-});
-
add_task(function test_DirectoryLinksProvider_setDefaultEnhanced() {
function checkDefault(expected) {
Services.prefs.clearUserPref(kNewtabEnhancedPref);
do_check_eq(Services.prefs.getBoolPref(kNewtabEnhancedPref), expected);
}
// Use the default donottrack prefs (enabled = false)
Services.prefs.clearUserPref("privacy.donottrackheader.enabled");