2020-12-26 07:51:30 +01:00
var browser : Browser = browser || chrome ;
2018-09-16 12:27:42 +02:00
2019-06-29 15:16:27 +02:00
const PENDING_SUBMISSIONS = ':PENDING_SUBMISSIONS'
const MIGRATION = ':MIGRATION'
2019-01-14 23:11:06 +01:00
2020-09-14 11:49:54 +02:00
const CURRENT_VERSION = 100025 ;
2019-05-12 16:09:05 +02:00
2019-10-06 16:31:46 +02:00
const badIdentifiersReasons : { [ id : string ] : BadIdentifierReason } = { } ;
const badIdentifiers : { [ id : string ] : true } = { } ;
2019-01-18 19:56:54 +01:00
// If a user labels one of these URLs, they're making a mistake. Ignore the label.
// This list includes:
2019-10-06 16:31:46 +02:00
// * Social networks that are not supported (SN)
2019-01-18 19:56:54 +01:00
// * System pages of supported social networks
2019-10-06 16:31:46 +02:00
// * Archival and link shortening sites. (AR)
2019-04-18 16:53:57 +02:00
// * Reddit bots.
2019-06-29 19:47:05 +02:00
const badIdentifiersArray = [
2021-03-14 14:17:02 +01:00
'a.co' ,
'about.me=SN' ,
'amzn.to' ,
2019-10-06 16:31:46 +02:00
'archive.is=AR' ,
'archive.org=AR' ,
'ask.fm=SN' ,
2019-01-14 23:11:06 +01:00
'assets.tumblr.com' ,
2019-03-01 00:04:29 +01:00
'bing.com' ,
2019-01-14 23:11:06 +01:00
'bit.ly' ,
'blogspot.com' ,
2021-03-14 14:17:02 +01:00
'buymeacoffee.com=SN' ,
'cash.app=SN' ,
'cash.me=SN' ,
2019-02-08 20:42:25 +01:00
'change.org' ,
2019-06-29 14:36:50 +02:00
'chrome.google.com' ,
2019-10-06 16:31:46 +02:00
'curiouscat.me=SN' ,
2021-03-14 14:17:02 +01:00
'curiouscat.qa=SN' ,
2019-10-06 16:31:46 +02:00
'deviantart.com=SN' ,
'discord.gg=SN' ,
'discordapp.com=SN' ,
2021-03-14 14:17:02 +01:00
'discord-store.com=SN' ,
2019-04-08 16:27:41 +02:00
'disqus.com' ,
2019-06-29 14:36:50 +02:00
'docs.google.com' ,
'drive.google.com' ,
2019-03-01 00:04:29 +01:00
'duckduckgo.com' ,
2019-04-08 16:27:41 +02:00
'en.wikipedia.org' ,
2019-02-18 23:16:03 +01:00
'en.wikiquote.org' ,
2019-10-06 16:31:46 +02:00
'etsy.com=SN' ,
2019-04-08 16:27:41 +02:00
'facebook.com' ,
2019-01-14 23:11:06 +01:00
'facebook.com/a' ,
2021-03-14 14:17:02 +01:00
'facebook.com/about' ,
2019-01-14 23:11:06 +01:00
'facebook.com/ad_campaign' ,
'facebook.com/ads' ,
2019-07-10 20:36:34 +02:00
'facebook.com/advertising' ,
2019-01-14 23:11:06 +01:00
'facebook.com/ajax' ,
'facebook.com/bookmarks' ,
2019-07-10 20:36:34 +02:00
'facebook.com/browse' ,
2019-01-14 23:11:06 +01:00
'facebook.com/buddylist.php' ,
'facebook.com/bugnub' ,
2019-07-10 20:36:34 +02:00
'facebook.com/business' ,
2021-03-14 14:17:02 +01:00
'facebook.com/c' ,
2019-01-14 23:11:06 +01:00
'facebook.com/comment' ,
'facebook.com/composer' ,
2019-07-10 20:36:34 +02:00
'facebook.com/connect' ,
2021-03-14 14:17:02 +01:00
'facebook.com/dialog' ,
2019-06-29 14:36:50 +02:00
'facebook.com/docs' ,
2019-04-30 21:46:56 +02:00
'facebook.com/donate' ,
2019-01-14 23:11:06 +01:00
'facebook.com/events' ,
'facebook.com/findfriends' ,
'facebook.com/friends' ,
'facebook.com/fundraisers' ,
'facebook.com/games' ,
'facebook.com/groups' ,
2019-02-25 23:44:18 +01:00
'facebook.com/hashtag' ,
2019-01-14 23:11:06 +01:00
'facebook.com/help' ,
'facebook.com/home.php' ,
2019-10-06 10:30:29 +02:00
'facebook.com/instantgames' ,
2019-01-14 23:11:06 +01:00
'facebook.com/intl' ,
'facebook.com/jobs' ,
'facebook.com/l.php' ,
'facebook.com/language.php' ,
2021-03-14 14:17:02 +01:00
'facebook.com/latest' ,
2019-01-14 23:11:06 +01:00
'facebook.com/legal' ,
'facebook.com/like.php' ,
'facebook.com/local_surface' ,
'facebook.com/logout.php' ,
2020-04-13 09:32:53 +02:00
'facebook.com/marketplace' ,
2019-01-14 23:11:06 +01:00
'facebook.com/mbasic' ,
2020-04-13 09:32:53 +02:00
'facebook.com/me' ,
2019-04-30 21:55:40 +02:00
'facebook.com/media' ,
2021-03-14 14:17:02 +01:00
'facebook.com/memories' ,
2019-01-14 23:11:06 +01:00
'facebook.com/menu' ,
'facebook.com/messages' ,
'facebook.com/nfx' ,
'facebook.com/notes' ,
'facebook.com/notifications' ,
2021-03-14 14:17:02 +01:00
'facebook.com/notifications.php' ,
2019-01-14 23:11:06 +01:00
'facebook.com/nt' ,
'facebook.com/page' ,
'facebook.com/pages' ,
'facebook.com/people' ,
'facebook.com/permalink.php' ,
'facebook.com/pg' ,
2020-04-13 09:32:53 +02:00
'facebook.com/photo' ,
2021-03-14 14:17:02 +01:00
'facebook.com/photo.php' ,
2019-08-30 22:28:45 +02:00
'facebook.com/places' ,
2019-01-14 23:11:06 +01:00
'facebook.com/policies' ,
'facebook.com/privacy' ,
2019-07-10 20:36:34 +02:00
'facebook.com/profile' ,
2021-03-14 14:17:02 +01:00
'facebook.com/profile.php' ,
2019-07-10 20:36:34 +02:00
'facebook.com/public' ,
2019-01-14 23:11:06 +01:00
'facebook.com/rapid_report' ,
'facebook.com/reactions' ,
'facebook.com/salegroups' ,
'facebook.com/search' ,
'facebook.com/settings' ,
2021-03-14 14:17:02 +01:00
'facebook.com/share' ,
'facebook.com/share.php' ,
2019-02-25 23:44:18 +01:00
'facebook.com/sharer.php' ,
2019-01-14 23:11:06 +01:00
'facebook.com/shares' ,
2019-07-10 20:36:34 +02:00
'facebook.com/stories' ,
2019-01-14 23:11:06 +01:00
'facebook.com/story.php' ,
2021-03-14 14:17:02 +01:00
'facebook.com/support' ,
'facebook.com/timeline' ,
2019-01-14 23:11:06 +01:00
'facebook.com/ufi' ,
2021-03-14 14:17:02 +01:00
'facebook.com/video' ,
2019-07-10 20:36:34 +02:00
'facebook.com/watch' ,
2021-03-14 14:17:02 +01:00
'fb.me' ,
2019-10-06 16:31:46 +02:00
'flickr.com=SN' ,
2021-03-14 14:17:02 +01:00
'gofundme.com=SN' ,
2019-08-30 22:28:45 +02:00
'goo.gl' ,
2019-01-14 23:14:36 +01:00
'google.com' ,
'googleusercontent.com' ,
2020-12-26 07:51:30 +01:00
'http' ,
'https' ,
2019-02-18 21:27:01 +01:00
'i.imgur.com' ,
'i.reddituploads.com' ,
2019-10-06 16:31:46 +02:00
'imdb.com=SN' ,
2019-02-18 21:27:01 +01:00
'imgur.com' ,
2021-03-14 14:17:02 +01:00
'indiegogo.com=SN' ,
2019-10-06 16:31:46 +02:00
'instagram.com=SN' ,
'itunes.apple.com=SN' ,
'ko-fi.com=SN' ,
2021-03-14 14:17:02 +01:00
'last.fm=SN' ,
2019-10-06 16:31:46 +02:00
'linkedin.com=SN' ,
2021-03-14 14:17:02 +01:00
'linktr.ee=SN' ,
2019-01-18 19:56:54 +01:00
'mail.google.com' ,
2019-01-14 23:11:06 +01:00
'media.tumblr.com' ,
'medium.com' ,
2019-06-29 14:36:50 +02:00
'news.google.com' ,
2021-03-14 14:17:02 +01:00
'onlyfans.com=SN' ,
'open.spotify.com=SN' ,
2019-10-06 16:31:46 +02:00
'patreon.com=SN' ,
'paypal.com=SN' ,
'paypal.me=SN' ,
2021-03-14 14:17:02 +01:00
'pinterest.com=SN' ,
2019-02-18 21:27:01 +01:00
'play.google.com' ,
2021-03-14 14:17:02 +01:00
'plus.google.com=SN' ,
'podcasts.apple.com=SN' ,
'poshmark.com=SN' ,
2019-04-08 16:27:41 +02:00
'rationalwiki.org' ,
2019-01-14 23:11:06 +01:00
'reddit.com' ,
'reddit.com/r/all' ,
'reddit.com/r/popular' ,
2019-04-18 16:50:41 +02:00
'reddit.com/user/_youtubot_' ,
'reddit.com/user/animalfactsbot' ,
'reddit.com/user/anti-gif-bot' ,
'reddit.com/user/areyoudeaf' ,
'reddit.com/user/automoderator' ,
'reddit.com/user/autotldr' ,
2021-03-14 14:17:02 +01:00
'reddit.com/user/auto-xkcd37' ,
2019-04-18 16:50:41 +02:00
'reddit.com/user/biglebowskibot' ,
'reddit.com/user/bots_rise_up' ,
'reddit.com/user/cheer_up_bot' ,
'reddit.com/user/cheer-bot' ,
'reddit.com/user/clickablelinkbot' ,
'reddit.com/user/colorizethis' ,
'reddit.com/user/darnit_bot' ,
'reddit.com/user/darthplagueisbot' ,
'reddit.com/user/deepfrybot' ,
'reddit.com/user/dreamprocessor' ,
'reddit.com/user/drunkanimalfactbot' ,
'reddit.com/user/election_info_bot' ,
'reddit.com/user/eyebleachbot' ,
'reddit.com/user/factorial-bot' ,
'reddit.com/user/friendly-bot' ,
'reddit.com/user/garlicbot' ,
'reddit.com/user/gfycat_details_fixer' ,
'reddit.com/user/gifv-bot' ,
'reddit.com/user/good_good_gb_bb' ,
'reddit.com/user/goodbot_badbot' ,
'reddit.com/user/goodmod_badmod' ,
'reddit.com/user/gyazo_bot' ,
2019-04-30 21:46:56 +02:00
'reddit.com/user/haikubot-1911' ,
2021-03-14 14:17:02 +01:00
'reddit.com/user/haiku-detector' ,
2019-04-18 16:50:41 +02:00
'reddit.com/user/helperbot_' ,
'reddit.com/user/hug-bot' ,
'reddit.com/user/i_am_a_haiku_bot' ,
'reddit.com/user/ilinknsfwsubreddits' ,
'reddit.com/user/image_linker_bot' ,
'reddit.com/user/imdb_preview' ,
'reddit.com/user/imguralbumbot' ,
'reddit.com/user/jacksfilmsbot' ,
'reddit.com/user/jiffierbot' ,
'reddit.com/user/livetwitchclips' ,
'reddit.com/user/lyrics-matcher-bot' ,
'reddit.com/user/mailmygovnnbot' ,
'reddit.com/user/massdropbot' ,
'reddit.com/user/mentioned_videos' ,
'reddit.com/user/metric_units' ,
'reddit.com/user/mlbvideoconverterbot' ,
'reddit.com/user/morejpeg_auto' ,
'reddit.com/user/movieguide' ,
'reddit.com/user/multiusebot' ,
'reddit.com/user/news-summary' ,
'reddit.com/user/nflvideoconverterbot' ,
'reddit.com/user/octopusfunfacts' ,
'reddit.com/user/octupusfunfacts' ,
'reddit.com/user/opfeels' ,
'reddit.com/user/payrespects-bot' ,
'reddit.com/user/perrycohen' ,
'reddit.com/user/phonebatterylevelbot' ,
'reddit.com/user/picdescriptionbot' ,
'reddit.com/user/portmanteau-bot' ,
'reddit.com/user/quoteme-bot' ,
'reddit.com/user/redditsilverbot' ,
'reddit.com/user/redditstreamable' ,
'reddit.com/user/remindmebot' ,
'reddit.com/user/riskyclickerbot' ,
'reddit.com/user/rosey-the-bot' ,
'reddit.com/user/seriouslywhenishl3' ,
'reddit.com/user/shhbot' ,
'reddit.com/user/smallsubbot' ,
'reddit.com/user/snapshillbot' ,
'reddit.com/user/sneakpeekbot' ,
2019-04-30 21:46:56 +02:00
'reddit.com/user/stabbot' ,
2021-03-14 14:17:02 +01:00
'reddit.com/user/stabbot_crop' ,
2019-04-18 16:50:41 +02:00
'reddit.com/user/steamnewsbot' ,
'reddit.com/user/subjunctive__bot' ,
'reddit.com/user/table_it_bot' ,
2019-04-30 21:46:56 +02:00
'reddit.com/user/thehelperdroid' ,
2021-03-14 14:17:02 +01:00
'reddit.com/user/the-paranoid-android' ,
2019-04-18 16:50:41 +02:00
'reddit.com/user/thiscatmightcheeryou' ,
'reddit.com/user/timestamp_bot' ,
'reddit.com/user/timezone_bot' ,
'reddit.com/user/tiny_smile_bot' ,
'reddit.com/user/tipjarbot' ,
'reddit.com/user/tippr' ,
'reddit.com/user/totes_meta_bot' ,
'reddit.com/user/totesmessenger' ,
'reddit.com/user/tumblrdirect' ,
'reddit.com/user/tweetsincommentsbot' ,
'reddit.com/user/twitterlinkbot' ,
'reddit.com/user/twittertostreamable' ,
'reddit.com/user/video_descriptionbot' ,
'reddit.com/user/videodirectlinkbot' ,
'reddit.com/user/vredditmirrorbot' ,
'reddit.com/user/whodidthisbot' ,
'reddit.com/user/wikitextbot' ,
'reddit.com/user/xkcd_transcriber' ,
'reddit.com/user/youtubefactsbot' ,
2019-02-18 21:27:01 +01:00
'reddituploads.com' ,
2019-01-14 23:11:06 +01:00
'removeddit.com' ,
2019-06-29 14:36:50 +02:00
'sites.google.com' ,
2019-10-06 16:31:46 +02:00
'snapchat.com=SN' ,
'soundcloud.com=SN' ,
2021-03-14 14:17:02 +01:00
'spotify.com=SN' ,
2019-10-06 16:31:46 +02:00
'steamcommunity.com=SN' ,
2019-01-14 23:11:06 +01:00
't.co' ,
2021-03-14 14:17:02 +01:00
't.me=SN' ,
2019-01-14 23:11:06 +01:00
't.umblr.com' ,
2021-03-14 14:17:02 +01:00
'tapastic.com=SN' ,
2019-10-06 16:31:46 +02:00
'tapatalk.com=SN' ,
2021-03-14 14:17:02 +01:00
'tiktok.com=SN' ,
2019-04-30 21:46:56 +02:00
'tmblr.co' ,
2019-01-14 23:11:06 +01:00
'tumblr.com' ,
2019-10-06 16:31:46 +02:00
'twitch.tv=SN' ,
2019-01-14 23:11:06 +01:00
'twitter.com' ,
2019-10-06 16:31:46 +02:00
'twitter.com/explore' ,
2019-01-14 23:11:06 +01:00
'twitter.com/hashtag' ,
2019-10-06 16:31:46 +02:00
'twitter.com/home' ,
2019-01-14 23:11:06 +01:00
'twitter.com/i' ,
2021-03-14 14:17:02 +01:00
'twitter.com/intent' ,
2019-10-06 16:31:46 +02:00
'twitter.com/messages' ,
'twitter.com/notifications' ,
2019-01-14 23:11:06 +01:00
'twitter.com/search' ,
'twitter.com/settings' ,
2021-03-14 14:17:02 +01:00
'twitter.com/share' ,
2019-02-25 23:03:20 +01:00
'twitter.com/threader_app' ,
2019-01-14 23:11:06 +01:00
'twitter.com/threadreaderapp' ,
'twitter.com/who_to_follow' ,
2019-10-06 16:31:46 +02:00
'vimeo.com=SN' ,
'vk.com=SN' ,
2021-03-14 14:17:02 +01:00
'vm.tiktok.com=SN' ,
'wattpad.com=SN' ,
2019-04-08 16:27:41 +02:00
'wikipedia.org' ,
2019-01-14 23:11:06 +01:00
'wordpress.com' ,
2021-03-14 14:17:02 +01:00
'wp.me' ,
2019-01-14 23:11:06 +01:00
'www.tumblr.com' ,
'youtu.be' ,
'youtube.com' ,
2021-03-14 14:17:02 +01:00
'youtube.com/account' ,
'youtube.com/feed' ,
'youtube.com/gaming' ,
2019-03-03 21:26:59 +01:00
'youtube.com/playlist' ,
2021-03-14 14:17:02 +01:00
'youtube.com/premium' ,
2019-01-14 23:11:06 +01:00
'youtube.com/redirect' ,
'youtube.com/watch' ,
2019-10-06 16:31:46 +02:00
] . map ( x = > {
const arr = x . split ( '=' ) ;
const id = arr [ 0 ] ;
if ( arr [ 1 ] ) badIdentifiersReasons [ id ] = < BadIdentifierReason > arr [ 1 ] ;
badIdentifiers [ id ] = true ;
return id ;
} ) ;
2019-01-14 23:11:06 +01:00
2021-07-05 09:57:51 +02:00
2021-07-05 10:07:26 +02:00
const ASYMMETRIC_COMMENT = "Submission data is asymmetrically encrypted (in addition to HTTPS), so that not even the cloud provider can access it (since it doesn't have the corresponding private key). Actual processing and decryption is done off-cloud in a second phase. If you want to inspect the submission data *before* it gets encrypted, open the extension debugging dev tools (chrome://extensions or about:debugging) and look at the console output, or call setAsymmetricEncryptionEnabled(false) to permanently turn asymmetric encryption off." ;
2021-07-05 09:57:51 +02:00
// This key is public. Decrypting requires a different key.
const SHINIGAMI_PUBLIC_ENCRYPTION_KEY = {
"alg" : "RSA-OAEP-256" ,
"e" : "AQAB" ,
"ext" : true ,
"key_ops" : [
"encrypt"
] ,
"kty" : "RSA" ,
"n" : "sJ8r8D_Ae_y4db_sSZvLIqTCjAdyDEIMXHcCNM_sOO_t2RmcUETecKyDdNVtaY9Ve0OM1cyHz-YEYXMpNQx_NcXd6KDdGxZ1MUTlja5tUIDMNw-N0hzZbmvk-4MymMpN25lwdvCGo3Ri6EJ7XRMZbtmwTfQoZR5olfGi_Y0SbTw0RJ-U9Wf2CqlQ7w8x-M77cPaANKav_yOitwlJjhkZTo6ssvdnsc20OIP46XSYRwyzlMAlx7wQ2Dw7aX4bkPMbgs2L13uAFPCvQOBnE4esD2MyICKiIe0j-wgVK4qh0gmh513HNYewsgsoiMJlzz5v2epFwh25icIEHfYRcKteryEuzKUZ7g-FqdLb6sI_hrnvvu6D8MIDH1Baq179lpyFjJ4_famcuRuHsRPSwyQSX8v8DL23lARX8U9ZhcH0f3bBepuzEHXutnqxGxnErnxZGGr64saIBgGdtuOYbYuFqzMjCUvlFyCVh8DItRsJOdzj6xAxafnU5yvSJqcgAX0PQclbwIyg6wtxVa1et6Q7QiM16s5RyW2KHxp27PaBAuVlgVBG8S4DguJK3Y9E2vkgDTpFoSS-J80tZhZhPZ4PZL4ouvYrNnR3JgveuLYZsmYdpjtShkO_6erSanM0ZRb0E00TUYRykkviDtBLDP1aYNXv4_5jhAlLc_tOmWK_RLc"
} ;
2019-06-29 19:54:25 +02:00
var lastSubmissionError : string = null ;
2018-09-16 12:27:42 +02:00
2019-06-29 19:54:25 +02:00
var overrides : LabelMap = null ;
2018-09-16 12:27:42 +02:00
var accepted = false ;
2019-06-29 19:54:25 +02:00
var installationId : string = null ;
2019-07-17 23:35:00 +02:00
var theme : string = '' ;
2019-01-14 23:11:06 +01:00
2021-07-05 09:57:51 +02:00
var disableAsymmetricEncryption = false ;
browser . storage . local . get ( [ 'overrides' , 'accepted' , 'installationId' , 'theme' , 'disableAsymmetricEncryption' ] , v = > {
2019-05-12 16:58:41 +02:00
if ( ! v . installationId ) {
installationId = ( Math . random ( ) + '.' + Math . random ( ) + '.' + Math . random ( ) ) . replace ( /\./g , '' ) ;
browser . storage . local . set ( { installationId : installationId } ) ;
} else {
installationId = v . installationId ;
}
2018-09-16 12:27:42 +02:00
accepted = v . accepted
overrides = v . overrides || { }
2019-07-17 23:35:00 +02:00
theme = v . theme ;
2021-07-05 09:57:51 +02:00
disableAsymmetricEncryption = v . disableAsymmetricEncryption || false ;
2019-01-14 23:11:06 +01:00
2019-06-29 19:47:05 +02:00
const migration = overrides [ MIGRATION ] || 0 ;
2019-06-29 19:54:25 +02:00
if ( migration < CURRENT_VERSION ) {
2019-01-14 23:11:06 +01:00
2019-06-29 19:54:25 +02:00
for ( const key of Object . getOwnPropertyNames ( overrides ) ) {
2019-06-29 19:47:05 +02:00
if ( key . startsWith ( ':' ) ) continue ;
2019-06-29 19:54:25 +02:00
if ( key . startsWith ( 'facebook.com/a.' ) ) {
2019-02-18 21:52:58 +01:00
delete overrides [ key ] ;
continue ;
}
2019-06-29 19:54:25 +02:00
if ( key != key . toLowerCase ( ) ) {
2019-06-29 19:47:05 +02:00
let v = overrides [ key ] ;
2019-01-14 23:11:06 +01:00
delete overrides [ key ] ;
overrides [ key . toLowerCase ( ) ] = v ;
}
}
2019-06-29 19:54:25 +02:00
2019-01-14 23:11:06 +01:00
badIdentifiersArray . forEach ( x = > delete overrides [ x ] ) ;
2019-06-29 19:47:05 +02:00
overrides [ MIGRATION ] = < any > CURRENT_VERSION ;
2019-01-14 23:11:06 +01:00
browser . storage . local . set ( { overrides : overrides } ) ;
}
2018-09-16 12:27:42 +02:00
} )
2019-06-29 19:54:25 +02:00
const bloomFilters : BloomFilter [ ] = [ ] ;
2018-09-16 12:27:42 +02:00
2019-06-29 19:47:05 +02:00
async function loadBloomFilter ( name : LabelKind ) {
2018-09-16 12:27:42 +02:00
2019-06-29 19:47:05 +02:00
const url = browser . extension . getURL ( 'data/' + name + '.dat' ) ;
const response = await fetch ( url ) ;
const arrayBuffer = await response . arrayBuffer ( ) ;
const array = new Uint32Array ( arrayBuffer ) ;
const b = new BloomFilter ( array , 20 ) ;
b . name = name ;
bloomFilters . push ( b ) ;
2018-09-16 12:27:42 +02:00
}
2021-07-05 09:57:51 +02:00
function setAsymmetricEncryptionEnabled ( enabled : boolean ) {
disableAsymmetricEncryption = ! enabled ;
browser . storage . local . set ( { disableAsymmetricEncryption : disableAsymmetricEncryption } ) ;
}
2018-09-16 12:27:42 +02:00
2019-06-29 19:47:05 +02:00
browser . runtime . onMessage . addListener < ShinigamiEyesMessage , ShinigamiEyesMessage | LabelMap > ( ( message , sender , sendResponse ) = > {
2019-07-17 23:35:00 +02:00
if ( message . setTheme ) {
theme = message . setTheme ;
browser . storage . local . set ( { theme : message.setTheme } ) ;
chrome . tabs . query ( { } , function ( tabs ) {
for ( var i = 0 ; i < tabs . length ; ++ i ) {
try {
2019-10-06 16:31:46 +02:00
sendMessageToContent ( tabs [ i ] . id , null , { updateAllLabels : true } ) ;
2019-07-17 23:35:00 +02:00
} catch ( e ) { }
}
} ) ;
}
2018-12-16 17:36:19 +01:00
if ( message . acceptClicked !== undefined ) {
2018-09-16 12:27:42 +02:00
accepted = message . acceptClicked ;
2018-12-16 17:36:19 +01:00
browser . storage . local . set ( { accepted : accepted } ) ;
if ( accepted && uncommittedResponse )
2018-09-16 12:27:42 +02:00
saveLabel ( uncommittedResponse )
uncommittedResponse = null ;
2019-07-17 23:35:00 +02:00
}
if ( message . closeCallingTab ) {
browser . tabs . remove ( sender . tab . id ) ;
2018-09-16 12:27:42 +02:00
return ;
}
2019-06-29 19:54:25 +02:00
const response : LabelMap = { } ;
2019-06-29 19:47:05 +02:00
const transphobic = message . myself && bloomFilters . filter ( x = > x . name == 'transphobic' ) [ 0 ] . test ( message . myself ) ;
for ( const id of message . ids ) {
2018-10-27 11:42:49 +02:00
if ( overrides [ id ] !== undefined ) {
response [ id ] = overrides [ id ] ;
continue ;
}
if ( transphobic ) {
if ( id == message . myself ) continue ;
2019-06-29 19:47:05 +02:00
let sum = 0 ;
for ( let i = 0 ; i < id . length ; i ++ ) {
2018-09-16 12:27:42 +02:00
sum += id . charCodeAt ( i ) ;
}
2018-12-16 17:36:19 +01:00
if ( sum % 8 != 0 ) continue ;
2018-09-16 12:27:42 +02:00
}
2019-06-29 19:47:05 +02:00
for ( const bloomFilter of bloomFilters ) {
2018-10-27 11:42:49 +02:00
if ( bloomFilter . test ( id ) ) response [ id ] = bloomFilter . name ;
2018-09-16 12:27:42 +02:00
}
}
2019-07-17 23:35:00 +02:00
response [ ':theme' ] = < any > theme ;
2018-09-16 12:27:42 +02:00
sendResponse ( response ) ;
} ) ;
loadBloomFilter ( 'transphobic' ) ;
loadBloomFilter ( 't-friendly' ) ;
2020-12-26 09:55:04 +01:00
const socialNetworkPatterns = [
2018-09-16 12:27:42 +02:00
"*://*.facebook.com/*" ,
"*://*.youtube.com/*" ,
"*://*.reddit.com/*" ,
2018-11-16 21:51:31 +01:00
"*://*.twitter.com/*" ,
2019-07-28 07:31:04 +02:00
"*://*.t.co/*" ,
2020-12-26 08:14:42 +01:00
"*://*.medium.com/*" ,
2018-12-16 11:32:37 +01:00
"*://disqus.com/*" ,
2019-01-13 17:16:37 +01:00
"*://*.tumblr.com/*" ,
"*://*.wikipedia.org/*" ,
"*://*.rationalwiki.org/*" ,
"*://*.google.com/*" ,
2019-03-01 00:04:29 +01:00
"*://*.bing.com/*" ,
"*://duckduckgo.com/*" ,
2020-12-26 09:55:04 +01:00
] ;
2019-10-06 13:04:11 +02:00
2020-12-26 09:55:04 +01:00
const homepagePatterns = [
2019-10-06 13:04:11 +02:00
"*://*/" ,
2019-10-26 12:38:08 +02:00
"*://*/?fbclid=*" ,
2019-10-06 13:04:11 +02:00
"*://*/about*" ,
"*://*/contact*" ,
"*://*/faq*" ,
"*://*/blog" ,
"*://*/blog/" ,
"*://*/news" ,
"*://*/news/" ,
"*://*/en/" ,
"*://*/index.html" ,
"*://*/index.php" ,
2020-12-26 09:55:04 +01:00
] ;
const allPatterns = socialNetworkPatterns . concat ( homepagePatterns ) ;
function createEntityContextMenu ( text : string , id : ContextMenuCommand ) {
browser . contextMenus . create ( {
id : id ,
title : text ,
contexts : [ "link" ] ,
targetUrlPatterns : allPatterns
2018-09-16 12:27:42 +02:00
} ) ;
}
2020-12-26 09:55:04 +01:00
function createSystemContextMenu ( text : string , id : ContextMenuCommand , separator? : boolean ) {
browser . contextMenus . create ( {
id : id ,
title : text ,
contexts : [ "all" ] ,
type : separator ? 'separator' : 'normal' ,
documentUrlPatterns : allPatterns
} ) ;
}
browser . contextMenus . create ( {
title : '(Please right click on a link instead)' ,
enabled : false ,
contexts : [ 'page' ] ,
documentUrlPatterns : socialNetworkPatterns
} ) ;
createEntityContextMenu ( 'Mark as anti-trans' , 'mark-transphobic' ) ;
createEntityContextMenu ( 'Mark as t-friendly' , 'mark-t-friendly' ) ;
createEntityContextMenu ( 'Clear' , 'mark-none' ) ;
createSystemContextMenu ( '---' , 'separator' , true ) ;
createSystemContextMenu ( 'Settings' , 'options' ) ;
createSystemContextMenu ( 'Help' , 'help' ) ;
2018-09-16 12:27:42 +02:00
2019-06-29 19:54:25 +02:00
var uncommittedResponse : ShinigamiEyesSubmission = null ;
2018-09-16 12:27:42 +02:00
2021-07-05 09:57:51 +02:00
/ *
* base64 - arraybuffer
* https : //github.com/niklasvh/base64-arraybuffer
*
* Copyright ( c ) 2012 Niklas von Hertzen
* Licensed under the MIT license .
* /
const BASE_64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
function bufferToBase64 ( arraybuffer : ArrayBuffer ) {
var bytes = new Uint8Array ( arraybuffer ) ,
i , len = bytes . length , base64 = "" ;
for ( i = 0 ; i < len ; i += 3 ) {
base64 += BASE_64_CHARS [ bytes [ i ] >> 2 ] ;
base64 += BASE_64_CHARS [ ( ( bytes [ i ] & 3 ) << 4 ) | ( bytes [ i + 1 ] >> 4 ) ] ;
base64 += BASE_64_CHARS [ ( ( bytes [ i + 1 ] & 15 ) << 2 ) | ( bytes [ i + 2 ] >> 6 ) ] ;
base64 += BASE_64_CHARS [ bytes [ i + 2 ] & 63 ] ;
}
if ( ( len % 3 ) === 2 ) {
base64 = base64 . substring ( 0 , base64 . length - 1 ) + "=" ;
} else if ( len % 3 === 1 ) {
base64 = base64 . substring ( 0 , base64 . length - 2 ) + "==" ;
}
return base64 ;
}
function objectToBytes ( obj : any ) {
const json = JSON . stringify ( obj ) ;
const textEncoder = new TextEncoder ( ) ;
return textEncoder . encode ( json ) ;
}
interface AsymmetricallyEncryptedData {
symmetricKey : JsonWebKey ;
2021-07-10 12:17:30 +02:00
sha256 : string ;
2021-07-05 09:57:51 +02:00
}
async function encryptSubmission ( plainObj : any ) : Promise < CipherSubmission > {
const publicEncryptionKey = await crypto . subtle . importKey ( 'jwk' , SHINIGAMI_PUBLIC_ENCRYPTION_KEY , {
name : 'RSA-OAEP' ,
hash : 'SHA-256'
} , false , [ 'encrypt' ] ) ;
const symmetricKey = await crypto . subtle . generateKey (
{
name : 'AES-CBC' ,
length : 256
} ,
true ,
[ 'encrypt' , 'decrypt' ]
) ;
const iv = window . crypto . getRandomValues ( new Uint8Array ( 16 ) ) ;
2021-07-10 12:17:30 +02:00
const plainData = objectToBytes ( plainObj ) ;
2021-07-05 09:57:51 +02:00
const symmetricallyEncryptedData = await crypto . subtle . encrypt ( {
name : "AES-CBC" ,
iv
2021-07-10 12:17:30 +02:00
} , symmetricKey , plainData ) ;
const plainHash = await crypto . subtle . digest ( 'SHA-256' , plainData ) ;
2021-07-05 09:57:51 +02:00
const asymmetricallyEncryptedSymmetricKey = await crypto . subtle . encrypt (
{
name : 'RSA-OAEP'
} ,
publicEncryptionKey ,
objectToBytes ( < AsymmetricallyEncryptedData > {
2021-07-10 12:17:30 +02:00
symmetricKey : await crypto . subtle . exportKey ( 'jwk' , symmetricKey ) ,
sha256 : bufferToBase64 ( plainHash )
2021-07-05 09:57:51 +02:00
} )
) ;
return {
_comment : ASYMMETRIC_COMMENT ,
asymmetricallyEncryptedSymmetricKey : bufferToBase64 ( asymmetricallyEncryptedSymmetricKey ) ,
symmetricInitializationVector : bufferToBase64 ( iv ) ,
symmetricallyEncryptedData : bufferToBase64 ( symmetricallyEncryptedData ) ,
version : CURRENT_VERSION
} ;
}
interface CipherSubmission {
_comment : string ;
asymmetricallyEncryptedSymmetricKey : string ;
symmetricInitializationVector : string ;
symmetricallyEncryptedData : string ;
version : number ;
}
2019-05-12 17:13:18 +02:00
async function submitPendingRatings() {
2019-06-29 19:47:05 +02:00
const submitted = getPendingSubmissions ( ) . map ( x = > x ) ;
2021-07-05 09:57:51 +02:00
let plainRequest : any = {
2018-12-16 17:36:19 +01:00
installationId : installationId ,
2019-05-12 17:13:18 +02:00
lastError : lastSubmissionError ,
2018-12-16 17:36:19 +01:00
entries : submitted
2018-10-27 17:02:15 +02:00
}
2021-07-05 09:57:51 +02:00
console . log ( 'Submitting request:' ) ;
console . log ( plainRequest ) ;
let actualRequest = plainRequest ;
if ( ! disableAsymmetricEncryption ) {
try {
actualRequest = await encryptSubmission ( plainRequest ) ;
} catch ( e ) {
// If something goes wrong, fall back to the old behavior (of course, we still have HTTPS).
// While the above encryption process has been tested on both Chromium- and Gecko-based browsers,
// the real world behavior might be different.
// If no significant issues appear, this catch clause will be removed in a subsequent version of Shinigami Eyes.
actualRequest . encryptionError = e + '' ;
}
}
2019-05-12 17:13:18 +02:00
lastSubmissionError = null ;
try {
2021-07-10 12:14:25 +02:00
const response = await fetch ( 'https://shini-api.xyz/submit-vote' , {
2021-07-05 09:57:51 +02:00
body : JSON.stringify ( actualRequest ) ,
2019-05-12 17:13:18 +02:00
method : 'POST' ,
credentials : 'omit' ,
} ) ;
if ( response . status != 200 ) throw ( 'HTTP status: ' + response . status )
2019-06-29 19:54:25 +02:00
const result = await response . text ( ) ;
2019-05-12 17:13:18 +02:00
if ( result != 'SUCCESS' ) throw 'Bad response: ' + ( '' + result ) . substring ( 0 , 20 ) ;
2019-06-29 19:47:05 +02:00
overrides [ PENDING_SUBMISSIONS ] = < any > getPendingSubmissions ( ) . filter ( x = > submitted . indexOf ( x ) == - 1 ) ;
2019-05-12 17:13:18 +02:00
browser . storage . local . set ( { overrides : overrides } ) ;
2019-06-29 19:54:25 +02:00
} catch ( e ) {
2019-05-12 17:13:18 +02:00
lastSubmissionError = '' + e
}
2018-12-16 17:36:19 +01:00
2018-10-27 17:02:15 +02:00
}
2019-06-29 19:54:25 +02:00
function getPendingSubmissions ( ) : ShinigamiEyesSubmission [ ] {
2019-06-29 19:47:05 +02:00
return < any > overrides [ PENDING_SUBMISSIONS ] ;
}
2018-10-27 17:02:15 +02:00
2019-06-29 19:47:05 +02:00
function saveLabel ( response : ShinigamiEyesSubmission ) {
2018-12-16 17:36:19 +01:00
if ( accepted ) {
2019-06-29 19:47:05 +02:00
if ( ! getPendingSubmissions ( ) ) {
overrides [ PENDING_SUBMISSIONS ] = < any > Object . getOwnPropertyNames ( overrides )
. map < ShinigamiEyesSubmission > ( x = > { return { identifier : x , label : overrides [ x ] } } ) ;
2018-10-27 17:02:15 +02:00
}
2018-09-16 12:27:42 +02:00
overrides [ response . identifier ] = response . mark ;
2019-03-03 21:02:40 +01:00
if ( response . secondaryIdentifier )
overrides [ response . secondaryIdentifier ] = response . mark ;
2018-12-16 17:36:19 +01:00
browser . storage . local . set ( { overrides : overrides } ) ;
2019-05-12 16:10:36 +02:00
response . version = CURRENT_VERSION ;
2019-05-12 16:12:16 +02:00
response . submissionId = ( Math . random ( ) + '' ) . replace ( '.' , '' ) ;
2019-06-29 19:47:05 +02:00
getPendingSubmissions ( ) . push ( response ) ;
2018-10-27 17:02:15 +02:00
submitPendingRatings ( ) ;
2018-09-16 12:27:42 +02:00
//console.log(response);
2019-10-06 16:31:46 +02:00
sendMessageToContent ( response . tabId , response . frameId , {
2019-10-06 14:29:26 +02:00
updateAllLabels : true ,
confirmSetIdentifier : response.identifier ,
2019-10-07 21:07:36 +02:00
confirmSetUrl : response.url ,
2019-10-06 16:31:46 +02:00
confirmSetLabel : response.mark || 'none'
} ) ;
2018-09-16 12:27:42 +02:00
//browser.tabs.executeScript(response.tabId, {code: 'updateAllLabels()'});
return ;
}
uncommittedResponse = response ;
openHelp ( ) ;
}
2018-12-16 17:36:19 +01:00
function openHelp() {
2018-09-16 12:27:42 +02:00
browser . tabs . create ( {
url : browser.extension.getURL ( 'help.html' )
} )
}
2019-01-13 18:25:47 +01:00
2019-07-17 23:35:00 +02:00
function openOptions() {
browser . tabs . create ( {
url : browser.extension.getURL ( 'options.html' )
} )
}
2019-01-13 18:25:47 +01:00
2019-10-06 16:31:46 +02:00
function sendMessageToContent ( tabId : number , frameId : number , message : ShinigamiEyesCommand ) {
const options = frameId === null ? undefined : { frameId : frameId } ;
console . log ( message ) ;
browser . tabs . sendMessage < ShinigamiEyesCommand , void > ( tabId , message , options ) ;
}
2018-09-16 12:27:42 +02:00
browser . contextMenus . onClicked . addListener ( function ( info , tab ) {
2018-12-16 17:36:19 +01:00
if ( info . menuItemId == 'help' ) {
2018-09-16 12:27:42 +02:00
openHelp ( ) ;
return ;
}
2019-07-17 23:35:00 +02:00
if ( info . menuItemId == 'options' ) {
openOptions ( ) ;
return ;
}
2018-09-16 12:27:42 +02:00
2019-06-29 19:47:05 +02:00
const tabId = tab . id ;
const frameId = info . frameId ;
2019-06-14 19:03:50 +02:00
2019-06-29 15:41:37 +02:00
var label = < LabelKind > info . menuItemId . substring ( 'mark-' . length ) ;
2018-12-16 17:36:19 +01:00
if ( label == 'none' ) label = '' ;
2019-06-29 19:47:05 +02:00
browser . tabs . sendMessage < ShinigamiEyesSubmission , ShinigamiEyesSubmission > ( tabId , {
2018-09-16 12:27:42 +02:00
mark : label ,
url : info.linkUrl ,
2019-06-14 19:03:50 +02:00
tabId : tabId ,
frameId : frameId ,
2018-12-16 17:38:20 +01:00
// elementId: info.targetElementId,
2019-06-29 19:47:05 +02:00
debug : < any > overrides . debug
2019-06-14 19:03:50 +02:00
} , { frameId : frameId } , response = > {
2019-10-06 16:31:46 +02:00
if ( ! response || ! response . identifier ) {
2019-10-06 14:29:26 +02:00
return ;
}
2019-06-29 19:54:25 +02:00
if ( response . mark ) {
2019-10-06 16:31:46 +02:00
if ( badIdentifiers [ response . identifier ] ) {
sendMessageToContent ( tabId , frameId , {
confirmSetIdentifier : response.identifier ,
2019-10-07 21:07:36 +02:00
confirmSetUrl : response.url ,
2019-10-06 16:31:46 +02:00
confirmSetLabel : 'bad-identifier' ,
badIdentifierReason : badIdentifiersReasons [ response . identifier ]
} ) ;
return ;
}
2019-03-03 21:02:40 +01:00
if ( response . secondaryIdentifier && badIdentifiers [ response . secondaryIdentifier ] )
response . secondaryIdentifier = null ;
}
2019-06-14 19:03:50 +02:00
response . tabId = tabId ;
response . frameId = frameId ;
2018-09-16 12:27:42 +02:00
saveLabel ( response ) ;
} )
} ) ;