diff --git a/README.md b/README.md index 5ba1bc93781..28bd26d9d46 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ We encourage you to participate in this open source project. We love Pull Reques High-level components for building browser(-like) apps. +* **Domains** - Localized and customizable domain lists for auto-completion in browsers. + * **Engine** - An abstract layer hiding the actual browser engine implementation. * **Engine-Gecko** - *Engine* implementation based on [GeckoView](https://wiki.mozilla.org/Mobile/GeckoView). diff --git a/build.gradle b/build.gradle index 45db481652f..d15570176e0 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,8 @@ buildscript { // Synchronized version numbers for dependencies used by (some) modules ext.dependencies = [ kotlin: '1.2.30', - supportLibraries: '27.1.0', + coroutines: '0.19.3', + supportLibraries: '27.1.1', junit: '4.12', robolectric: '3.7.1', mockito: '2.12.0' diff --git a/components/browser/domains/build.gradle b/components/browser/domains/build.gradle new file mode 100644 index 00000000000..731c0f52c61 --- /dev/null +++ b/components/browser/domains/build.gradle @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion rootProject.ext.build['compileSdkVersion'] + + defaultConfig { + minSdkVersion rootProject.ext.build['minSdkVersion'] + targetSdkVersion rootProject.ext.build['targetSdkVersion'] + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + lintOptions { + warningsAsErrors true + abortOnError true + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + kotlin { + experimental { + coroutines 'enable' + } + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:${rootProject.ext.dependencies['kotlin']}" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${rootProject.ext.dependencies['coroutines']}" + + testImplementation "junit:junit:${rootProject.ext.dependencies['junit']}" + testImplementation "org.robolectric:robolectric:${rootProject.ext.dependencies['robolectric']}" + testImplementation "org.mockito:mockito-core:${rootProject.ext.dependencies['mockito']}" +} + +archivesBaseName = "domains" + +apply from: '../../../publish.gradle' +ext.configurePublish( + 'org.mozilla.components', + 'domains', + 'Localized and customizable domain lists for auto-completion in browsers.') diff --git a/components/browser/domains/proguard-rules.pro b/components/browser/domains/proguard-rules.pro new file mode 100644 index 00000000000..f1b424510da --- /dev/null +++ b/components/browser/domains/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/components/browser/domains/src/main/AndroidManifest.xml b/components/browser/domains/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..20c8127b0a8 --- /dev/null +++ b/components/browser/domains/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + diff --git a/components/browser/domains/src/main/assets/domains/br b/components/browser/domains/src/main/assets/domains/br new file mode 100644 index 00000000000..3a7cd23b122 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/br @@ -0,0 +1,50 @@ +google.com.br +youtube.com +google.com +facebook.com +globo.com +uol.com.br +blastingnews.com +live.com +mercadolivre.com.br +yahoo.com +blogspot.com.br +wikipedia.org +whatsapp.com +netflix.com +olx.com.br +instagram.com +msn.com +metropoles.com +fatosdesconhecidos.com.br +twitter.com +caixa.gov.br +uptodown.com +aliexpress.com +curapelanatureza.com.br +wordpress.com +abril.com.br +americanas.com.br +correios.com.br +reclameaqui.com.br +bet365.com +onclkds.com +bol.uol.com.br +techtudo.com.br +fazenda.gov.br +microsoft.com +folha.uol.com.br +linkedin.com +tumblr.com +sp.gov.br +reddit.com +bb.com.br +pinterest.com +itau.com.br +letras.mus.br +otvfoco.com.br +vagalume.com.br +portalinteressante.com +myappolicious.com.br +thewhizmarketing.com +twitch.tv diff --git a/components/browser/domains/src/main/assets/domains/ca b/components/browser/domains/src/main/assets/domains/ca new file mode 100644 index 00000000000..692cd1af6b8 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/ca @@ -0,0 +1,50 @@ +google.com +youtube.com +facebook.com +reddit.com +amazon.com +wikipedia.org +yahoo.com +twitter.com +netflix.com +ebay.com +imgur.com +linkedin.com +instagram.com +diply.com +craigslist.org +live.com +office.com +microsoftonline.com +twitch.tv +tumblr.com +pinterest.com +espn.com +cnn.com +bing.com +wikia.com +chase.com +imdb.com +nytimes.com +paypal.com +blogspot.com +apple.com +yelp.com +stackoverflow.com +bankofamerica.com +wordpress.com +github.com +microsoft.com +wellsfargo.com +zillow.com +salesforce.com +msn.com +walmart.com +weather.com +dropbox.com +buzzfeed.com +intuit.com +washingtonpost.com +soundcloud.com +huffingtonpost.com +indeed.com \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/de b/components/browser/domains/src/main/assets/domains/de new file mode 100644 index 00000000000..8bd37b76065 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/de @@ -0,0 +1,50 @@ +google.de +youtube.com +google.com +facebook.com +amazon.de +ebay.de +wikipedia.org +ebay-kleinanzeigen.de +web.de +yahoo.com +ok.ru +gmx.net +reddit.com +vk.com +t-online.de +twitter.com +spiegel.de +mail.ru +instagram.com +live.com +chip.de +bild.de +paypal.com +bing.com +twitch.tv +whatsapp.com +yandex.ru +gutefrage.net +mobile.de +google.ru +blogspot.de +tumblr.com +bs.to +focus.de +linkedin.com +netflix.com +wordpress.com +imgur.com +postbank.de +welt.de +streamcloud.eu +microsoft.com +immobilienscout24.de +msn.com +dict.cc +otto.de +xing.com +amazon.com +heise.de +github.com \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/fr b/components/browser/domains/src/main/assets/domains/fr new file mode 100644 index 00000000000..d5829421135 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/fr @@ -0,0 +1,50 @@ +google.fr +youtube.com +google.com +facebook.com +wikipedia.org +amazon.fr +leboncoin.fr +yahoo.com +live.com +twitter.com +orange.fr +free.fr +linkedin.com +lemonde.fr +instagram.com +reddit.com +lefigaro.fr +ebay.fr +cdiscount.com +jeuxvideo.com +zone-telechargement.ws +labanquepostale.fr +blogspot.fr +allocine.fr +msn.com +commentcamarche.net +pole-emploi.fr +vk.com +sfr.fr +lequipe.fr +twitch.tv +francetvinfo.fr +20minutes.fr +pinterest.com +netflix.com +programme-tv.net +credit-agricole.fr +linternaute.com +github.com +wordpress.com +caf.fr +aliexpress.com +dailymotion.com +tumblr.com +t411.ai +stackoverflow.com +microsoft.com +meteofrance.com +onclkds.com +bfmtv.com \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/gb b/components/browser/domains/src/main/assets/domains/gb new file mode 100644 index 00000000000..8bc91c28255 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/gb @@ -0,0 +1,50 @@ +google.co.uk +youtube.com +google.com +facebook.com +reddit.com +bbc.co.uk +amazon.co.uk +wikipedia.org +ebay.co.uk +twitter.com +live.com +yahoo.com +instagram.com +diply.com +linkedin.com +imgur.com +netflix.com +theguardian.com +dailymail.co.uk +twitch.tv +imdb.com +paypal.com +microsoftonline.com +office.com +tumblr.com +www.gov.uk +wikia.com +givemesport.com +amazon.com +bing.com +wordpress.com +telegraph.co.uk +rightmove.co.uk +pinterest.com +gumtree.com +msn.com +microsoft.com +stackoverflow.com +booking.com +vk.com +tripadvisor.co.uk +lloydsbank.co.uk +apple.com +service.gov.uk +onclkds.com +github.com +independent.co.uk +bt.com +vice.com +hsbc.co.uk \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/global b/components/browser/domains/src/main/assets/domains/global new file mode 100644 index 00000000000..1d142937dfd --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/global @@ -0,0 +1,454 @@ +google.com +facebook.com +amazon.com +youtube.com +yahoo.com +ebay.com +wikipedia.org +twitter.com +reddit.com +go.com +craigslist.org +live.com +netflix.com +pinterest.com +bing.com +linkedin.com +imgur.com +espn.go.com +walmart.com +tumblr.com +target.com +paypal.com +cnn.com +chase.com +instagram.com +bestbuy.com +blogspot.com +nytimes.com +msn.com +imdb.com +apple.com +bankofamerica.com +diply.com +huffingtonpost.com +yelp.com +wellsfargo.com +etsy.com +weather.com +wordpress.com +buzzfeed.com +zillow.com +kohls.com +aol.com +homedepot.com +foxnews.com +microsoft.com +comcast.net +wikia.com +groupon.com +macys.com +washingtonpost.com +outbrain.com +microsoftonline.com +xfinity.com +usps.com +hulu.com +americanexpress.com +slickdeals.net +pandora.com +office.com +cnet.com +indeed.com +capitalone.com +nfl.com +ups.com +ask.com +verizonwireless.com +newegg.com +usatoday.com +forbes.com +dailymail.co.uk +dropbox.com +att.com +costco.com +gfycat.com +lowes.com +gap.com +about.com +tripadvisor.com +fedex.com +baidu.com +vice.com +nordstrom.com +adobe.com +bbc.com +twitch.tv +allrecipes.com +retailmenot.com +stackoverflow.com +citi.com +sears.com +jcpenney.com +webmd.com +ijreview.com +nih.gov +answers.com +foodnetwork.com +discovercard.com +cbssports.com +overstock.com +businessinsider.com +office365.com +theguardian.com +staples.com +bleacherreport.com +toysrus.com +verizon.com +github.com +wayfair.com +salesforce.com +zulily.com +wsj.com +flickr.com +goodreads.com +realtor.com +nbcnews.com +ebates.com +ancestry.com +wunderground.com +instructure.com +people.com +stackexchange.com +drudgereport.com +fidelity.com +southwest.com +deviantart.com +thesaurus.com +intuit.com +woot.com +pch.com +soundcloud.com +force.com +samsclub.com +ign.com +qvc.com +npr.org +patch.com +dell.com +accuweather.com +vimeo.com +expedia.com +trulia.com +ca.gov +swagbucks.com +spotify.com +bedbathandbeyond.com +nypost.com +aliexpress.com +blackboard.com +ticketmaster.com +ikea.com +feedly.com +usaa.com +tmz.com +quora.com +lifehacker.com +kayak.com +reference.com +zappos.com +gizmodo.com +slate.com +faithtap.com +adp.com +abcnews.go.com +sephora.com +cbs.com +latimes.com +shutterfly.com +t-mobile.com +littlethings.com +glassdoor.com +bloomberg.com +cbsnews.com +wikihow.com +walgreens.com +usbank.com +blogger.com +weebly.com +gamestop.com +food.com +time.com +kickstarter.com +okcupid.com +aa.com +weather.gov +nametests.com +fandango.com +engadget.com +steamcommunity.com +thekitchn.com +nba.com +mashable.com +hp.com +gamefaqs.com +delta.com +coupons.com +eonline.com +surveymonkey.com +kmart.com +barnesandnoble.com +meetup.com +bhphotovideo.com +fanduel.com +quizlet.com +nydailynews.com +sbnation.com +nbcsports.com +likes.com +bbc.co.uk +ew.com +nike.com +rottentomatoes.com +steampowered.com +reuters.com +qq.com +today.com +mapquest.com +audible.com +priceline.com +whitepages.com +united.com +myfitnesspal.com +icloud.com +forever21.com +theatlantic.com +microsoftstore.com +theverge.com +gawker.com +houzz.com +mayoclinic.org +rei.com +sfgate.com +lifebuzz.com +discover.com +pnc.com +pof.com +iflscience.com +popsugar.com +creditkarma.com +telegraph.co.uk +airbnb.com +buzzlie.com +cnbc.com +deadspin.com +sina.com.cn +legacy.com +thedailybeast.com +samsung.com +nextdoor.com +evite.com +shopify.com +yellowpages.com +pcmag.com +redfin.com +emgn.com +weibo.com +alibaba.com +cabelas.com +battle.net +foxsports.com +taobao.com +eventbrite.com +victoriassecret.com +theblaze.com +dealnews.com +cbslocal.com +cvs.com +dailymotion.com +ecollege.com +gofundme.com +fitbit.com +instructables.com +godaddy.com +babycenter.com +squarespace.com +llbean.com +dickssportinggoods.com +6pm.com +myway.com +hsn.com +wired.com +officedepot.com +ozztube.com +usmagazine.com +match.com +cracked.com +evernote.com +box.com +starbucks.com +kbb.com +mlb.com +marriott.com +si.com +jezebel.com +pbs.org +consumerreports.org +roblox.com +urbandictionary.com +kotaku.com +xbox.com +marketwatch.com +refinery29.com +wikimedia.org +tvguide.com +politico.com +barclaycardus.com +abc.go.com +mint.com +topix.com +theblackfriday.com +aarp.org +hotnewhiphop.com +yourdailydish.com +sprint.com +vox.com +cafemom.com +nbc.com +dailykos.com +azlyrics.com +autotrader.com +hilton.com +irs.gov +monster.com +fatwallet.com +mailchimp.com +webex.com +landsend.com +wix.com +usnews.com +jcrew.com +jet.com +capitalone360.com +sharepoint.com +schwab.com +ulta.com +vistaprint.com +rollingstone.com +biblegateway.com +gamespot.com +io9.com +opentable.com +hm.com +duckduckgo.com +chron.com +photobucket.com +shareasale.com +directv.com +avg.com +oracle.com +hotels.com +timewarnercable.com +chicagotribune.com +ehow.com +primewire.ag +abs-cbnnews.com +salon.com +greatergood.com +epicurious.com +fool.com +patheos.com +custhelp.com +purdue.edu +tickld.com +frys.com +indiatimes.com +amazon.co.uk +zendesk.com +tigerdirect.com +stubhub.com +healthcare.gov +archive.org +qualtrics.com +ravelry.com +cars.com +redbox.com +jalopnik.com +speedtest.net +harvard.edu +slideshare.net +kinja.com +nesn.com +michaels.com +mit.edu +bodybuilding.com +edmunds.com +nhl.com +zergnet.com +terraclicks.com +techcrunch.com +regnok.com +pogo.com +backpage.com +mozilla.org +naver.com +giphy.com +bankrate.com +msnbc.com +digitaltrends.com +fanfiction.net +skype.com +disney.go.com +norton.com +androidcentral.com +tomshardware.com +thefreedictionary.com +liveleak.com +247sports.com +merriam-webster.com +wnd.com +earthlink.net +conservativetribune.com +independent.co.uk +drugs.com +rotoworld.com +nationalgeographic.com +ae.com +noaa.gov +arstechnica.com +thinkgeek.com +stanford.edu +bizjournals.com +hootsuite.com +genius.com +goodhousekeeping.com +vanguard.com +ny.gov +citibankonline.com +booking.com +mic.com +orbitz.com +dominos.com +medium.com +wow.com +urbanoutfitters.com +douban.com +timeanddate.com +draftkings.com +livestrong.com +livingsocial.com +cox.net +theonion.com +marthastewart.com +comenity.net +worldlifestyle.com +disney.com +realsimple.com +vrbo.com +playstation.com +potterybarn.com +zazzle.com +ksl.com +tdbank.com +sourceforge.net +careerbuilder.com diff --git a/components/browser/domains/src/main/assets/domains/hk b/components/browser/domains/src/main/assets/domains/hk new file mode 100644 index 00000000000..73513d54d0a --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/hk @@ -0,0 +1,50 @@ +google.com.hk +youtube.com +google.com +facebook.com +yahoo.com +discuss.com.hk +aastocks.com +wikipedia.org +baidu.com +taobao.com +pixnet.net +bastillepost.com +nextmedia.com +whatsapp.com +instagram.com +price.com.hk +ettoday.net +qq.com +hsbc.com.hk +tmall.com +live.com +hkgolden.com +reddit.com +beautyexchange.com.hk +etnet.com.hk +on.cc +amazon.com +twitter.com +uwants.com +presslogic.com +unwire.hk +gamer.com.tw +hangseng.com +hk01.com +twitch.tv +linkedin.com +teepr.com +hkjc.com +apple.com +bomb01.com +sina.com.cn +weibo.com +dcfever.com +thestandnews.com +office.com +openrice.com +tumblr.com +tvb.com +alipay.com +stackoverflow.com \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/id b/components/browser/domains/src/main/assets/domains/id new file mode 100644 index 00000000000..6d59c970228 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/id @@ -0,0 +1,50 @@ +google.com +google.co.id +youtube.com +detik.com +tribunnews.com +facebook.com +yahoo.com +tokopedia.com +liputan6.com +kompas.com +bukalapak.com +kaskus.co.id +kapanlagi.com +wordpress.com +merdeka.com +okezone.com +elevenia.co.id +lazada.co.id +uzone.id +bintang.com +brilio.net +popads.net +instagram.com +bola.net +wikipedia.org +blogspot.com +onclkds.com +dream.co.id +viva.co.id +alodokter.com +tempo.co +suara.com +wowkeren.com +idntimes.com +bola.com +sindonews.com +republika.co.id +kompasiana.com +vemale.com +blanja.com +cnnindonesia.com +olx.co.id +lk21.org +popcash.net +blibli.com +poptm.com +nonton.movie +indexmovie.me +adexchangeprediction.com +subscene.com \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/in b/components/browser/domains/src/main/assets/domains/in new file mode 100644 index 00000000000..e69de29bb2d diff --git a/components/browser/domains/src/main/assets/domains/pl b/components/browser/domains/src/main/assets/domains/pl new file mode 100644 index 00000000000..bef0c8cf34a --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/pl @@ -0,0 +1,50 @@ +google.pl +youtube.com +facebook.com +google.com +allegro.pl +onet.pl +wp.pl +wikipedia.org +olx.pl +vk.com +interia.pl +wykop.pl +gazeta.pl +filmweb.pl +instagram.com +wiocha.pl +cda.pl +aliexpress.com +otomoto.pl +mbank.pl +reddit.com +ceneo.pl +tvn24.pl +twitter.com +gumtree.pl +blogspot.com +kwejk.pl +wyborcza.pl +joemonster.org +stackoverflow.com +twitch.tv +o2.pl +ipko.pl +steamcommunity.com +github.com +chomikuj.pl +centrum24.pl +linkedin.com +money.pl +librus.pl +demotywatory.pl +sport.pl +microsoft.com +zalukaj.com +wikia.com +jbzdy.pl +imgur.com +flashscore.pl +gry-online.pl +pudelek.pl \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/ru b/components/browser/domains/src/main/assets/domains/ru new file mode 100644 index 00000000000..26eefe027dc --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/ru @@ -0,0 +1,50 @@ +vk.com +google.ru +yandex.ru +youtube.com +mail.ru +ok.ru +google.com +avito.ru +aliexpress.com +wikipedia.org +instagram.com +sberbank.ru +gismeteo.ru +rambler.ru +kinogo.club +kinopoisk.ru +drom.ru +facebook.com +pikabu.ru +drive2.ru +rutracker.org +twitch.tv +rbc.ru +hh.ru +gosuslugi.ru +lenta.ru +pochta.ru +wildberries.ru +wikia.com +4pda.ru +fb.ru +seasonvar.ru +kp.ru +znanija.com +ucoz.ru +narod.ru +mts.ru +infourok.ru +ebay.com +ozon.ru +worldoftanks.ru +mos.ru +vesti.ru +nnmclub.to +microsoft.com +rp5.ru +2gis.ru +consultant.ru +fotostrana.ru +dnevnik.ru \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/sg b/components/browser/domains/src/main/assets/domains/sg new file mode 100644 index 00000000000..1d641563645 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/sg @@ -0,0 +1,50 @@ +google.com.sg +youtube.com +google.com +facebook.com +yahoo.com +wikipedia.org +reddit.com +blogspot.sg +live.com +instagram.com +qoo10.sg +whatsapp.com +linkedin.com +dbs.com.sg +amazon.com +twitter.com +wordpress.com +onclkds.com +office.com +allsingaporestuff.com +baidu.com +lazada.sg +straitstimes.com +singpass.gov.sg +google.co.id +microsoftonline.com +taobao.com +tumblr.com +gomovies.to +wikia.com +hardwarezone.com.sg +nus.edu.sg +msn.com +microsoft.com +carousell.com +kissanime.ru +ocbc.com +stackoverflow.com +ntu.edu.sg +thepiratebay.org +aliexpress.com +imgur.com +dropbox.com +apple.com +channelnewsasia.com +imdb.com +twitch.tv +abs-cbn.com +jobstreet.com.sg +uob.com.sg \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/tw b/components/browser/domains/src/main/assets/domains/tw new file mode 100644 index 00000000000..5651311cac9 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/tw @@ -0,0 +1,50 @@ +google.com.tw +pixnet.net +youtube.com +facebook.com +ettoday.net +google.com +yahoo.com +ltn.com.tw +nownews.com +setn.com +momoshop.com.tw +wikipedia.org +ck101.com +ptt.cc +tvbs.com.tw +104.com.tw +gamer.com.tw +appledaily.com.tw +pchome.com.tw +ruten.com.tw +ctitv.com.tw +teepr.com +life.tw +blogspot.tw +dcard.tw +baidu.com +udn.com +mobile01.com +eyny.com +epochtimes.com +qoolquiz.com +bomb01.com +talk.tw +ipetgroup.com +storm.mg +123kubo.com +cmoney.tw +taobao.com +twitch.tv +instagram.com +xuite.net +sina.com.tw +1111.com.tw +businessweekly.com.tw +elle.com.tw +twitter.com +books.com.tw +591.com.tw +everydayhealth.com.tw +techbang.com \ No newline at end of file diff --git a/components/browser/domains/src/main/assets/domains/us b/components/browser/domains/src/main/assets/domains/us new file mode 100644 index 00000000000..692cd1af6b8 --- /dev/null +++ b/components/browser/domains/src/main/assets/domains/us @@ -0,0 +1,50 @@ +google.com +youtube.com +facebook.com +reddit.com +amazon.com +wikipedia.org +yahoo.com +twitter.com +netflix.com +ebay.com +imgur.com +linkedin.com +instagram.com +diply.com +craigslist.org +live.com +office.com +microsoftonline.com +twitch.tv +tumblr.com +pinterest.com +espn.com +cnn.com +bing.com +wikia.com +chase.com +imdb.com +nytimes.com +paypal.com +blogspot.com +apple.com +yelp.com +stackoverflow.com +bankofamerica.com +wordpress.com +github.com +microsoft.com +wellsfargo.com +zillow.com +salesforce.com +msn.com +walmart.com +weather.com +dropbox.com +buzzfeed.com +intuit.com +washingtonpost.com +soundcloud.com +huffingtonpost.com +indeed.com \ No newline at end of file diff --git a/components/browser/domains/src/main/java/mozilla/components/domains/CustomDomains.kt b/components/browser/domains/src/main/java/mozilla/components/domains/CustomDomains.kt new file mode 100644 index 00000000000..4d3d42870d0 --- /dev/null +++ b/components/browser/domains/src/main/java/mozilla/components/domains/CustomDomains.kt @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.domains + +import android.content.Context +import android.content.SharedPreferences + +/** + * Contains functionality to manage custom domains for auto-completion. + */ +object CustomDomains { + private const val PREFERENCE_NAME = "custom_autocomplete" + private const val KEY_DOMAINS = "custom_domains" + private const val SEPARATOR = "@<;>@" + + /** + * Loads the previously added/saved custom domains from preferences. + * + * @param context the application context + * @return list of custom domains + */ + suspend fun load(context: Context): List = + preferences(context).getString(KEY_DOMAINS, "") + .split(SEPARATOR) + .filter { !it.isEmpty() } + + /** + * Saves the provided domains to preferences. + * + * @param context the application context + * @param domains list of domains + */ + fun save(context: Context, domains: List) { + preferences(context) + .edit() + .putString(KEY_DOMAINS, domains.joinToString(separator = SEPARATOR)) + .apply() + } + + /** + * Adds the provided domain to preferences. + * + * @param context the application context + * @param domain the domain to add + */ + suspend fun add(context: Context, domain: String) { + val domains = mutableListOf() + domains.addAll(load(context)) + domains.add(domain) + + save(context, domains) + } + + /** + * Removes the provided domain from preferences. + * + * @param context the application context + * @param domains the domain to remove + */ + suspend fun remove(context: Context, domains: List) { + save(context, load(context) - domains) + } + + private fun preferences(context: Context): SharedPreferences = + context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE) +} diff --git a/components/browser/domains/src/main/java/mozilla/components/domains/DomainAutoCompleteProvider.kt b/components/browser/domains/src/main/java/mozilla/components/domains/DomainAutoCompleteProvider.kt new file mode 100644 index 00000000000..5a977743b5c --- /dev/null +++ b/components/browser/domains/src/main/java/mozilla/components/domains/DomainAutoCompleteProvider.kt @@ -0,0 +1,128 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.domains + +import android.content.Context +import kotlinx.coroutines.experimental.CommonPool +import kotlinx.coroutines.experimental.android.UI +import kotlinx.coroutines.experimental.async +import kotlinx.coroutines.experimental.launch +import java.util.Locale + +typealias ResultCallback = (String, String, Int) -> Unit + +/** + * Provides autocomplete functionality for domains, based on a provided list + * of assets (see @{link Domains}) and/or a custom domain list managed + * by {@link CustomDomains}. + */ +class DomainAutoCompleteProvider { + object AutocompleteSource { + const val DEFAULT_LIST = "default" + const val CUSTOM_LIST = "custom" + } + + private var customDomains = emptyList() + private var shippedDomains = emptyList() + private var useCustomDomains = false + private var useShippedDomains = true + + /** + * Computes an autocomplete suggestion for the given text, and invokes the + * provided callback, passing the result. + * + * @param rawText text to be auto completed + * @param resultCallback callback to be invoked with the autocomplete + * result. The callback is passed the auto completed text, the source + * identifier ({@link AutocompleteSource}) and the total number of + * possible results. + */ + fun autocomplete(rawText: String, resultCallback: ResultCallback) { + // Search terms are all lowercase already, we just need to lowercase the search text + val searchText = rawText.toLowerCase(Locale.US) + + if (useCustomDomains) { + val autocomplete = tryToAutocomplete(searchText, customDomains) + if (autocomplete != null) { + val resultText = getResultText(rawText, autocomplete) + resultCallback(resultText, AutocompleteSource.CUSTOM_LIST, customDomains.size) + return + } + } + + if (useShippedDomains) { + val autocomplete = tryToAutocomplete(searchText, shippedDomains) + if (autocomplete != null) { + val resultText = getResultText(rawText, autocomplete) + resultCallback(resultText, AutocompleteSource.DEFAULT_LIST, shippedDomains.size) + return + } + } + + resultCallback("", "", 0) + } + + /** + * Initializes this provider instance by making sure the shipped and/or custom + * domains are loaded. + * + * @param context the application context + * @param useShippedDomains true (default) if the domains provided by this + * module should be used, otherwise false. + * @param useCustomDomains true if the custom domains provided by + * {@see CustomDomains} should be used, otherwise false (default). + * @param loadDomainsFromDisk true (default) if domains should be loaded, + * otherwise false. This parameter is for testing purposes only. + */ + fun initialize( + context: Context, + useShippedDomains: Boolean = true, + useCustomDomains: Boolean = false, + loadDomainsFromDisk: Boolean = true + ) { + this.useCustomDomains = useCustomDomains + this.useShippedDomains = useShippedDomains + + if (loadDomainsFromDisk) { + launch(UI) { + val domains = async(CommonPool) { Domains.load(context) } + val customDomains = async(CommonPool) { CustomDomains.load(context) } + + onDomainsLoaded(domains.await(), customDomains.await()) + } + } + } + + internal fun onDomainsLoaded(domains: List, customDomains: List) { + this.shippedDomains = domains + this.customDomains = customDomains + } + + @Suppress("ReturnCount") + private fun tryToAutocomplete(searchText: String, domains: List): String? { + domains.forEach { + val wwwDomain = "www.$it" + if (wwwDomain.startsWith(searchText)) { + return wwwDomain + } + + if (it.startsWith(searchText)) { + return it + } + } + + return null + } + + /** + * Our autocomplete list is all lower case, however the search text might + * be mixed case. Our autocomplete EditText code does more string comparison, + * which fails if the suggestion doesn't exactly match searchText (ie. + * if casing differs). It's simplest to just build a suggestion + * that exactly matches the search text - which is what this method is for: + */ + private fun getResultText(rawSearchText: String, autocomplete: String) = + rawSearchText + autocomplete.substring(rawSearchText.length) +} diff --git a/components/browser/domains/src/main/java/mozilla/components/domains/Domains.kt b/components/browser/domains/src/main/java/mozilla/components/domains/Domains.kt new file mode 100644 index 00000000000..d5ba85404ee --- /dev/null +++ b/components/browser/domains/src/main/java/mozilla/components/domains/Domains.kt @@ -0,0 +1,82 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.domains + +import android.content.Context +import android.os.LocaleList +import android.text.TextUtils +import java.io.IOException +import java.util.Locale + +/** + * Contains functionality to access domain lists shipped as part of this + * module's assets. + */ +object Domains { + + /** + * Loads the domains applicable to the app's locale, plus the domains + * in the 'global' list. + * + * @param context the application context + * @return list of domains + */ + suspend fun load(context: Context): List { + return load(context, getCountriesInDefaultLocaleList()) + } + + internal suspend fun load(context: Context, countries: Set): List { + val domains = LinkedHashSet() + val availableLists = getAvailableDomainLists(context) + + // First initialize the country specific lists following the default locale order + countries + .filter { availableLists.contains(it) } + .forEach { loadDomainsForLanguage(context, domains, it) } + + // And then add domains from the global list + loadDomainsForLanguage(context, domains, "global") + + return domains.toList() + } + + private fun getAvailableDomainLists(context: Context): Set { + val availableDomains = LinkedHashSet() + val assetManager = context.assets + val domains = try { + assetManager.list("domains") + } catch (e: IOException) { + arrayOf() + } + availableDomains.addAll(domains) + return availableDomains + } + + private fun loadDomainsForLanguage(context: Context, domains: MutableSet, country: String) { + val assetManager = context.assets + val languageDomains = try { + assetManager.open("domains/" + country).bufferedReader().readLines() + } catch (e: IOException) { + emptyList() + } + domains.addAll(languageDomains) + } + + private fun getCountriesInDefaultLocaleList(): Set { + val countries = java.util.LinkedHashSet() + val addIfNotEmpty = { c: String -> if (!TextUtils.isEmpty(c)) countries.add(c.toLowerCase(Locale.US)) } + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + val list = LocaleList.getDefault() + for (i in 0 until list.size()) { + addIfNotEmpty(list.get(i).country) + } + } else { + addIfNotEmpty(Locale.getDefault().country) + } + + return countries + } +} diff --git a/components/browser/domains/src/test/java/mozilla/components/domains/CustomDomainsTest.kt b/components/browser/domains/src/test/java/mozilla/components/domains/CustomDomainsTest.kt new file mode 100644 index 00000000000..67d519eb8d0 --- /dev/null +++ b/components/browser/domains/src/test/java/mozilla/components/domains/CustomDomainsTest.kt @@ -0,0 +1,76 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.domains + +import android.content.Context +import kotlinx.coroutines.experimental.runBlocking +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment + +@RunWith(RobolectricTestRunner::class) +class CustomDomainsTest { + @Before + fun setUp() { + RuntimeEnvironment.application + .getSharedPreferences("custom_autocomplete", Context.MODE_PRIVATE) + .edit() + .clear() + .apply() + } + + @Test + fun testCustomListIsEmptyByDefault() { + val domains = runBlocking { + CustomDomains.load(RuntimeEnvironment.application) + } + + assertEquals(0, domains.size) + } + + @Test + fun testSaveAndRemoveDomains() = runBlocking { + CustomDomains.save(RuntimeEnvironment.application, listOf( + "mozilla.org", + "example.org", + "example.com" + )) + + var domains = CustomDomains.load(RuntimeEnvironment.application) + assertEquals(3, domains.size) + + CustomDomains.remove(RuntimeEnvironment.application, listOf("example.org", "example.com")) + domains = CustomDomains.load(RuntimeEnvironment.application) + assertEquals(1, domains.size) + assertEquals("mozilla.org", domains.elementAt(0)) + } + + @Test + fun testAddAndLoadDomains() = runBlocking { + CustomDomains.add(RuntimeEnvironment.application, "mozilla.org") + val domains = CustomDomains.load(RuntimeEnvironment.application) + assertEquals(1, domains.size) + assertEquals("mozilla.org", domains.elementAt(0)) + } + + @Test + fun testSaveAndLoadDomains() = runBlocking { + CustomDomains.save(RuntimeEnvironment.application, listOf( + "mozilla.org", + "example.org", + "example.com" + )) + + val domains = CustomDomains.load(RuntimeEnvironment.application) + + assertEquals(3, domains.size) + assertEquals("mozilla.org", domains.elementAt(0)) + assertEquals("example.org", domains.elementAt(1)) + assertEquals("example.com", domains.elementAt(2)) + } +} \ No newline at end of file diff --git a/components/browser/domains/src/test/java/mozilla/components/domains/DomainAutoCompleteProviderTest.kt b/components/browser/domains/src/test/java/mozilla/components/domains/DomainAutoCompleteProviderTest.kt new file mode 100644 index 00000000000..55e4d4ae1b7 --- /dev/null +++ b/components/browser/domains/src/test/java/mozilla/components/domains/DomainAutoCompleteProviderTest.kt @@ -0,0 +1,105 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.domains + +import android.preference.PreferenceManager +import mozilla.components.domains.DomainAutoCompleteProvider.AutocompleteSource +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@Config(constants = BuildConfig::class) +class DomainAutoCompleteProviderTest { + + @After + fun tearDown() { + PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application) + .edit() + .clear() + .apply() + } + + @Test + fun testAutocompletionWithShippedDomains() { + val provider = DomainAutoCompleteProvider() + provider.initialize(RuntimeEnvironment.application, true, false, false) + + val domains = listOf("mozilla.org", "google.com", "facebook.com") + provider.onDomainsLoaded(domains, emptyList()) + + assertCompletion(provider, "m", AutocompleteSource.DEFAULT_LIST, domains.size, "mozilla.org") + assertCompletion(provider, "www", AutocompleteSource.DEFAULT_LIST, domains.size, "www.mozilla.org") + assertCompletion(provider, "www.face", AutocompleteSource.DEFAULT_LIST, domains.size, "www.facebook.com") + assertCompletion(provider, "MOZ", AutocompleteSource.DEFAULT_LIST, domains.size, "MOZilla.org") + assertCompletion(provider, "www.GOO", AutocompleteSource.DEFAULT_LIST, domains.size, "www.GOOgle.com") + assertCompletion(provider, "WWW.GOOGLE.", AutocompleteSource.DEFAULT_LIST, domains.size, "WWW.GOOGLE.com") + assertCompletion(provider, "www.facebook.com", AutocompleteSource.DEFAULT_LIST, domains.size, "www.facebook.com") + assertCompletion(provider, "facebook.com", AutocompleteSource.DEFAULT_LIST, domains.size, "facebook.com") + + assertNoCompletion(provider, "wwww") + assertNoCompletion(provider, "yahoo") + } + + @Test + fun testAutocompletionWithCustomDomains() { + val domains = listOf("facebook.com", "google.com", "mozilla.org") + val customDomains = listOf("gap.com", "fanfiction.com", "mobile.de") + + val provider = DomainAutoCompleteProvider() + provider.initialize(RuntimeEnvironment.application, true, true, false) + provider.onDomainsLoaded(domains, customDomains) + + assertCompletion(provider, "f", AutocompleteSource.CUSTOM_LIST, customDomains.size, "fanfiction.com") + assertCompletion(provider, "fa", AutocompleteSource.CUSTOM_LIST, customDomains.size, "fanfiction.com") + assertCompletion(provider, "fac", AutocompleteSource.DEFAULT_LIST, domains.size, "facebook.com") + + assertCompletion(provider, "g", AutocompleteSource.CUSTOM_LIST, customDomains.size, "gap.com") + assertCompletion(provider, "go", AutocompleteSource.DEFAULT_LIST, domains.size, "google.com") + assertCompletion(provider, "ga", AutocompleteSource.CUSTOM_LIST, customDomains.size, "gap.com") + + assertCompletion(provider, "m", AutocompleteSource.CUSTOM_LIST, customDomains.size, "mobile.de") + assertCompletion(provider, "mo", AutocompleteSource.CUSTOM_LIST, customDomains.size, "mobile.de") + assertCompletion(provider, "mob", AutocompleteSource.CUSTOM_LIST, customDomains.size, "mobile.de") + assertCompletion(provider, "moz", AutocompleteSource.DEFAULT_LIST, domains.size, "mozilla.org") + } + + @Test + fun testAutocompletionWithoutDomains() { + val filter = DomainAutoCompleteProvider() + assertNoCompletion(filter, "mozilla") + } + + private fun assertCompletion( + provider: DomainAutoCompleteProvider, + text: String, + domainSource: String, + sourceSize: Int, + completion: String + ) { + val resultCallback = { result: String, source: String, totalItems: Int -> + assertFalse(result.isEmpty()) + assertEquals(completion, result) + assertEquals(domainSource, source) + assertEquals(sourceSize, totalItems) + } + provider.autocomplete(text, resultCallback) + } + + private fun assertNoCompletion(provider: DomainAutoCompleteProvider, text: String) { + val resultCallback = { result: String, source: String, totalItems: Int -> + assertTrue(result.isEmpty()) + assertTrue(source.isEmpty()) + assertEquals(0, totalItems) + } + provider.autocomplete(text, resultCallback) + } +} diff --git a/components/browser/domains/src/test/java/mozilla/components/domains/DomainsTest.kt b/components/browser/domains/src/test/java/mozilla/components/domains/DomainsTest.kt new file mode 100644 index 00000000000..e5bc066cd8c --- /dev/null +++ b/components/browser/domains/src/test/java/mozilla/components/domains/DomainsTest.kt @@ -0,0 +1,23 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.domains + +import kotlinx.coroutines.experimental.runBlocking +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment + +@RunWith(RobolectricTestRunner::class) +class DomainsTest { + + @Test + fun testLoadDomains() = runBlocking { + val domains = Domains.load(RuntimeEnvironment.application, setOf("us")) + Assert.assertFalse(domains.isEmpty()) + Assert.assertTrue(domains.contains("google.com")) + } +} \ No newline at end of file diff --git a/config/detekt-baseline.xml b/config/detekt-baseline.xml index 307c2b39611..a11c83a2678 100644 --- a/config/detekt-baseline.xml +++ b/config/detekt-baseline.xml @@ -1,7 +1,7 @@ - + ComplexCondition:InlineAutocompleteEditText.kt$InlineAutocompleteEditText$settingAutoComplete || start < 0 || start == selStart && start == selEnd ComplexCondition:InlineAutocompleteEditText.kt$InlineAutocompleteEditText.<no name provided>$composingStart >= 0 && composingEnd >= 0 && composingEnd - composingStart > text.length && removeAutocomplete(editable) ComplexMethod:DownloadUtils.kt$DownloadUtils$ @JvmStatic fun guessFileName(contentDisposition: String?, url: String?, mimeType: String?): String @@ -35,7 +35,6 @@ ReturnCount:SafeIntent.kt$SafeIntent$fun getStringArrayListExtra(name: String): ArrayList<String>? ReturnCount:SafeIntent.kt$SafeIntent$fun getStringExtra(name: String): String? ReturnCount:SafeIntent.kt$SafeIntent$fun hasExtra(name: String): Boolean - TooGenericExceptionCaught:InlineAutocompleteEditText.kt$InlineAutocompleteEditText$e: NullPointerException TooGenericExceptionCaught:InlineAutocompleteEditText.kt$InlineAutocompleteEditText$ignored: NullPointerException TooGenericExceptionCaught:SafeBundle.kt$SafeBundle$e: RuntimeException TooGenericExceptionCaught:SafeIntent.kt$SafeIntent$e: RuntimeException diff --git a/settings.gradle b/settings.gradle index fa1dd64bdc4..0501fd11c0e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,6 +21,9 @@ project(':browser-session').projectDir = new File(rootDir, 'components/browser/s include ':browser-toolbar' project(':browser-toolbar').projectDir = new File(rootDir, 'components/browser/toolbar') +include ':browser-domains' +project(':browser-domains').projectDir = new File(rootDir, 'components/browser/domains') + //////////////////////////////////////////////////////////////////////////////////////////////////// // UI components ////////////////////////////////////////////////////////////////////////////////////////////////////