├── cheevos.xpi ├── data ├── coins.png ├── firefox.png ├── background.jpg ├── trophy_icon.png ├── background-1024.jpg ├── point-ring-bronze.png ├── point-ring-gold.png ├── point-ring-silver.png ├── star-bronze-empty.png ├── star-gold-empty.png ├── star-gold-filled.png ├── star-silver-empty.png ├── star-bronze-filled.png ├── star-silver-filled.png ├── noise-overlay-orange.png ├── award-glyph-default-gold.png ├── award-disc-background-gold.png ├── award-glyph-default-bronze.png ├── award-glyph-default-silver.png ├── award-disc-background-bronze.png ├── award-disc-background-silver.png ├── panel.css ├── icon-generator.html ├── panel.html ├── panel.js ├── icon-generator.js ├── cheevo.js ├── cheevo.html ├── chrome.css └── cheevo.css ├── logo-64x64.png ├── cheevos-toolbar-24x24.png ├── doc └── main.md ├── lib ├── icon-generator.js ├── achievement-overlay.js └── main.js ├── package.json ├── README.md ├── test └── test-main.js └── locale ├── en-US.properties └── el-GR.properties /cheevos.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/cheevos.xpi -------------------------------------------------------------------------------- /data/coins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/coins.png -------------------------------------------------------------------------------- /data/firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/firefox.png -------------------------------------------------------------------------------- /logo-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/logo-64x64.png -------------------------------------------------------------------------------- /data/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/background.jpg -------------------------------------------------------------------------------- /data/trophy_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/trophy_icon.png -------------------------------------------------------------------------------- /cheevos-toolbar-24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/cheevos-toolbar-24x24.png -------------------------------------------------------------------------------- /data/background-1024.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/background-1024.jpg -------------------------------------------------------------------------------- /data/point-ring-bronze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/point-ring-bronze.png -------------------------------------------------------------------------------- /data/point-ring-gold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/point-ring-gold.png -------------------------------------------------------------------------------- /data/point-ring-silver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/point-ring-silver.png -------------------------------------------------------------------------------- /data/star-bronze-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/star-bronze-empty.png -------------------------------------------------------------------------------- /data/star-gold-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/star-gold-empty.png -------------------------------------------------------------------------------- /data/star-gold-filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/star-gold-filled.png -------------------------------------------------------------------------------- /data/star-silver-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/star-silver-empty.png -------------------------------------------------------------------------------- /data/star-bronze-filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/star-bronze-filled.png -------------------------------------------------------------------------------- /data/star-silver-filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/star-silver-filled.png -------------------------------------------------------------------------------- /data/noise-overlay-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/noise-overlay-orange.png -------------------------------------------------------------------------------- /data/award-glyph-default-gold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/award-glyph-default-gold.png -------------------------------------------------------------------------------- /data/award-disc-background-gold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/award-disc-background-gold.png -------------------------------------------------------------------------------- /data/award-glyph-default-bronze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/award-glyph-default-bronze.png -------------------------------------------------------------------------------- /data/award-glyph-default-silver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/award-glyph-default-silver.png -------------------------------------------------------------------------------- /data/award-disc-background-bronze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/award-disc-background-bronze.png -------------------------------------------------------------------------------- /data/award-disc-background-silver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msujaws/Cheevos/HEAD/data/award-disc-background-silver.png -------------------------------------------------------------------------------- /data/panel.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: green; 3 | } 4 | 5 | h1 { 6 | color: #000; 7 | } 8 | 9 | h2 { 10 | color: #000; 11 | } 12 | -------------------------------------------------------------------------------- /doc/main.md: -------------------------------------------------------------------------------- 1 | The main module is a program that creates a widget. When a user clicks on 2 | the widget, the program loads the mozilla.org website in a new tab. 3 | -------------------------------------------------------------------------------- /data/icon-generator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /data/panel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /lib/icon-generator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {data} = require('sdk/self'); 4 | 5 | exports.generate = function(options) { 6 | let text = options.text || ""; 7 | let callback = options.onReady; 8 | 9 | let port = require("sdk/page-worker").Page({ 10 | contentScriptFile: data.url('icon-generator.js'), 11 | contentURL: data.url('icon-generator.html') 12 | }).port; 13 | port.on('icon', function(details) { 14 | callback({icon: details.icon}); 15 | }); 16 | port.emit('icon', {text: text}); 17 | } -------------------------------------------------------------------------------- /data/panel.js: -------------------------------------------------------------------------------- 1 | function populateTemplate(name, description, points, award, medal, styleCss) { 2 | document.getElementsByTagName("h1")[0].textContent = unescape(name); 3 | document.getElementsByTagName("h2")[0].textContent = unescape(description); 4 | document.getElementById("logo").classList.add(unescape(award)); 5 | document.getElementById("points").textContent = unescape(points); 6 | document.getElementById("medals").classList.add(unescape(medal)); 7 | document.getElementById("style").href = unescape(styleCss); 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jared Wein", 3 | "dependencies": ["addon-kit", "api-utils", "pathfinder"], 4 | "description": "Cheevos is an addon for Firefox that makes learning about different parts of the browser fun, as well as giving you the opportunity to brag to your friends about your pro-level web surfing.", 5 | "fullName": "Cheevos", 6 | "permissions": {"private-browsing": true}, 7 | "icon": "cheevos-toolbar-24x24.png", 8 | "id": "jid1-bpzDizt9E1R7nw", 9 | "name": "cheevos", 10 | "license": "MPL 1.1/GPL 2.0/LGPL 2.1", 11 | "version": "1.5" 12 | } 13 | -------------------------------------------------------------------------------- /data/icon-generator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | self.port.on('icon', function(details) { 4 | generateIcon(details.text); 5 | }); 6 | 7 | function generateIcon(aOverlayText) { 8 | let img = document.getElementById('icon'); 9 | let canvas = document.createElement('canvas'); 10 | canvas.setAttribute("width", 16); 11 | canvas.setAttribute("height", 16); 12 | let ctx = canvas.getContext("2d"); 13 | 14 | ctx.clearRect(0, 0, canvas.width, canvas.height); 15 | ctx.drawImage(img, 0, 0); 16 | 17 | if (aOverlayText) { 18 | ctx.textBaseline = "top"; 19 | ctx.textAlign = "center"; 20 | ctx.font = "9px sans-serif"; 21 | let height = 9; 22 | let y = canvas.height - height - 1; // 1 = bottom padding 23 | ctx.fillStyle = "#000"; 24 | ctx.strokeStyle = "#F5DEB3"; 25 | ctx.lineWidth = 4; 26 | ctx.strokeText(aOverlayText, canvas.width / 2, y); 27 | ctx.fillText(aOverlayText, canvas.width / 2, y); 28 | } 29 | 30 | self.port.emit('icon', {icon: canvas.toDataURL("image/png")}); 31 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Cheevos is an addon for Firefox that makes learning about different parts of the browser fun, as well as giving you the opportunity to brag to your friends about your pro-level web surfing. It contains: 2 | 3 | Technology used: 4 | 5 | * Mozilla Firefox Add-on SDK 6 | * JavaScript 7 | * CSS 8 | 9 | AUTHORS: 10 | 11 | * Jared Wein 12 | * Matthew Wein 13 | * Felipe Gomes 14 | * Matt Noorenberghe 15 | * Stephen Horlander 16 | * ... and you too, patches are welcome :) 17 | 18 | Special thanks to: 19 | 20 | * Stephen Horlander for the background of the Cheevo page and the design + graphics of the overlay 21 | * mfayaz on deviantART for the hand-drawn Firefox logo on the Cheevo page 22 | * Gozala on github for the jetpack-protocol library 23 | * Erik Vold on github for the toolbarbutton-jplib library 24 | -------------------------------------------------------------------------------- /data/cheevo.js: -------------------------------------------------------------------------------- 1 | function populateTemplate(tweetText, stats, cheevoBlocks, styleCss, cheevosFullName, cheevosTagLine, 2 | addOnHomepageLink, supportLink, authorHomepageLink) { 3 | if (!document.getElementById("cheevo-h1")) 4 | return; 5 | document.title = unescape(cheevosFullName); 6 | document.getElementById("cheevo-h1").textContent = unescape(cheevosFullName); 7 | document.getElementById("cheevo-h2").textContent = unescape(cheevosTagLine); 8 | document.getElementById("cheevo-message").textContent = unescape(stats); 9 | document.getElementById("cheevo-blocks").innerHTML = unescape(cheevoBlocks); 10 | document.getElementById("cheevo-stylesheet").href = unescape(styleCss); 11 | document.getElementById("addOnHomepageLink").textContent = unescape(addOnHomepageLink); 12 | document.getElementById("supportLink").textContent = unescape(supportLink); 13 | document.getElementById("authorHomepageLink").textContent = unescape(authorHomepageLink); 14 | document.getElementById("twitterLink").setAttribute("data-text", unescape(tweetText)); 15 | document.getElementById("twitterScript").src = 'https://platform.twitter.com/widgets.js'; 16 | } 17 | -------------------------------------------------------------------------------- /test/test-main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { Loader } = require('test-harness/loader'); 4 | const { data } = require('self'); 5 | const tabs = require('tabs'); 6 | const windowUtils = require("window-utils"); 7 | 8 | function $(id) windowUtils.activeBrowserWindow.document.getElementById(id); 9 | 10 | exports.testStylesheetIsRegistered = function(test) { 11 | let loader = Loader(module); 12 | loader.require('main'); 13 | test.assertEqual( 14 | require('userstyles').registered(data.url("chrome.css"), {type: 'agent'}), 15 | true, 16 | 'The cheeevos style sheet was registered' 17 | ); 18 | loader.unload(); 19 | }; 20 | 21 | exports.testAboutCheevos = function(test) { 22 | test.waitUntilDone(); 23 | let loader = Loader(module); 24 | loader.require('main'); 25 | tabs.open({ 26 | url: 'about:cheevos', 27 | inBackground: true, 28 | onReady: function(tab) { 29 | test.assertEqual(tab.url, 'about:cheevos', 'about:cheevos works'); 30 | test.assertEqual(tab.title, 'about:cheevos', 'about:cheevos works'); 31 | 32 | // end test 33 | tab.close(test.done()); 34 | } 35 | }); 36 | }; 37 | 38 | exports.testIconGenerator = function(test) { 39 | test.waitUntilDone(); 40 | let loader = Loader(module); 41 | loader.require('main'); 42 | let {generate} = loader.require('icon-generator'); 43 | generate({ 44 | onReady: function({icon}) { 45 | test.assertEqual($('cheevos-toolbarbutton').image, icon, 'the image is correct'); 46 | 47 | loader.unload(); 48 | 49 | // end test 50 | test.done(); 51 | }, 52 | text: '5' 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /data/cheevo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |

12 |

13 |

14 | 15 |
16 |
    17 |
    18 |
    19 | 20 | 21 | 22 |
    23 | 24 | -------------------------------------------------------------------------------- /lib/achievement-overlay.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const winUtils = require("sdk/deprecated/window-utils"); 4 | const {isBrowser} = require("sdk/window/utils"); 5 | const {unload} = require("addon/unload"); 6 | 7 | const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 8 | const NS_HTML = "http://www.w3.org/1999/xhtml"; 9 | 10 | const debug = false; 11 | 12 | exports.AchievementOverlay = function AchievementOverlay(options) { 13 | var unloaders = [], 14 | insertbefore = "browser-bottombox", 15 | destroyed = false, 16 | id = options.id; 17 | 18 | winUtils.WindowTracker(OverlayTracker(options, insertbefore, unloaders, destroyed)); 19 | 20 | return { 21 | destroy: function() { 22 | if (destroyed) return; 23 | destroyed = true; 24 | unloaders.forEach(function(unload) unload()); 25 | }, 26 | show: function(data) { 27 | for each (var window in winUtils.windowIterator()) { 28 | if (!isBrowser(window)) return; 29 | 30 | updateOverlay( 31 | id, data, function(id) window.document.getElementById(id)); 32 | } 33 | }, 34 | }; 35 | }; 36 | 37 | function updateOverlay(id, data, $) { 38 | let overlay = $(id); 39 | if (!overlay) return; 40 | 41 | $("cheevos-achievementOverlay-achievement").className = data.awardsClass; 42 | $("cheevos-achievementOverlay-h1").textContent = data.title; 43 | $("cheevos-achievementOverlay-h2").textContent = data.text; 44 | $("cheevos-achievementOverlay-points").textContent = data.points; 45 | $("cheevos-achievementOverlay-meta").className = data.awardsClass; 46 | 47 | overlay.hidden = false; 48 | // Trigger a reflow so the setting of the attributes are separate. 49 | overlay.boxObject.height; 50 | overlay.setAttribute("fadeOut", true); 51 | } 52 | 53 | function node(doc, ns, type, attrs, parent) { 54 | let ele = doc.createElementNS(ns, type); 55 | attrs && Object.keys(attrs).forEach(function(attr) { 56 | ele.setAttribute(attr, attrs[attr]); 57 | }); 58 | parent && parent.appendChild(ele); 59 | return ele; 60 | } 61 | 62 | function OverlayTracker(options, insertbefore, unloaders, destroyed) { 63 | let id = options.id; 64 | 65 | return { 66 | onTrack: function (window) { 67 | if (!isBrowser(window) || destroyed) return; 68 | 69 | let doc = window.document; 70 | function $(id) doc.getElementById(id); 71 | let xul = node.bind(null, doc, NS_XUL); 72 | let html = node.bind(null, doc, NS_HTML); 73 | 74 | let box1 = xul("hbox", { 75 | id: id, 76 | hidden: true 77 | }); 78 | let box2 = xul("hbox", {pack: "center"}, box1); 79 | let box3 = xul("hbox", {id: id + "-message"}, box2); 80 | let achievement = html("div", {id: id + "-achievement"}, box3); 81 | let award = html("img", {id: id + "-award"}, achievement); 82 | let h1 = html("h1", {id: id + "-h1"}, achievement); 83 | let h2 = html("h2", {id: id + "-h2"}, achievement); 84 | let meta = html("div", {id: id + "-meta"}, achievement); 85 | let points = html("div", {id: id + "-points"}, meta); 86 | let medals = html("ol", {id: id + "-medals"}, meta); 87 | let bronze = html("li", {}, medals); 88 | let silver = html("li", {}, medals); 89 | let gold = html("li", {}, medals); 90 | 91 | box1.addEventListener("command", function() { 92 | options.onCommand && options.onCommand({}); 93 | }, true); 94 | h1.textContent = "Cheevo acquired!"; 95 | 96 | let overlay = $(id); 97 | // if the overlay element dne, then add it 98 | if (!overlay) 99 | overlay = $("browser-panel").insertBefore(box1, $(insertbefore)); 100 | 101 | overlay.addEventListener("transitionend", function onAchievementHidden(event) { 102 | if (debug) 103 | console.log('onAchievementHidden reached'); 104 | if (event.propertyName != "opacity") 105 | return; 106 | if (overlay) { 107 | overlay.hidden = true; 108 | overlay.removeAttribute("fadeOut"); 109 | } 110 | }, false); 111 | 112 | unloaders.push(unload(function() { 113 | overlay.parentNode.removeChild(overlay); 114 | }, window)); 115 | } 116 | }; 117 | } 118 | -------------------------------------------------------------------------------- /data/chrome.css: -------------------------------------------------------------------------------- 1 | #cheevos-achievementOverlay { 2 | pointer-events: none; 3 | position: fixed; 4 | top: 0; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | } 9 | 10 | #cheevos-achievementOverlay > hbox { 11 | width: 100%; 12 | } 13 | 14 | #cheevos-achievementOverlay-message { 15 | font: 12px Segoe UI, Helvetica, sans-serif; 16 | color: #fff; 17 | position: absolute; 18 | bottom: 100px; 19 | left: 0; 20 | right: 0; 21 | margin: 0 auto; 22 | max-width: 400px; 23 | opacity: 1; 24 | -moz-transition: opacity 500ms linear 10s; 25 | } 26 | 27 | #cheevos-achievementOverlay[hidden] #cheevos-achievementOverlay-message { 28 | opacity: 0; 29 | -moz-transition: opacity 500ms linear 10s; 30 | } 31 | 32 | #cheevos-achievementOverlay[fadeOut] #cheevos-achievementOverlay-message { 33 | opacity: 0; 34 | -moz-transition: opacity 500ms linear 10s; 35 | } 36 | 37 | #cheevos-achievementOverlay-achievement { 38 | max-height: 100px; 39 | max-width: 400px; 40 | overflow: hidden; 41 | position: relative; 42 | background-image: url(noise-overlay-orange.png), 43 | -moz-linear-gradient(#a65d29, #591d09); 44 | border-radius: 3px; 45 | border: 1px solid #ff6; 46 | -moz-animation-name: achievementGlow; 47 | -moz-animation-duration: 2s; 48 | -moz-animation-iteration-count: infinite; 49 | } 50 | 51 | @-moz-keyframes achievementGlow { 52 | from { 53 | box-shadow: 0 0 25px #ff6; 54 | } 55 | 25% { 56 | box-shadow: 0 0 30px #ffa; 57 | } 58 | 50% { 59 | box-shadow: 0 0 25px #ffd4bf; 60 | } 61 | 75% { 62 | box-shadow: 0 0 30px #ffeecc; 63 | } 64 | to { 65 | box-shadow: 0 0 25px #ff6; 66 | } 67 | } 68 | 69 | #cheevos-achievementOverlay-award { 70 | float: left; 71 | width: 80px; 72 | height: 80px; 73 | margin: 10px; 74 | background-repeat: no-repeat, no-repeat; 75 | background-position: center, center; 76 | } 77 | 78 | #cheevos-achievementOverlay-achievement.bronze #cheevos-achievementOverlay-award { 79 | background-image: url(award-glyph-default-bronze.png), url(award-disc-background-bronze.png); 80 | } 81 | 82 | #cheevos-achievementOverlay-achievement.silver #cheevos-achievementOverlay-award { 83 | background-image: url(award-glyph-default-silver.png), url(award-disc-background-silver.png); 84 | } 85 | 86 | #cheevos-achievementOverlay-achievement.gold #cheevos-achievementOverlay-award { 87 | background-image: url(award-glyph-default-gold.png), url(award-disc-background-gold.png); 88 | } 89 | 90 | #cheevos-achievementOverlay-h1, #cheevos-achievementOverlay-h2 { 91 | color: white; 92 | margin: 0; 93 | text-shadow: 0 0 2px #333; 94 | font-weight: normal; 95 | } 96 | 97 | #cheevos-achievementOverlay-h1 { 98 | padding-top: 20px; 99 | } 100 | 101 | #cheevos-achievementOverlay-h2 { 102 | color: #F0B289; 103 | line-height: 16px; 104 | font-size: 16px; 105 | width: 325px; 106 | } 107 | 108 | #cheevos-achievementOverlay-meta { 109 | position: absolute; 110 | top: 0; 111 | right: 0; 112 | padding: 0; 113 | width: 75px; 114 | height: 100%; 115 | border-left: 1px groove rgba(0,0,0,.3); 116 | background-image: url(noise-overlay-orange.png), 117 | -moz-linear-gradient(#cc7333, #67220a); 118 | } 119 | 120 | #cheevos-achievementOverlay-points { 121 | width: 64px; 122 | height: 64px; 123 | margin: 0 auto; 124 | font-size: 24px; 125 | font-weight: bold; 126 | text-shadow: 0 0 2px #333; 127 | line-height: 60px; 128 | text-align: center; 129 | vertical-align: top; 130 | } 131 | 132 | #cheevos-achievementOverlay-meta.bronze #cheevos-achievementOverlay-points { 133 | background-image: url(point-ring-bronze.png); 134 | color: #ffd4bf; 135 | } 136 | 137 | #cheevos-achievementOverlay-meta.silver #cheevos-achievementOverlay-points { 138 | background-image: url(point-ring-silver.png); 139 | color: #e5eaff; 140 | } 141 | 142 | #cheevos-achievementOverlay-meta.gold #cheevos-achievementOverlay-points { 143 | background-image: url(point-ring-gold.png); 144 | color: #ffeecc; 145 | } 146 | 147 | #cheevos-achievementOverlay-medals { 148 | width: 100%; 149 | text-align: center; 150 | margin: 8px 0 0; 151 | padding: 0; 152 | list-style-type: none; 153 | } 154 | 155 | #cheevos-achievementOverlay-medals li { 156 | display: inline-block; 157 | min-width: 16px; 158 | max-width: 16px; 159 | min-height: 16px; 160 | max-height: 16px; 161 | margin: 0 3px; 162 | background-repeat: no-repeat; 163 | background-position: center; 164 | } 165 | 166 | #cheevos-achievementOverlay-meta.gold li:nth-child(1), 167 | #cheevos-achievementOverlay-meta.silver li:nth-child(1), 168 | #cheevos-achievementOverlay-meta.bronze li:nth-child(1) { 169 | background-image: url(star-bronze-filled.png); 170 | } 171 | 172 | #cheevos-achievementOverlay-meta.gold li:nth-child(2), 173 | #cheevos-achievementOverlay-meta.silver li:nth-child(2) { 174 | background-image: url(star-silver-filled.png); 175 | } 176 | 177 | #cheevos-achievementOverlay-meta.gold li:nth-child(3) { 178 | background-image: url(star-gold-filled.png); 179 | } 180 | 181 | #cheevos-achievementOverlay-meta.bronze li:nth-child(2) { 182 | background-image: url(star-silver-empty.png); 183 | } 184 | 185 | #cheevos-achievementOverlay-meta.bronze li:nth-child(3), 186 | #cheevos-achievementOverlay-meta.silver li:nth-child(3) { 187 | background-image: url(star-gold-empty.png); 188 | } 189 | -------------------------------------------------------------------------------- /data/cheevo.css: -------------------------------------------------------------------------------- 1 | html { 2 | background-color: #296AA4; 3 | background-image: url(background.jpg); 4 | background-repeat: no-repeat; 5 | background-position: top; 6 | background-attachment: fixed; 7 | } 8 | 9 | body { 10 | font-family: Georgia, serif; 11 | color: #333; 12 | font-size: 16px; 13 | margin: 0 auto; 14 | padding: 10px 10px 0; 15 | -moz-transition-timing-function: ease; 16 | -moz-transition-duration: 1000ms; 17 | } 18 | 19 | header { 20 | position: relative; 21 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAfCAYAAADwbH0HAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0REN0YwNzNBOTNGMTFERjgzM0NCNTVFOEI3QjAzMTMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0REN0YwNzRBOTNGMTFERjgzM0NCNTVFOEI3QjAzMTMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozREQ3RjA3MUE5M0YxMURGODMzQ0I1NUU4QjdCMDMxMyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozREQ3RjA3MkE5M0YxMURGODMzQ0I1NUU4QjdCMDMxMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pt7ILeIAAAO9SURBVHja7FZLbxNXFP489tgdnJjE18WprYCCeAYi8RJsKlXqH+umUqVWXbVddFMVUGtlw4ZiwiOKBFYgKo9acRAhGDckdmLqsYMfGHtim/mOcaRSQJ5dF77S1dxz7pnvnve9rvnUphoaGsKxcT/Wt4DM6hoikQgOht1YybeQy+UwsW8ce4PA4moN1WoVh/aFYXiBx8/tH+xxZO8I6k3gyWoe/WJpmUxGwDQNCHwCLC0tYXt7WwD5XVxchN8rpMil02moIWCXzcvn8zK5Js8JlqvT6SizCtxPPUU0GrW1NfCsABGamprC/pANsFZHNpvF6eMH5IB7T4qo1+s4OxmF5gLuLmVhGAbOHAqiXyyNp9NthUIBlmWJNh6bu7Gxgd5otVqyb7zVloeWy2X4dED3QNbkOcFyxROPVTgcxqkDI9h8CSQWHoh2hz/TsbxhibafnzuFsd3Ag6db4tovzx6WQ28ns2i32/ji5Dgs26M3F5bRL5ZYzJ8/NN63R/d+aK9vLMa41uio2JUF9TD9UpFeNTvq59gNlf6nI3QyU1G/Xb4jcqRv/bWu/rj1SNacXJPnBMsjMbNLIRgMQtf1bgbaitFlveF2uxEKhUSOGcxE4rC6CYtAILDD6xcLPJ21TG1KtY766eJV9Wj9tdD8ki5UutpSjvI9S5kfnD3aCZZnYmJCip6j/BqYnJyEx+PpZqT9JV2zrVA2TTnKs2SYvbSEcXvV7FrqBAs9bX84f0X9uWzuxOWr78/Ll/T9lZLst1pd+tqdlX9ZzpiS5wTLRZdQuxeFIoaHhzGudOS22jBNE0opREY0rJkWKpUK9oSC0pGyZl3qdEwFxJpNsywxjSoD/WJpv1+awbO/n0vXoeC3P15Ao9HAuaOfCjjpyKgu++y9lGdHOrE/IHXKyTV5TrBcDDr979PdaNopSEGv14tdPjdeNVpoNpvw+Xzw2i2oYbWk55JmR6o3ut3JsLsJs5f/9oulHY365Pb45dcL4hJqTsGvv/lOAEgXi0XZpxzl2YHiM9elI3HOXL8pPCdY/7GYLunRPQsZv3ctljp+2497NfuuxR/D0ubm5uS24B3J4E9PT4tLSFMwFoshHNCE5n06OzsrtwwnrUwmkzu0EywXC5q1VShuwe/3S/Dz5ba4hB2IgrmShVqthlBwRO7TzVJdbpk9o92afVGqSkcaGzXQL5bG+5UazM/PS5oP2+VCV8TjcfmSpmAikRA5ytOqVColtwwn1+Q5wXINnj6Dp8/g6TN4+gyePv/7p88bAQYAKrFdNP4leE0AAAAASUVORK5CYII=), 22 | url(firefox.png) no-repeat -moz-calc(100% + 30px) -moz-calc(100% + 40px), 23 | -moz-radial-gradient(bottom center 45deg, ellipse cover, rgba(255,255,255,.4) 0%, rgba(255,255,255,.3) 100%); 24 | padding: 10px; 25 | border-radius: 2.5px; 26 | margin-bottom: 10px; 27 | box-shadow: 0 0 10px #000; 28 | min-height: 125px; 29 | } 30 | 31 | #cheevo-h1 { 32 | margin-top: 0; 33 | margin-bottom: 0; 34 | font-weight: normal; 35 | } 36 | 37 | #cheevo-h2 { 38 | margin-top: 0; 39 | font-weight: normal; 40 | font-style: italic; 41 | } 42 | 43 | #cheevo-message { 44 | margin: 0; 45 | position: absolute; 46 | bottom: 10px; 47 | left: 10px; 48 | } 49 | 50 | #cheevo-h1, 51 | #cheevo-message, 52 | #cheevo-name, 53 | .cheevo-block { 54 | text-align: left; 55 | } 56 | 57 | #cheevo-blocks { 58 | margin: 0 0 10px; 59 | padding: 0; 60 | -moz-column-gap: 0; 61 | -moz-column-count: 3; 62 | background-color: rgba(255,255,255,0.3); 63 | border-radius: 2.5px; 64 | } 65 | 66 | .cheevo-block { 67 | vertical-align: top; 68 | -moz-box-sizing: border-box; 69 | padding: 10px; 70 | display: inline-block; 71 | margin: 0; 72 | position: relative; 73 | -moz-transition-timing-function: ease; 74 | -moz-transition-duration: 600ms; 75 | } 76 | 77 | .name { 78 | -moz-transition-delay: 400ms; 79 | -moz-transition-timing-function: ease; 80 | -moz-transition-duration: 200ms; 81 | margin-top: 0; 82 | } 83 | 84 | .message { 85 | padding: 5px 12px; 86 | -moz-transition: background-color 200ms linear; 87 | } 88 | 89 | .cheevo-block > h3 { 90 | border-radius: 2.5px; 91 | padding: 5px 12px; 92 | font-weight: normal; 93 | border-color: #2D53AF; 94 | background-image: -moz-radial-gradient(center center 45deg, ellipse contain, rgba(255,255,255,.3) 0%, rgba(255,255,255,.2) 100%); 95 | margin-bottom: 0; 96 | } 97 | 98 | .cheevo-block.achieved { 99 | background-image: -moz-radial-gradient(center center 45deg, ellipse contain, rgba(255,255,255,.3) 0%, rgba(255,255,255,.1) 100%); 100 | } 101 | 102 | .achieved > h3 { 103 | padding: 5px 12px; 104 | color: #856D42; 105 | text-shadow: 0 0 4px #E1763E; 106 | background-repeat: no-repeat; 107 | background-position: -moz-calc(100% - 12px), center; 108 | background-image: url(trophy_icon.png), 109 | -moz-linear-gradient(top, rgba(255,241,181,.8) 25%, rgba(228,199,127,.8) 100%) 110 | } 111 | 112 | .cheevo-block > p { 113 | margin-top: 0; 114 | } 115 | 116 | ol.awards { 117 | position: absolute; 118 | bottom: 10px; 119 | right: 10px; 120 | max-height: 16px; 121 | padding: 0; 122 | } 123 | 124 | ol.awards > li { 125 | display: inline-block; 126 | } 127 | 128 | .bronze, .silver, .gold { 129 | width: 20px; 130 | height: 20px; 131 | } 132 | 133 | div.bronze, div.silver, div.gold { 134 | position: absolute; 135 | bottom: 10px; 136 | right: 10px; 137 | } 138 | 139 | .learnMore { 140 | position: absolute; 141 | bottom: 10px; 142 | left: 10px; 143 | display: block; 144 | } 145 | 146 | a { 147 | color: #2D53AF; 148 | } 149 | 150 | .bronze { 151 | background: url(star-bronze-empty.png) no-repeat right; 152 | } 153 | 154 | .silver { 155 | background: url(star-silver-empty.png) no-repeat right; 156 | } 157 | 158 | .gold { 159 | background: url(star-gold-empty.png) no-repeat right; 160 | } 161 | 162 | .achieved > .bronze, .bronze.achieved { 163 | background: url(star-bronze-filled.png) no-repeat right; 164 | } 165 | 166 | .silver.achieved { 167 | background: url(star-silver-filled.png) no-repeat right; 168 | } 169 | 170 | .gold.achieved { 171 | background: url(star-gold-filled.png) no-repeat right; 172 | } 173 | 174 | #twitterLink { 175 | visibility: hidden; 176 | } 177 | 178 | .twitter-share-button { 179 | position: absolute; 180 | top: 10px; 181 | right: 10px; 182 | } 183 | 184 | footer { 185 | text-align: center; 186 | margin-bottom: 10px; 187 | } 188 | 189 | footer > a { 190 | margin: 0 20px; 191 | color: #222; 192 | text-decoration: none; 193 | } 194 | 195 | footer > a:hover { 196 | text-decoration: underline; 197 | } 198 | 199 | @media all and (min-width: 1200px) { 200 | body { 201 | width: 1023px; 202 | } 203 | .cheevo-block { 204 | width: 100%; 205 | height: 198px; 206 | } 207 | } 208 | 209 | @media all and (max-width: 1200px) and (min-width: 900px) { 210 | body { 211 | width: 824px; 212 | } 213 | .cheevo-block { 214 | width: 100%; 215 | height: 164px; 216 | } 217 | } 218 | 219 | @media all and (max-width: 900px) and (min-width: 620px) { 220 | body { 221 | width: 593px; 222 | font-size: 14px; 223 | } 224 | #cheevo-blocks { 225 | -moz-column-count: 2; 226 | } 227 | .cheevo-block { 228 | width: 100%; 229 | height: 176px; 230 | } 231 | } 232 | 233 | @media all and (max-width: 620px) and (min-width: 400px) { 234 | html { 235 | background-image: url(background-1024.jpg); 236 | } 237 | body { 238 | width: 398px; 239 | font-size: 12px; 240 | } 241 | #cheevo-blocks { 242 | -moz-column-count: 1; 243 | } 244 | .cheevo-block { 245 | width: 100%; 246 | min-height: 100px; 247 | } 248 | } 249 | 250 | @media all and (max-width: 400px) { 251 | html { 252 | background-image: url(background-1024.jpg); 253 | } 254 | body { 255 | width: 100%; 256 | font-size: 12px; 257 | padding: 0; 258 | } 259 | #cheevo-blocks { 260 | -moz-column-count: auto; 261 | } 262 | .cheevo-block { 263 | display: block; 264 | min-height: 80px; 265 | margin: 0; 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /locale/en-US.properties: -------------------------------------------------------------------------------- 1 | # LOCALIZATION NOTE: lwThemeChanged is the award that is granted when a user applies a 'persona' 2 | # or a 'lightweight theme'. The hint that is used references multiple personalities 3 | # because the award is granted based on the number of lightweight themes that a user applies. 4 | # LOCALIZATION NOTE: (lwThemeChanged.description): %s is the name of the browser, for example "Firefox" 5 | lwThemeChanged.description='Wearing' a persona is just one of the many ways to customize %s. 6 | lwThemeChanged.hint=I'm always telling myself I have multiple personalities. 7 | # LOCALIZATION NOTE: (lwThemeChanged.learnMoreLabel): %s is the name of the browser, for example "Firefox" 8 | lwThemeChanged.learnMoreLabel=Your %s, Your Style 9 | lwThemeChanged.name=Split Personalities 10 | 11 | # LOCALIZATION NOTE: dwRemoveDownload is the award that is granted when a user clears their download history. 12 | dmRemoveDownload.description=Keeping your downloads list clean can make it easier to find your special files. 13 | dmRemoveDownload.hint=Ever wanted to forget something you downloaded? 14 | dmRemoveDownload.learnMoreLabel=Downloads window 15 | dmRemoveDownload.name=Tidy up! 16 | 17 | # LOCALIZATION NOTE: privateBrowsingEnter is the award that is granted when a user enters private browsing. 18 | # Many users use private browsing to view websites that they don't want others to know about. 19 | # This hint is used because many people claim that they are "buying gifts". 20 | # LOCALIZATION NOTE: (privateBrowsingEnter.description): %s is the name of the browser, for example "Firefox" 21 | privateBrowsingEnter.description=In Private Browsing mode, %s won't keep any history or cookies. 22 | privateBrowsingEnter.hint=All your secrets are belong to you. 23 | privateBrowsingEnter.learnMoreLabel=Private Browsing 24 | privateBrowsingEnter.name=Shopping for gifts? 25 | 26 | # LOCALIZATION NOTE: pmLoginAdded is the award that is granted when a user has Firefox remember their password. 27 | # Many users remember passwords by writing them on small pieces of paper and hiding them near 28 | # their computer. Post-it Notes are a popular brand of stationary that is used to short things. 29 | pmLoginAdded.description=The Password Manager securely stores the usernames and passwords so you don't have to. 30 | pmLoginAdded.hint=An improvement over hidden Post-it Notes. 31 | pmLoginAdded.learnMoreLabel=Password Manager 32 | pmLoginAdded.name=hunter2 33 | 34 | # LOCALIZATION NOTE: homepageChanged is the award that is granted when a user changes their homepage. 35 | # In "The Wizard of Oz" movie, Dorothy says "there's no place like home", which is where 36 | # the hint comes from. 37 | # LOCALIZATION NOTE: (homepageChanged.description): %s is the name of the browser, for example "Firefox" 38 | homepageChanged.description=Setting a homepage allows you to see your favorite webpage every time you open %s. 39 | homepageChanged.hint=There's no place like home. 40 | homepageChanged.learnMoreLabel=Setting a home page 41 | homepageChanged.name=Home Sweet Home 42 | 43 | # LOCALIZATION NOTE: addOnsOpened is the award that is granted when the user views their add-ons or customizes 44 | # their toolbar. "Go-go-gadget" is the phrase used by Inspector Gadget, a character from a popular 45 | # kid's cartoon, when he wanted to use one of his extensions to increase his capabilities. 46 | # LOCALIZATION NOTE: (addOnsOpened.description): %s is the name of the browser, for example "Firefox" 47 | addOnsOpened.description=Add-ons provide thousands of extra features and styles to make %s your own. 48 | addOnsOpened.hint=Go-go-gadget! 49 | addOnsOpened.learnMoreLabel=Find more 50 | addOnsOpened.name=Inspector Gadget 51 | 52 | # LOCALIZATION NOTE: aboutMisc is the award that is granted when a user visits the various "about:" pages in Firefox. 53 | # The hint is used because it is a popular phrase that contains the word "about". Sorry, it's not 54 | # that creative ;) 55 | aboutMisc.description=Mozilla has a long history of adding both quirky and useful about: pages. 56 | aboutMisc.hint=Have I ever told you about... 57 | aboutMisc.learnMoreLabel=Learn more 58 | aboutMisc.name=Let's talk about it 59 | 60 | # LOCALIZATION NOTE: configOpened is the award that is granted when a user visits about:config. 61 | # The hint is used because the en-US locale has a "This might void your warranty!" warning. 62 | configOpened.description=At 'about:config' all user preferences can be viewed and modified. 63 | configOpened.hint=It's about time you void your warranty! 64 | configOpened.learnMoreLabel=Learn more 65 | configOpened.name=Super User 66 | 67 | # LOCALIZATION NOTE: knowUrRights is the award that is granted when a user visits about:rights. 68 | # LOCALIZATION NOTE: (knowUrRights.description): %s is the name of the browser, for example "Firefox" 69 | knowUrRights.description=You may use, modify, copy and distribute %s to others. 70 | knowUrRights.hint=Users of Firefox are granted these rights. 71 | knowUrRights.learnMoreLabel=The Mozilla Manifesto 72 | knowUrRights.name=Know Your Rights 73 | 74 | # LOCALIZATION NOTE: "many places at the same time" is a popular phrase that generally means to 75 | # perform many actions at once. 76 | frequentFlyer.description=Open multiple tabs at the same time for super-advanced high speed browsing. 77 | frequentFlyer.hint=Have you ever been in many places at the same time? 78 | frequentFlyer.name=Same time, same place 79 | 80 | # LOCALIZATION NOTE: revolutionTelevised is the award that is granted when a user visits air.mozilla.org. 81 | # The hint references a popular quote "The Revolution Will Not Be Televised", which fits 82 | # well with the revolution in software freedome that Mozilla is a part of. 83 | revolutionTelevised.description=Air Mozilla is the Internet multimedia presence of Mozilla. 84 | revolutionTelevised.hint=The Revolution Will Not Be Televised 85 | revolutionTelevised.learnMoreLabel=Tune in 86 | revolutionTelevised.name=Mozilla, in Video 87 | 88 | # LOCALIZATION NOTE: yoDawg is the award that is granted when a user visits chrome://browser/content/browser.xul 89 | # See http://msujaws.wordpress.com/2012/01/12/how-to-guide-for-the-esoteric-cheevos-in-cheevos-for-firefox-part-1/ 90 | # for an explanation of the Yo Dawg achievement. 91 | # LOCALIZATION NOTE: (yoDawg.description): %s is the name of the browser, for example "Firefox" 92 | yoDawg.description=%s is made using XUL, JavaScript, and CSS. Very similar technology to websites. 93 | yoDawg.hint=I heard you like browsers 94 | yoDawg.learnMoreLabel=Learn more 95 | yoDawg.name=Yo Dawg 96 | 97 | # LOCALIZATION NOTE: bookmarkAdded is the award that is granted when users add bookmarks. 98 | # The hint references the star icon that is used to symbolize bookmarking, or "starring", 99 | # a website that a user would like to come back to later. 100 | bookmarkAdded.description=Bookmarks keep track of websites that you would like to come back to. 101 | bookmarkAdded.hint=My God, it's full of stars! 102 | bookmarkAdded.learnMoreLabel=Learn more 103 | bookmarkAdded.name=Dog eared 104 | 105 | # LOCALIZATION NOTE: feedbackSubmitted is the award that is granted when a user enters feedback at input.mozilla.org. 106 | # The hint is a reference to a popular childrens song "If you're happy and you know it". 107 | # LOCALIZATION NOTE: (feedbackSubmitted.description): %s is the name of the browser, for example "Firefox" 108 | feedbackSubmitted.description=Your feedback will be used to create a better experience in future releases of %s. 109 | feedbackSubmitted.hint=If you're happy and you know it... 110 | feedbackSubmitted.learnMoreLabel=Submit more feedback 111 | feedbackSubmitted.name=Your opinion matters 112 | 113 | # LOCALIZATION NOTE: releaseChannels is the award that is granted when a user uses Beta, Aurora, or Nightly versions of Firefox. 114 | # LOCALIZATION NOTE: (releaseChannels.description): %s is the name of the browser, for example "Firefox" 115 | releaseChannels.description=Thanks for testing the latest innovations in %s. 116 | releaseChannels.hint=The future comes one day at a time. 117 | # LOCALIZATION NOTE: (releaseChannels.learnMoreLabel): %s is the name of the browser, for example "Firefox" 118 | releaseChannels.learnMoreLabel=How you can help %s 119 | releaseChannels.name=Back to the Future! 120 | 121 | # LOCALIZATION NOTE: devTools is the award that is granted when a users uses one of the many native devtools. 122 | # "Made with Notepad" is the name of the addon because many web developers started making 123 | # websites by using very basic text editors like Microsoft's Notepad. 124 | # LOCALIZATION NOTE: (devTools.description): %s is the name of the browser, for example "Firefox" 125 | devTools.description=%s comes out of the box with some of the best tools for web development. 126 | devTools.hint=The ultimate tool for web developers. 127 | devTools.learnMoreLabel=hacks.mozilla.org 128 | devTools.name=Made with Notepad 129 | 130 | # LOCALIZATION NOTE: sociallyAwesomePenguin is the award that is granted when a user visits a specific social site many times. 131 | # The hint is a reference to Facebook's popular "like" button. 132 | # The name is a reference to the idea that everyone is connected by approximitely six relationships. 133 | sociallyAwesomePenguin.description=Everybody knows everybody in your social networking site. 134 | sociallyAwesomePenguin.hint=Where is the dislike button? 135 | sociallyAwesomePenguin.name=6deg of separation 136 | 137 | # LOCALIZATION NOTE: socialButterfly is the award that is granted when a users visits multiple social networking sites. 138 | # The name "social butterfly" is a person who very social and outgoing. 139 | # The hint references FaceSpace, a combination of Facebook and MySpace. 140 | # LOCALIZATION NOTE: (socialButterfly.description): %s is the name of the browser, for example "Firefox" 141 | socialButterfly.description=%s is the best tool for checking in on your social networks. 142 | socialButterfly.hint=Can you retweet my post on FaceSpace? 143 | socialButterfly.name=Social butterfly 144 | 145 | # LOCALIZATION NOTE: tabCandy is the award that is gratned when a user opens many tabs over the lifetime of using Firefox. 146 | # The name is a reference to the codename for the Tab Groups feature of Firefox (also known as Panorama). 147 | tabCandy.description=Tabs provide a great user interface for viewing multiple websites at the same time. 148 | tabCandy.hint=Oooh, tabs are teh pretty 149 | tabCandy.name=Tab Candy 150 | 151 | # LOCALIZATION NOTE: concurrentTabs is the award that is granted when a user opens many tabs in a single browsing session. 152 | concurrentTabs.description=Tabs provide a great user interface for viewing multiple websites at the same time. 153 | concurrentTabs.hint=Whoa, so many tabs dude! 154 | concurrentTabs.name=Concurrent Tabs 155 | 156 | # LOCALIZATION NOTE: geekCred is the award that is granted when a user visits one of a list of sites popular with the tech crowd. 157 | # The hint references "upvotes", which are used to promote a topic on sites like Reddit and Hacker News. 158 | geekCred.description=Online communities are a great way to find people with similar interests. 159 | geekCred.hint=So I was browsing today and I found some upvotes... 160 | geekCred.name=Geek Cred 161 | 162 | # LOCALIZATION NOTE: newsJunkie is the award that is granted when a user visits a news website multiple times. The hint 163 | # references the increasing use of "Breaking News" to gain reader attention. 164 | newsJunkie.description=News websites have dramatically changed how we learn about current events. 165 | newsJunkie.hint=Addicted to the LATEST & BREAKING! 166 | newsJunkie.name=News Junkie 167 | 168 | # LOCALIZATION NOTE: cheevosTheyreGreat is the award that is granted when a user visits about:cheevos, the Cheevo's AMO listing 169 | # and the Cheevos website. 170 | cheevosTheyreGreat.description=Achievements are a great way to add fun to your browsing. 171 | cheevosTheyreGreat.hint=They're G-r-r-reat! 172 | cheevosTheyreGreat.name=Cheeeeeevos! 173 | 174 | # LOCALIZATION NOTE: noun.news is used to search the title of websites to determine if they focus on news and current events. 175 | noun.news=news 176 | 177 | # LOCALIZATION NOTE (points): %s is the number of points the user has scored 178 | points=%s points scored 179 | 180 | # LOCALIZATION NOTE (tweetText): %1s is the number of points the user has scored 181 | # %2s is the addOnShortName 182 | # %3s is the name of the browser, for example "Firefox" 183 | tweetText=I've got %1s points with %2s for %3s. How many points can you score? 184 | 185 | # LOCALIZATION NOTE (stats): %1s is the number of points the user has scored. 186 | # %2s is the number of awards the user has scored. 187 | # %3s is the number of awards available. 188 | stats=You've got %1s points, with %2s/%3s awards. 189 | 190 | addOnShortName=Cheevos 191 | # LOCALIZATION NOTE: (addOnFullName): %1s is the addOnShortName, for example "Cheevos". 192 | # %2s is the name of the browser, for example "Firefox". 193 | addOnFullName=%1s for %2s 194 | # LOCALIZATION NOTE: (addOnTagLine): %1s is the name of the browser. 195 | addOnTagLine=Use %s, gain achievements. 196 | 197 | addOnHomepageLink=add-on homepage 198 | supportLink=support 199 | authorHomepageLink=author's homepage 200 | -------------------------------------------------------------------------------- /locale/el-GR.properties: -------------------------------------------------------------------------------- 1 | # LOCALIZATION NOTE: lwThemeChanged is the award that is granted when a user applies a 'persona' 2 | # or a 'lightweight theme'. The hint that is used references multiple personalities 3 | # because the award is granted based on the number of lightweight themes that a user applies. 4 | # LOCALIZATION NOTE: (lwThemeChanged.description): %s is the name of the browser, for example "Firefox" 5 | lwThemeChanged.description=Το να «φοράς» ένα persona είναι ένας από τους πολλούς τρόπους να προσαρμόσεις τον %s. 6 | lwThemeChanged.hint=Όλο λέω στον εαυτό μου ότι έχω πολλαπλές προσωπικότητες. 7 | # LOCALIZATION NOTE: (lwThemeChanged.learnMoreLabel): %s is the name of the browser, for example "Firefox" 8 | lwThemeChanged.learnMoreLabel=Ο δικός σου %s, το δικό σου στυλ. 9 | lwThemeChanged.name=Διχασμένη Προσωπικότητα 10 | 11 | # LOCALIZATION NOTE: dwRemoveDownload is the award that is granted when a user clears their download history. 12 | dmRemoveDownload.description=Το να έχεις τη λίστα των ληφθέντων αρχείων σου άδεια σε βοηθάει να βρεις πιο εύκολα συγκεκριμένα αρχεία. 13 | dmRemoveDownload.hint=Σου έχει τύχει ποτέ να θέλεις να ξεχάσεις κάτι που κατέβασες; 14 | dmRemoveDownload.learnMoreLabel=Παράθυρο ληφθέντων αρχείων 15 | dmRemoveDownload.name=Συμμάζεψε! 16 | 17 | # LOCALIZATION NOTE: privateBrowsingEnter is the award that is granted when a user enters private browsing. 18 | # Many users use private browsing to view websites that they don't want others to know about. 19 | # This hint is used because many people claim that they are "buying gifts". 20 | # LOCALIZATION NOTE: (privateBrowsingEnter.description): %s is the name of the browser, for example "Firefox" 21 | privateBrowsingEnter.description=Στην Ιδιωτική Περιήγηση, ο %s δεν αποθηκεύει το ιστορικό ή τα cookies. 22 | privateBrowsingEnter.hint=Όλα σου τα μυστικά ανήκουν σε σένα. 23 | privateBrowsingEnter.learnMoreLabel=Ιδιωτική Περιήγηση 24 | privateBrowsingEnter.name=Δώρα αγοράζουμε; 25 | 26 | # LOCALIZATION NOTE: pmLoginAdded is the award that is granted when a user has Firefox remember their password. 27 | # Many users remember passwords by writing them on small pieces of paper and hiding them near 28 | # their computer. Post-it Notes are a popular brand of stationary that is used to short things. 29 | pmLoginAdded.description=Ο Διαχειριστής Κωδικών αποθηκεύει με ασφάλεια τα ονόματα χρήστη και τους κωδικούς για σένα. 30 | pmLoginAdded.hint=Βελτίωση σε σύγκριση με κρυμμένα Post-it. 31 | pmLoginAdded.learnMoreLabel=Διαχειριστής Κωδικών 32 | pmLoginAdded.name=hunter2 33 | 34 | # LOCALIZATION NOTE: homepageChanged is the award that is granted when a user changes their homepage. 35 | # In "The Wizard of Oz" movie, Dorothy says "there's no place like home", which is where 36 | # the hint comes from. 37 | # LOCALIZATION NOTE: (homepageChanged.description): %s is the name of the browser, for example "Firefox" 38 | homepageChanged.description=Το να ορίζεις Αρχική σελίδα σημαίνει ότι μπορείς να βλέπεις την αγαπημένη σου σελίδα κάθε φορά που ανοίγεις τον %s. 39 | homepageChanged.hint=Είναι ωραίο να είσαι στο σπίτι. 40 | homepageChanged.learnMoreLabel=Ορίζοντας Αρχικής σελίδα. 41 | homepageChanged.name=Σπίτι μου, σπιτάκι μου. 42 | 43 | # LOCALIZATION NOTE: addOnsOpened is the award that is granted when the user views their add-ons or customizes 44 | # their toolbar. "Go-go-gadget" is the phrase used by Inspector Gadget, a character from a popular 45 | # kid's cartoon, when he wanted to use one of his extensions to increase his capabilities. 46 | # LOCALIZATION NOTE: (addOnsOpened.description): %s is the name of the browser, for example "Firefox" 47 | addOnsOpened.description=Τα Πρόσθετα σου προσφέρουν χιλιάδες έξτρα λειτουργίες και θέματα για να κάνεις τον %s όπως σου ταιριάζει. 48 | addOnsOpened.hint=Εμπρός καλό μου πρόσθετο! 49 | addOnsOpened.learnMoreLabel=Βρες περισσότερα 50 | addOnsOpened.name=Αστυνόμος Σαΐνης 51 | 52 | # LOCALIZATION NOTE: aboutMisc is the award that is granted when a user visits the various "about:" pages in Firefox. 53 | # The hint is used because it is a popular phrase that contains the word "about". Sorry, it's not 54 | # that creative ;) 55 | aboutMisc.description=Ο Mozilla έχει μεγάλη ιστορία όσον αφορά το να βάζει και ιδιότροπες και χρήσιμες about: σελίδες. 56 | aboutMisc.hint=Σου έχω μιλήσει ποτέ σχετικά με... 57 | aboutMisc.learnMoreLabel=Μάθε περισσότερα 58 | aboutMisc.name=Ας το συζητήσουμε 59 | 60 | # LOCALIZATION NOTE: configOpened is the award that is granted when a user visits about:config. 61 | # The hint is used because the en-US locale has a "This might void your warranty!" warning. 62 | configOpened.description=Στο 'about:config' όλες οι επιλογές μπορούν να προβληθούν και να τροποποιηθούν. 63 | configOpened.hint=Είναι ώρα να χάσεις την εγγύηση! 64 | configOpened.learnMoreLabel=Μάθε περισσότερα 65 | configOpened.name=Super User 66 | 67 | # LOCALIZATION NOTE: knowUrRights is the award that is granted when a user visits about:rights. 68 | # LOCALIZATION NOTE: (knowUrRights.description): %s is the name of the browser, for example "Firefox" 69 | knowUrRights.description=Μπορείς να χρησιμοποιήσεις, τροποποιήσεις, αντιγράψεις και διανέμεις τον %s σε άλλους. 70 | knowUrRights.hint=Οι χρήστες του Firefox χορηγούνται αυτά τα δικαιώματα. 71 | knowUrRights.learnMoreLabel=Η Διακήρυξη του Mozilla. 72 | knowUrRights.name=Μάθε τα δικαιώματα σου 73 | 74 | # LOCALIZATION NOTE: "many places at the same time" is a popular phrase that generally means to 75 | # perform many actions at once. 76 | frequentFlyer.description=Άνοιξε πολλαπλές καρτέλες ταυτόχρονα για υπέρ-προηγμένη και υψηλής ταχύτητας περιήγηση. 77 | frequentFlyer.hint=Έχεις βρεθεί ποτέ σε πολλά μέρη την ίδια χρονική στιγμή; 78 | frequentFlyer.name=Ίδια ώρα, ίδιο μέρος 79 | 80 | # LOCALIZATION NOTE: revolutionTelevised is the award that is granted when a user visits air.mozilla.org. 81 | # The hint references a popular quote "The Revolution Will Not Be Televised", which fits 82 | # well with the revolution in software freedome that Mozilla is a part of. 83 | revolutionTelevised.description=Το Air Mozilla είναι η διαδικτυακή παρουσία πολυμέσων του Mozilla. 84 | revolutionTelevised.hint=The Revolution Will Not Be Televised 85 | revolutionTelevised.learnMoreLabel=Συντονίσου 86 | revolutionTelevised.name=Mozilla, σε βίντεο 87 | 88 | # LOCALIZATION NOTE: yoDawg is the award that is granted when a user visits chrome://browser/content/browser.xul 89 | # See http://msujaws.wordpress.com/2012/01/12/how-to-guide-for-the-esoteric-cheevos-in-cheevos-for-firefox-part-1/ 90 | # for an explanation of the Yo Dawg achievement. 91 | # LOCALIZATION NOTE: (yoDawg.description): %s is the name of the browser, for example "Firefox" 92 | yoDawg.description=Ο %s φτιάχνεται χρησιμοποιώντας XUL, JavaScript, και CSS. Παρόμοια τεχνολογία με αυτή των ιστοσελίδων. 93 | yoDawg.hint=Έμαθα σου αρέσουν οι περιηγητές 94 | yoDawg.learnMoreLabel=Μάθε περισσότερα 95 | yoDawg.name=Yo Dawg 96 | 97 | # LOCALIZATION NOTE: bookmarkAdded is the award that is granted when users add bookmarks. 98 | # The hint references the star icon that is used to symbolize bookmarking, or "starring", 99 | # a website that a user would like to come back to later. 100 | bookmarkAdded.description=Με τους Σελιδοδείκτες μπορείς να αποθηκεύεις σελίδες που θέλεις να ξαναεπισκεπτείς. 101 | bookmarkAdded.hint=My God, it's full of stars! 102 | bookmarkAdded.learnMoreLabel=Μάθε περισσότερα 103 | bookmarkAdded.name=Τσάκισμα σελίδας 104 | 105 | # LOCALIZATION NOTE: feedbackSubmitted is the award that is granted when a user enters feedback at input.mozilla.org. 106 | # The hint is a reference to a popular childrens song "If you're happy and you know it". 107 | # LOCALIZATION NOTE: (feedbackSubmitted.description): %s is the name of the browser, for example "Firefox" 108 | feedbackSubmitted.description=Τα σχόλια σου θα ληφθούν υπόψη για την βελτίωση του %s στο μέλλον. 109 | feedbackSubmitted.hint=If you're happy and you know it... 110 | feedbackSubmitted.learnMoreLabel=Υπέβαλε περισσότερα σχόλια 111 | feedbackSubmitted.name=Η γνώμη σου μετράει 112 | 113 | # LOCALIZATION NOTE: releaseChannels is the award that is granted when a user uses Beta, Aurora, or Nightly versions of Firefox. 114 | # LOCALIZATION NOTE: (releaseChannels.description): %s is the name of the browser, for example "Firefox" 115 | releaseChannels.description=Ευχαριστούμε για τη δοκιμή των τελευταίων καινοτομιών του %s. 116 | releaseChannels.hint=Το μέλλον έρχεται μέρα με την μέρα. 117 | # LOCALIZATION NOTE: (releaseChannels.learnMoreLabel): %s is the name of the browser, for example "Firefox" 118 | releaseChannels.learnMoreLabel=Πώς μπορείς να βοηθήσεις τον %s 119 | releaseChannels.name=Επιστροφή στο Μέλλον! 120 | 121 | # LOCALIZATION NOTE: devTools is the award that is granted when a users uses one of the many native devtools. 122 | # "Made with Notepad" is the name of the addon because many web developers started making 123 | # websites by using very basic text editors like Microsoft's Notepad. 124 | # LOCALIZATION NOTE: (devTools.description): %s is the name of the browser, for example "Firefox" 125 | devTools.description=Ο %s έχει κάποια από τα καλύτερα εργαλεία για web development. 126 | devTools.hint=Το απόλυτο εργαλείο για τους web developers. 127 | devTools.learnMoreLabel=hacks.mozilla.org 128 | devTools.name=Made with Notepad 129 | 130 | # LOCALIZATION NOTE: sociallyAwesomePenguin is the award that is granted when a user visits a specific social site many times. 131 | # The hint is a reference to Facebook's popular "like" button. 132 | # The name is a reference to the idea that everyone is connected by approximitely six relationships. 133 | sociallyAwesomePenguin.description=Όλοι γνωρίζονται μεταξύ τους στη σελίδα κοινωνικής δικτύωσης σου. 134 | sociallyAwesomePenguin.hint=Πού είναι το dislike; 135 | sociallyAwesomePenguin.name=6deg of separation 136 | 137 | # LOCALIZATION NOTE: socialButterfly is the award that is granted when a users visits multiple social networking sites. 138 | # The name "social butterfly" is a person who very social and outgoing. 139 | # The hint references FaceSpace, a combination of Facebook and MySpace. 140 | # LOCALIZATION NOTE: (socialButterfly.description): %s is the name of the browser, for example "Firefox" 141 | socialButterfly.description=Ο %s είναι το καλύτερο εργαλέιο για να βλέπεις τις σελίδες κοινωνικής δικτύωσης σου. 142 | socialButterfly.hint==Μπορείς να κάνεις retweet το post μου στο FaceSpace; 143 | socialButterfly.name=Κοινωνικός τύπος 144 | 145 | # LOCALIZATION NOTE: tabCandy is the award that is gratned when a user opens many tabs over the lifetime of using Firefox. 146 | # The name is a reference to the codename for the Tab Groups feature of Firefox (also known as Panorama). 147 | tabCandy.description=Οι καρτέλες σε βοηθάνε να βλέπεις πολλές σελίδες ταυτόχρονα. 148 | tabCandy.hint=Ααα, οι καρτέλες είναι οι πιο όμορφες 149 | tabCandy.name=Tab Candy 150 | 151 | # LOCALIZATION NOTE: concurrentTabs is the award that is granted when a user opens many tabs in a single browsing session. 152 | concurrentTabs.description=Οι καρτέλες σε βοηθάνε να βλέπεις πολλές σελίδες ταυτόχρονα. 153 | concurrentTabs.hint=Μαν, πολλές καρτέλες έχεις! 154 | concurrentTabs.name=Ταυτόχρονες καρτέλες 155 | 156 | # LOCALIZATION NOTE: geekCred is the award that is granted when a user visits one of a list of sites popular with the tech crowd. 157 | # The hint references "upvotes", which are used to promote a topic on sites like Reddit and Hacker News. 158 | geekCred.description=Οι οnline κοινότητες είναι ένας ωραίος τρόπος να βρίσκεις ανθρώπους με κοινά ενδιαφέροντα. 159 | geekCred.hint=Σήμερα βρήκα κάτι upvotes... 160 | geekCred.name=Geek Cred 161 | 162 | # LOCALIZATION NOTE: newsJunkie is the award that is granted when a user visits a news website multiple times. The hint 163 | # references the increasing use of "Breaking News" to gain reader attention. 164 | newsJunkie.description=Οι ειδησεογραφικές ιστοσελίδες έχουν αλλάξει δραματικά το πώς μαθαίνουμε τα γεγονότα. 165 | newsJunkie.hint=Εθισμένοι στα ΕΚΤΑΚΤΑ δελτία ειδήσεων! 166 | newsJunkie.name=Γεγονοτομανής 167 | 168 | # LOCALIZATION NOTE: cheevosTheyreGreat is the award that is granted when a user visits about:cheevos, the Cheevo's AMO listing 169 | # and the Cheevos website. 170 | cheevosTheyreGreat.description=Τα achievements είναι ένας καλός τρόπος για να διασκεδάζεις όταν σερφάρεις στο διαδίκτυο. 171 | cheevosTheyreGreat.hint=Είναι Τέ-λει-α! 172 | cheevosTheyreGreat.name=Cheeeeeevos! 173 | 174 | # LOCALIZATION NOTE: noun.news is used to search the title of websites to determine if they focus on news and current events. 175 | noun.news=news 176 | 177 | # LOCALIZATION NOTE (points): %s is the number of points the user has scored 178 | points=%s κερδισμένοι πόντοι 179 | 180 | # LOCALIZATION NOTE (tweetText): %1s is the number of points the user has scored 181 | # %2s is the addOnShortName 182 | # %3s is the name of the browser, for example "Firefox" 183 | tweetText=Έχω %1s πόντους με τα %2s για τον %3s. Πόσους μπορείς να μαζέψεις; 184 | 185 | # LOCALIZATION NOTE (stats): %1s is the number of points the user has scored. 186 | # %2s is the number of awards the user has scored. 187 | # %3s is the number of awards available. 188 | stats=Έχεις μαζέψει %1s πόντους, με %2s/%3s βραβεία. 189 | 190 | addOnShortName=Cheevos 191 | # LOCALIZATION NOTE: (addOnFullName): %1s is the addOnShortName, for example "Cheevos". 192 | # %2s is the name of the browser, for example "Firefox". 193 | addOnFullName=%1s για %2s 194 | # LOCALIZATION NOTE: (addOnTagLine): %1s is the name of the browser. 195 | addOnTagLine=Χρησιμοποίησε %s, κέρδισε achievements. 196 | 197 | addOnHomepageLink=σελίδα πρόσθετου 198 | supportLink=υποστήριξη 199 | authorHomepageLink=σελίδα δημιουργού 200 | -------------------------------------------------------------------------------- /lib/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const ao = require("achievement-overlay"), 4 | {Cc,Ci,Cu} = require("chrome"), 5 | BrandStringBundle = Cc["@mozilla.org/intl/stringbundle;1"] 6 | .getService(Ci.nsIStringBundleService) 7 | .createBundle("chrome://branding/locale/brand.properties"), 8 | {data} = require("sdk/self"), 9 | events = require("sdk/system/events"), 10 | {listen} = require("xul/listen"), 11 | {MatchPattern} = require("sdk/util/match-pattern"), 12 | ss = require("sdk/simple-storage").storage, 13 | tabs = require("sdk/tabs"), 14 | {unload} = require("addon/unload"), 15 | urlFactory = require("sdk/url"), 16 | winUtils = require("sdk/deprecated/window-utils"), 17 | _ = require("sdk/l10n").get, 18 | SimplePrefs = require("sdk/simple-prefs"), 19 | PrivateBrowsing = require("sdk/private-browsing"); 20 | 21 | const brandShortName = BrandStringBundle.GetStringFromName("brandShortName"); 22 | const aboutCheevosUrl = "about:cheevos"; 23 | const addOnAchievementObs = "cheevos.api.add-on-achievement"; 24 | 25 | let objHolder = {}; 26 | Cu.import("resource://gre/modules/PlacesUtils.jsm", objHolder); 27 | let PlacesUtils = objHolder.PlacesUtils; 28 | 29 | const debug = false; 30 | log("cheevos loaded"); 31 | 32 | const PTS_PER_BASIC = 5, 33 | PTS_PER_BRONZE = 5, 34 | PTS_PER_SILVER = 10, 35 | PTS_PER_GOLD = 25; 36 | let totalAwards = 0, 37 | acquiredAwards = 0, 38 | acquiredPoints = 0, 39 | unloaders = [], 40 | destroyFuncs = []; 41 | let socialSites = ["*.facebook.com", 42 | "*.twitter.com", 43 | "*.linkedin.com", 44 | "*.myspace.com", 45 | "*.ning.com", 46 | "*.plus.google.com", 47 | "*.tagged.com", 48 | "*.orkut.com", 49 | "*.hi5.com", 50 | "*.renren.com"], 51 | geekCredSites = ["*.reddit.com", 52 | "*.stackoverflow.com", 53 | "*.ycombinator.com", 54 | "*.slashdot.org", 55 | "*.stumbleupon.com"]; 56 | 57 | let cheevos = { 58 | lwThemeChanged: { 59 | id: "lightweight-theme-changed", 60 | obs: "lightweight-theme-changed", 61 | description: _("lwThemeChanged.description", brandShortName), 62 | hint: _("lwThemeChanged.hint"), 63 | learnMoreUrl: "http://www.getpersonas.com", 64 | learnMoreLabel: _("lwThemeChanged.learnMoreLabel", brandShortName), 65 | name: _("lwThemeChanged.name"), 66 | subAwards: true, 67 | bronzeId: "lightweight-theme-changed", /* migrated from generic award */ 68 | silverId: "lightweight-theme-changedSilver", 69 | goldId: "lightweight-theme-changedGold" 70 | }, 71 | dmRemoveDownload: { 72 | id: "download-manager-remove-download", 73 | obs: "download-manager-remove-download", 74 | description: _("dmRemoveDownload.description"), 75 | hint: _("dmRemoveDownload.hint"), 76 | learnMoreUrl: "http://support.mozilla.com/kb/Downloads window", 77 | learnMoreLabel: _("dmRemoveDownload.learnMoreLabel"), 78 | name: _("dmRemoveDownload.name"), 79 | subAwards: true, 80 | bronzeId: "dmRemoveDownloadBronze", 81 | silverId: "dmRemoveDownloadSilver", 82 | goldId: "dmRemoveDownloadGold" 83 | }, 84 | privateBrowsingEnter: { 85 | id: "private-browsing", 86 | obs: "private-browsing", 87 | description: _("privateBrowsingEnter.description", brandShortName), 88 | hint: _("privateBrowsingEnter.hint"), 89 | learnMoreUrl: "http://support.mozilla.com/kb/Private Browsing", 90 | learnMoreLabel: _("privateBrowsingEnter.learnMoreLabel"), 91 | name: _("privateBrowsingEnter.name"), 92 | subAwards: true, 93 | bronzeId: "private-browsing", /* migrated from generic award */ 94 | silverId: "private-browsingSilver", 95 | goldId: "private-browsingGold", 96 | }, 97 | pmLoginAdded: { 98 | id: "passwordmgr-storage-changed", 99 | obs: "passwordmgr-storage-changed", 100 | description: _("pmLoginAdded.description"), 101 | hint: _("pmLoginAdded.hint"), 102 | learnMoreUrl: "http://support.mozilla.com/kb/make-firefox-remember-usernames-and-passwords", 103 | learnMoreLabel: _("pmLoginAdded.learnMoreLabel"), 104 | name: _("pmLoginAdded.name"), 105 | subAwards: true, 106 | bronzeId: "passwordmgr-storage-changed", /* migrated from generic award */ 107 | silverId: "passwordmgr-storage-changedSilver", 108 | goldId: "passwordmgr-storage-changedGold", 109 | }, 110 | homepageChanged: { 111 | id: "homepageChanged", 112 | obs: "browser.startup.homepage", 113 | description: _("homepageChanged.description", brandShortName), 114 | hint: _("homepageChanged.hint"), 115 | learnMoreUrl: "http://support.mozilla.com/kb/How to set the home page", 116 | learnMoreLabel: _("homepageChanged.learnMoreLabel"), 117 | name: _("homepageChanged.name"), 118 | award: "bronze", 119 | }, 120 | addOnsOpened: { 121 | id: "Tools:Addons", 122 | obs: "Tools:Addons", 123 | description: _("addOnsOpened.description", brandShortName), 124 | hint: _("addOnsOpened.hint"), 125 | learnMoreUrl: "https://addons.mozilla.org", 126 | learnMoreLabel: _("addOnsOpened.learnMoreLabel"), 127 | name: _("addOnsOpened.name"), 128 | url: "about:addons", 129 | subAwards: true, 130 | bronzeId: "addOnsBronze", 131 | silverId: "addOnsSilver", 132 | goldId: "addOnsGold", 133 | }, 134 | aboutMisc: { 135 | id: "aboutMisc", 136 | obs: "aboutMisc", 137 | description: _("aboutMisc.description"), 138 | hint: _("aboutMisc.hint"), 139 | learnMoreUrl: "http://www.mozilla.org", 140 | learnMoreLabel: _("aboutMisc.learnMoreLabel"), 141 | name: _("aboutMisc.name"), 142 | subAwards: true, 143 | bronzeId: "aboutPagesBronze", 144 | silverId: "aboutPagesSilver", 145 | goldId: "aboutPagesGold", 146 | }, 147 | configOpened: { 148 | id: "about:config", 149 | obs: "about:config", 150 | description: _("configOpened.description"), 151 | hint: _("configOpened.hint"), 152 | learnMoreUrl: "http://kb.mozillazine.org/About:config", 153 | learnMoreLabel: _("configOpened.learnMoreLabel"), 154 | name: _("configOpened.name"), 155 | url: "about:config", 156 | award: "silver", /* migrated from generic award */ 157 | subAwards: true, 158 | bronzeId: "about:configBronze", 159 | silverId: "about:config", /* migrated from generic award */ 160 | goldId: "about:configGold", 161 | }, 162 | knowUrRights: { 163 | id: "about:rights", 164 | obs: "about:rights", 165 | description: _("knowUrRights.description", brandShortName), 166 | hint: _("knowUrRights.hint"), 167 | learnMoreUrl: "http://www.mozilla.org/about/manifesto.html", 168 | learnMoreLabel: _("knowUrRights.learnMoreLabel"), 169 | name: _("knowUrRights.name"), 170 | url: "about:rights", 171 | award: "bronze", 172 | }, 173 | frequentFlyer: { 174 | id: "frequentFlyer", 175 | obs: "frequentFlyer", 176 | description: _("frequentFlyer.description"), 177 | hint: _("frequentFlyer.hint"), 178 | name: _("frequentFlyer.name"), 179 | subAwards: true, 180 | bronzeId: "frequentFlyerBronze", 181 | silverId: "frequentFlyerSilver", 182 | goldId: "frequentFlyerGold", 183 | }, 184 | revolutionTelevised: { 185 | id: "revolutionTelevised", 186 | obs: "revolutionTelevised", 187 | description: _("revolutionTelevised.description"), 188 | hint: _("revolutionTelevised.hint"), 189 | learnMoreUrl: "https://air.mozilla.org", 190 | learnMoreLabel: _("revolutionTelevised.learnMoreLabel"), 191 | name: _("revolutionTelevised.name"), 192 | url: "*.air.mozilla.org", 193 | award: "bronze", 194 | }, 195 | yoDawg: { 196 | id: "yoDawg", 197 | obs: "chrome://browser/content/browser.xul", 198 | description: _("yoDawg.description", brandShortName), 199 | hint: _("yoDawg.hint"), 200 | learnMoreUrl: "https://developer.mozilla.org/En/XUL", 201 | learnMoreLabel: _("yoDawg.learnMoreLabel"), 202 | name: _("yoDawg.name"), 203 | url: "chrome://browser/content/browser.xul", 204 | award: "bronze", 205 | }, 206 | bookmarkAdded: { 207 | id: "bookmarkAdded", 208 | obs: "bookmarkAdded", 209 | description: _("bookmarkAdded.description"), 210 | learnMoreUrl: "http://support.mozilla.com/kb/how-do-i-use-bookmarks", 211 | learnMoreLabel: _("bookmarkAdded.learnMoreLabel"), 212 | hint: _("bookmarkAdded.hint"), 213 | name: _("bookmarkAdded.name"), 214 | subAwards: true, 215 | bronzeId: "bookmarkAddedBronze", 216 | silverId: "bookmarkAddedSilver", 217 | goldId: "bookmarkAddedGold", 218 | }, 219 | feedbackSubmitted: { 220 | id: "feedbackSubmitted", 221 | obs: "feedbackSubmitted", 222 | description: _("feedbackSubmitted.description", brandShortName), 223 | learnMoreUrl: "https://input.mozilla.org/feedback", 224 | learnMoreLabel: _("feedbackSubmitted.learnMoreLabel"), 225 | hint: _("feedbackSubmitted.hint"), 226 | url: /https?:\/\/input.mozilla.(org|com)\/[^/]*\/thanks/, 227 | name: _("feedbackSubmitted.name"), 228 | award: "bronze", 229 | }, 230 | releaseChannels: { 231 | id: "releaseChannels", 232 | obs: "releaseChannels", 233 | description: _("releaseChannels.description", brandShortName), 234 | learnMoreUrl: "http://www.mozilla.org/projects/firefox/prerelease.html", 235 | learnMoreLabel: _("releaseChannels.learnMoreLabel", brandShortName), 236 | hint: _("releaseChannels.hint"), 237 | name: _("releaseChannels.name"), 238 | subAwards: true, 239 | bronzeId: "releaseChannelsBronze", 240 | silverId: "releaseChannelsSilver", 241 | goldId: "releaseChannelsGold", 242 | hidden: true, 243 | }, 244 | devTools: { 245 | id: "devTools", 246 | obs: "devTools", 247 | description: _("devTools.description", brandShortName), 248 | learnMoreUrl: "http://hacks.mozilla.org/category/developer-tools/", 249 | learnMoreLabel: _("devTools.learnMoreLabel"), 250 | hint: _("devTools.hint"), 251 | name: _("devTools.name"), 252 | subAwards: true, 253 | bronzeId: "devToolsBronze", 254 | silverId: "devToolsSilver", 255 | goldId: "devToolsGold", 256 | }, 257 | sociallyAwesomePenguin: { 258 | id: "sociallyAwesomePenguin", 259 | obs: "sociallyAwesomePenguin", 260 | description: _("sociallyAwesomePenguin.description"), 261 | hint: _("sociallyAwesomePenguin.hint"), 262 | name: _("sociallyAwesomePenguin.name"), 263 | subAwards: true, 264 | bronzeId: "sociallyAwesomePenguinBronze", 265 | silverId: "sociallyAwesomePenguinSilver", 266 | goldId: "sociallyAwesomePenguinGold", 267 | }, 268 | socialButterfly: { 269 | id: "socialButterfly", 270 | obs: "socialButterfly", 271 | description: _("socialButterfly.description", brandShortName), 272 | hint: _("socialButterfly.hint"), 273 | name: _("socialButterfly.name"), 274 | subAwards: true, 275 | bronzeId: "socialButterflyBronze", 276 | silverId: "socialButterflySilver", 277 | goldId: "socialButterflyGold", 278 | }, 279 | tabCandy: { 280 | id: "tabCandy", 281 | obs: "tabCandy", 282 | description: _("tabCandy.description"), 283 | hint: _("tabCandy.hint"), 284 | name: _("tabCandy.name"), 285 | subAwards: true, 286 | bronzeId: "tabCandyBronze", 287 | silverId: "tabCandySilver", 288 | goldId: "tabCandyGold", 289 | hidden: true, 290 | }, 291 | concurrentTabs: { 292 | id: "concurrentTabs", 293 | obs: "concurrentTabs", 294 | description: _("concurrentTabs.description"), 295 | hint: _("concurrentTabs.hint"), 296 | name: _("concurrentTabs.name"), 297 | subAwards: true, 298 | bronzeId: "concurrentTabsBronze", 299 | silverId: "concurrentTabsSilver", 300 | goldId: "concurrentTabsGold", 301 | hidden: true, 302 | }, 303 | geekCred: { 304 | id: "geekCred", 305 | obs: "geekCred", 306 | description: _("geekCred.description"), 307 | hint: _("geekCred.hint"), 308 | name: _("geekCred.name"), 309 | subAwards: true, 310 | bronzeId: "geekCredBronze", 311 | silverId: "geekCredSilver", 312 | goldId: "geekCredGold", 313 | }, 314 | newsJunkie: { 315 | id: "newsJunkie", 316 | obs: "newsJunkie", 317 | description: _("newsJunkie.description"), 318 | hint: _("newsJunkie.hint"), 319 | name: _("newsJunkie.name"), 320 | subAwards: true, 321 | bronzeId: "newsJunkieBronze", 322 | silverId: "newsJunkieSilver", 323 | goldId: "newsJunkieGold", 324 | }, 325 | cheevosTheyreGreat: { 326 | id: "cheevosTheyreGreat", 327 | obs: "cheevosTheyreGreat", 328 | description: _("cheevosTheyreGreat.description"), 329 | hint: _("cheevosTheyreGreat.hint"), 330 | name: _("cheevosTheyreGreat.name"), 331 | subAwards: true, 332 | bronzeId: "cheevosTheyreGreatBronze", 333 | silverId: "cheevosTheyreGreatSilver", 334 | goldId: "cheevosTheyreGreatGold", 335 | }, 336 | }; 337 | 338 | if (!ss.dynamicCheevos) 339 | ss.dynamicCheevos = {}; 340 | 341 | // Need to load any dynamic cheevos that were persisted. 342 | for (let index in ss.dynamicCheevos) { 343 | cheevos[index] = ss.dynamicCheevos[index]; 344 | } 345 | 346 | let totalCheevos = []; 347 | for (let index in cheevos) { 348 | totalCheevos[totalCheevos.length] = cheevos[index]; 349 | totalAwards += cheevos[index].subAwards ? 3 : 1; 350 | } 351 | 352 | if (!ss.cheevosAcquired) 353 | ss.cheevosAcquired = {}; 354 | 355 | for (let i in cheevos) { 356 | let cheevo = cheevos[i]; 357 | if (cheevo.subAwards) { 358 | if (ss.cheevosAcquired[cheevo.bronzeId]) { 359 | acquiredAwards++; 360 | acquiredPoints += PTS_PER_BRONZE; 361 | } 362 | if (ss.cheevosAcquired[cheevo.silverId]) { 363 | acquiredAwards++; 364 | acquiredPoints += PTS_PER_SILVER; 365 | } 366 | if (ss.cheevosAcquired[cheevo.goldId]) { 367 | acquiredAwards++; 368 | acquiredPoints += PTS_PER_GOLD; 369 | } 370 | } else if (ss.cheevosAcquired[cheevo.id]) { 371 | acquiredAwards++; 372 | acquiredPoints += PTS_PER_BASIC; 373 | } 374 | } 375 | 376 | if (!ss.hostCount) 377 | ss.hostCount = [{},{},{}]; 378 | if (!ss.aboutsVisited) 379 | ss.aboutsVisited = {}; 380 | if (!ss.aboutsVisitedCount) 381 | ss.aboutsVisitedCount = 0; 382 | if (!ss.aboutConfigVisits) 383 | ss.aboutConfigVisits = 0; 384 | if (!ss.downloadsRemoved) 385 | ss.downloadsRemoved = 0; 386 | if (!ss.bookmarksAdded) 387 | ss.bookmarksAdded = 0; 388 | if (!ss.tabsCount) 389 | ss.tabsCount = 1; 390 | if (!ss.socialVisits) { 391 | ss.socialVisits = 0; 392 | ss.specificSocialSiteVisits = {}; 393 | } 394 | if (!ss.privateBrowsingEntrances) 395 | ss.privateBrowsingEntrances = 0; 396 | if (!ss.lwThemeChanges) 397 | ss.lwThemeChanges = 0; 398 | if (!ss.pmLoginsAdded) 399 | ss.pmLoginsAdded = 0; 400 | if (!ss.scratchPadOpenings) 401 | ss.scratchPadOpenings = 0; 402 | if (!ss.errorConsoleOpenings) 403 | ss.errorConsoleOpenings = 0; 404 | if (!ss.viewSourceOpenings) 405 | ss.viewSourceOpenings = 0; 406 | if (!ss.geekCredVisits) 407 | ss.geekCredVisits = 0; 408 | if (!ss.newsJunkieVisits) 409 | ss.newsJunkieVisits = 0; 410 | addObs(cheevos.lwThemeChanged.obs, onLightweightThemeChanged, this); 411 | addObs(cheevos.dmRemoveDownload.obs, onDownloadManagerRemoveDownload, this); 412 | addObs(cheevos.pmLoginAdded.obs, onPMLoginAdded, this); 413 | addObs(addOnAchievementObs, onAddOnAchievement, this); 414 | tabs.on('ready', onDOMContentLoaded); 415 | 416 | let {ActionButton} = require('sdk/ui/button/action'); 417 | let toolbarbutton = ActionButton({ 418 | id: "cheevos-toolbarbutton", 419 | label: _("points", acquiredPoints.toString()), 420 | title: _("addOnShortName"), 421 | icon: { 422 | "16": data.url("coins.png") 423 | }, 424 | onClick: function (state) { 425 | let aboutCheevosAlreadyOpen = false; 426 | for each (let tab in tabs) { 427 | if (tab.url == aboutCheevosUrl) { 428 | aboutCheevosAlreadyOpen = true; 429 | tab.activate(); 430 | tab.reload(); 431 | } 432 | } 433 | 434 | if (!aboutCheevosAlreadyOpen) 435 | loadCheevosPage(); 436 | } 437 | }); 438 | let achievementOverlay = ao.AchievementOverlay({ 439 | id: "cheevos-achievementOverlay", 440 | onCommand: function () { loadCheevosPage(); } 441 | }); 442 | 443 | require('userstyles').load(data.url("chrome.css"), {type: 'agent'}); 444 | 445 | // show cheevo for installing the addon 446 | onObservation(cheevos.addOnsOpened, true, "bronze"); 447 | 448 | function addObs(topic, callback, thisRef) { 449 | events.on(topic, function(data) { 450 | callback.call(thisRef, data.subject, data.data); 451 | }, false); 452 | } 453 | 454 | function log(aMessage) { 455 | if (debug) 456 | console.info("cheevos: " + aMessage); 457 | } 458 | 459 | function getCheevoListBlockText() { 460 | log("getCheevoListBlockText"); 461 | let h = ''; 462 | for (let i in totalCheevos) { 463 | let cheevo = totalCheevos[i]; 464 | if (cheevo.hidden && !ss.cheevosAcquired[cheevo.id] && !ss.cheevosAcquired[cheevo.bronzeId] && 465 | !ss.cheevosAcquired[cheevo.silverId] && !ss.cheevosAcquired[cheevo.goldId]) 466 | continue; 467 | let achieved = cheevo.subAwards ? ss.cheevosAcquired[cheevo.goldId] : ss.cheevosAcquired[cheevo.id]; 468 | log(cheevo.id + " is " + (achieved ? "achieved" : "not achieved")); 469 | if (cheevo.subAwards) 470 | h += achieved ? "
  • " : "
  • "; 471 | else 472 | h += achieved ? "
  • " : "
  • "; 473 | h += "

    " + cheevo.name + "

    " 474 | h += "

    " + (achieved ? cheevo.description : cheevo.hint) + "

    "; 475 | if (cheevo.subAwards) { 476 | h += "
      "; 477 | if (ss.cheevosAcquired[cheevo.bronzeId]) 478 | h += "
    1. "; 479 | else 480 | h += "
    2. "; 481 | if (ss.cheevosAcquired[cheevo.silverId]) 482 | h += "
    3. "; 483 | else 484 | h += "
    4. "; 485 | if (ss.cheevosAcquired[cheevo.goldId]) 486 | h += "
    5. "; 487 | else 488 | h += "
    6. "; 489 | h += "
    "; 490 | } else { 491 | if (ss.cheevosAcquired[cheevo.id]) 492 | h += "
    "; 493 | else 494 | h += "
    "; 495 | 496 | } 497 | if (achieved && cheevo.learnMoreUrl && cheevo.learnMoreLabel) { 498 | h += ""; 499 | } 500 | h += "
  • "; 501 | } 502 | return h; 503 | } 504 | 505 | function onCheevosPageOpened(tab) { 506 | log("onCheevosPageOpened"); 507 | let tweetText = _("tweetText", acquiredPoints, _("addOnShortName"), brandShortName); 508 | let stats = _("stats", acquiredPoints, acquiredAwards, totalAwards); 509 | let addOnFullName = _("addOnFullName", _("addOnShortName"), brandShortName); 510 | let addOnTagLine = _("addOnTagLine", brandShortName); 511 | let addOnHomepageLink = _("addOnHomepageLink"); 512 | let supportLink = _("supportLink"); 513 | let authorHomepageLink = _("authorHomepageLink"); 514 | let styleCss = data.url("cheevo.css"); 515 | tab.attach({ 516 | contentScriptFile: data.url("cheevo.js"), 517 | contentScript: "populateTemplate('" + escape(tweetText) + "','" + escape(stats) + "','" + 518 | escape(getCheevoListBlockText()) + "','" + escape(styleCss) + "','" + 519 | escape(addOnFullName) + "','" + escape(addOnTagLine) + "','" + 520 | escape(addOnHomepageLink) + "','" + escape(supportLink) + "','" + escape(authorHomepageLink) + "');", 521 | }); 522 | } 523 | 524 | function loadCheevosPage() { 525 | tabs.open({ 526 | url: aboutCheevosUrl, 527 | onReady: function onReady(tab) { onCheevosPageOpened(tab); } 528 | }); 529 | } 530 | 531 | function notify(cheevo, points, awardsClass) { 532 | log("showing notification: " + cheevo.name); 533 | 534 | for each (let tab in tabs) { 535 | if (tab.url == aboutCheevosUrl) { 536 | tab.reload(); 537 | } 538 | } 539 | 540 | achievementOverlay.show({ 541 | title: cheevo.name, 542 | text: cheevo.hint, 543 | points: points, 544 | awardsClass: awardsClass, 545 | }); 546 | } 547 | 548 | function updateToolbarButtonLabel(aPoints) { 549 | let text = _("points", aPoints.toString()); 550 | 551 | toolbarbutton.label = text; 552 | toolbarbutton.tooltiptext = text; 553 | require('./icon-generator').generate({ 554 | onReady: function({icon}) { 555 | toolbarbutton.image = icon; 556 | }, 557 | text: aPoints.toString() 558 | }); 559 | } 560 | 561 | function onObservation(cheevo, shouldShow, specificAward) { 562 | log("onObservation: " + cheevo.obs); 563 | function acquireCheevo(cheevo, id, points, awardsClass) { 564 | if (!ss.cheevosAcquired[id]) { 565 | ss.cheevosAcquired[id] = new Date().toDateString(); 566 | acquiredAwards++; 567 | notify(cheevo, points, awardsClass); 568 | updateToolbarButtonLabel(acquiredPoints); 569 | }; 570 | }; 571 | if (!shouldShow) 572 | return; 573 | if (specificAward) { 574 | switch (specificAward) { 575 | case "bronze": 576 | if (ss.cheevosAcquired[cheevo.bronzeId]) 577 | return; 578 | acquiredPoints += PTS_PER_BRONZE; 579 | acquireCheevo(cheevo, cheevo.bronzeId, PTS_PER_BRONZE, "bronze"); 580 | break; 581 | case "silver": 582 | if (ss.cheevosAcquired[cheevo.silverId]) 583 | return; 584 | acquiredPoints += PTS_PER_SILVER; 585 | acquireCheevo(cheevo, cheevo.silverId, PTS_PER_SILVER, "silver"); 586 | break; 587 | case "gold": 588 | if (ss.cheevosAcquired[cheevo.goldId]) 589 | return; 590 | acquiredPoints += PTS_PER_GOLD; 591 | acquireCheevo(cheevo, cheevo.goldId, PTS_PER_GOLD, "gold"); 592 | break; 593 | default: 594 | log("Cheevo: Unexpected observation specificAward: " + specificAward); 595 | break; 596 | } 597 | } else { 598 | if (ss.cheevosAcquired[cheevo.id]) 599 | return; 600 | acquiredPoints += PTS_PER_BASIC; 601 | acquireCheevo(cheevo, cheevo.id, PTS_PER_BASIC, "bronze generic"); 602 | } 603 | } 604 | 605 | function onURLOpened(cheevo) { 606 | return onObservation(cheevo, true, (cheevo.award != "bronze") ? cheevo.award : false); 607 | } 608 | 609 | function onLightweightThemeChanged(subject, data) { 610 | ss.lwThemeChanges++; 611 | onObservation(cheevos.lwThemeChanged, true, "bronze"); 612 | if (ss.lwThemeChanges > 10) 613 | onObservation(cheevos.lwThemeChanged, true, "silver"); 614 | if (ss.lwThemeChanges > 20) 615 | onObservation(cheevos.lwThemeChanged, true, "gold"); 616 | } 617 | 618 | function onDownloadManagerRemoveDownload(subject, data) { 619 | ss.downloadsRemoved++; 620 | if (subject) { 621 | if (ss.downloadsRemoved >= 1) 622 | onObservation(cheevos.dmRemoveDownload, true, "bronze"); 623 | if (ss.downloadsRemoved >= 3) 624 | onObservation(cheevos.dmRemoveDownload, true, "silver"); 625 | } else { 626 | onObservation(cheevos.dmRemoveDownload, true, "bronze"); 627 | onObservation(cheevos.dmRemoveDownload, true, "silver"); 628 | onObservation(cheevos.dmRemoveDownload, true, "gold"); 629 | } 630 | } 631 | 632 | function onPMLoginAdded(subject, data) { 633 | if (data == "addLogin") 634 | ss.pmLoginsAdded++; 635 | onObservation(cheevos.pmLoginAdded, data == "addLogin", "bronze"); 636 | if (ss.pmLoginsAdded > 10) 637 | onObservation(cheevos.pmLoginAdded, data == "addLogin", "silver"); 638 | if (ss.pmLoginsAdded > 20) 639 | onObservation(cheevos.pmLoginAdded, data == "addLogin", "gold"); 640 | } 641 | 642 | function onAddOnAchievement(subject, data) { 643 | log("onAddOnAchievement with subject: " + subject + "; and data: " + data); 644 | // Validate data 645 | if (!data) 646 | return; 647 | 648 | let [id, description, hint, name, subAwards, specificAward] = 649 | data.split(";"); 650 | subAwards = subAwards == "true"; 651 | if (!id || !description || !hint || !name) 652 | return; 653 | if (subAwards && specificAward != "bronze" && 654 | specificAward != "silver" && specificAward != "gold") 655 | return; 656 | 657 | let cheevo = { 658 | id: id, 659 | obs: addOnAchievementObs, 660 | description: description, 661 | hint: hint, 662 | name: name, 663 | subAwards: subAwards, 664 | bronzeId: id + "Bronze", 665 | silverId: id + "Silver", 666 | goldId: id + "Gold", 667 | hidden: true, 668 | }; 669 | 670 | // Since this is a dynamic cheevo, it's not stored in totalCheevos. 671 | let cheevoSeenBefore = false; 672 | for (let i in totalCheevos) { 673 | if (totalCheevos[i].id == id) 674 | cheevoSeenBefore = true; 675 | } 676 | if (!cheevoSeenBefore) { 677 | totalCheevos[totalCheevos.length] = cheevo; 678 | totalAwards += subAwards ? 3 : 1; 679 | } 680 | 681 | // Also need to persist it so it will appear in totalCheevos 682 | // upon restart. 683 | if (!ss.dynamicCheevos[id]) { 684 | ss.dynamicCheevos[id] = cheevo; 685 | } 686 | 687 | onObservation(cheevo, true, specificAward); 688 | } 689 | 690 | function onBookmarkAdded() { 691 | ss.bookmarksAdded++; 692 | onObservation(cheevos.bookmarkAdded, true, "bronze"); 693 | if (ss.bookmarksAdded > 10) 694 | onObservation(cheevos.bookmarkAdded, true, "silver"); 695 | if (ss.bookmarksAdded > 25) 696 | onObservation(cheevos.bookmarkAdded, true, "gold"); 697 | } 698 | 699 | function clearOldBuckets() { 700 | const date = new Date(), 701 | milliseconds = date.getTime(), 702 | threeMinutesAsMS = 180000; 703 | for (let bucket in ss.hostCount) { 704 | for (let i in ss.hostCount[bucket]) { 705 | if (milliseconds - (ss.hostCount[bucket])[i] > threeMinutesAsMS) 706 | ss.hostCount[bucket] = {}; 707 | break; 708 | } 709 | } 710 | } 711 | 712 | function trackHost(url) { 713 | let visited; 714 | const date = new Date(), 715 | minutes = date.getMinutes(), 716 | milliseconds = date.getTime(), 717 | threeMinutesAsMS = 180000, 718 | host = urlFactory.URL(url).host; 719 | for (let bucket in ss.hostCount) 720 | if (host in ss.hostCount[bucket]) { 721 | visited = true; 722 | break; 723 | } 724 | if (!visited) { 725 | let bucket = minutes % 3; 726 | (ss.hostCount[bucket])[host] = milliseconds; 727 | } 728 | } 729 | 730 | function getHostCount() { 731 | let hosts = 0; 732 | for (let bucket in ss.hostCount) { 733 | for (let i in ss.hostCount[bucket]) { 734 | hosts++; 735 | } 736 | } 737 | log("totalHosts: " + hosts); 738 | return hosts; 739 | } 740 | 741 | function onDOMContentLoaded(tab) { 742 | log("onDOMContentLoaded: " + tab.url); 743 | 744 | if (tab.url.toLowerCase() == aboutCheevosUrl) { 745 | onObservation(cheevos.cheevosTheyreGreat, true, "bronze"); 746 | } else if (tab.url.toLowerCase().contains("firefox/addon/cheevos")) { 747 | onObservation(cheevos.cheevosTheyreGreat, true, "silver"); 748 | } else if (tab.url.toLowerCase().contains("cheevos.msuja.ws")) { 749 | onObservation(cheevos.cheevosTheyreGreat, true, "gold"); 750 | } 751 | 752 | if (tab.url.toLowerCase() == aboutCheevosUrl) { 753 | onCheevosPageOpened(tab); 754 | return; 755 | } 756 | 757 | if (PrivateBrowsing.isPrivate(tab)) 758 | return; 759 | 760 | let url = urlFactory.URL(tab.url); 761 | for (let index in cheevos) { 762 | if ("url" in cheevos[index]) { 763 | var pattern = new MatchPattern(cheevos[index].url); 764 | if (pattern.test(tab.url)) { 765 | if (cheevos[index] == cheevos.addOnsOpened) 766 | onObservation(cheevos.addOnsOpened, true, "silver"); 767 | else 768 | onURLOpened(cheevos[index]); 769 | } 770 | } 771 | } 772 | 773 | if (tab.url.toLowerCase() == "about:config") { 774 | ss.aboutConfigVisits++; 775 | onObservation(cheevos.configOpened, true, "bronze"); 776 | onObservation(cheevos.configOpened, true, "silver"); 777 | if (ss.aboutConfigVisits > 5) 778 | onObservation(cheevos.configOpened, true, "gold"); 779 | } 780 | 781 | if (tab.url.toLowerCase().indexOf("about:") == 0 && 782 | tab.url.toLowerCase() != "about:home" && 783 | tab.url.toLowerCase() != "about:blank" && 784 | tab.url.toLowerCase() != "about:privatebrowsing" && 785 | tab.url.toLowerCase() != "about:sessionrestore" && 786 | !(tab.url.toLowerCase() in ss.aboutsVisited)) { 787 | ss.aboutsVisited[tab.url.toLowerCase()] = true; 788 | ss.aboutsVisitedCount++; 789 | if (ss.aboutsVisitedCount >= 3) 790 | onObservation(cheevos.aboutMisc, true, "bronze"); 791 | if (ss.aboutsVisitedCount >= 9) 792 | onObservation(cheevos.aboutMisc, true, "silver"); 793 | if (ss.aboutsVisitedCount >= 19) 794 | onObservation(cheevos.aboutMisc, true, "gold"); 795 | } 796 | 797 | for (var i = 0; i < socialSites.length; i++) { 798 | let socialSite = socialSites[i]; 799 | if (new MatchPattern(socialSite).test(tab.url)) { 800 | ss.socialVisits++; 801 | if (ss.socialVisits >= 3) 802 | onObservation(cheevos.socialButterfly, true, "bronze"); 803 | if (ss.socialVisits >= 10) 804 | onObservation(cheevos.socialButterfly, true, "silver"); 805 | if (ss.socialVisits >= 20) 806 | onObservation(cheevos.socialButterfly, true, "gold"); 807 | if (socialSite in ss.specificSocialSiteVisits) { 808 | let specificSocialSiteVisit = ++ss.specificSocialSiteVisits[socialSite]; 809 | if (specificSocialSiteVisit >= 5 && specificSocialSiteVisit != ss.socialVisits) 810 | onObservation(cheevos.sociallyAwesomePenguin, true, "bronze"); 811 | if (specificSocialSiteVisit >= 15 && specificSocialSiteVisit != ss.socialVisits) 812 | onObservation(cheevos.sociallyAwesomePenguin, true, "silver"); 813 | if (specificSocialSiteVisit >= 25 && specificSocialSiteVisit != ss.socialVisits) 814 | onObservation(cheevos.sociallyAwesomePenguin, true, "gold"); 815 | } else { 816 | ss.specificSocialSiteVisits[socialSite] = 1; 817 | } 818 | break; 819 | } 820 | } 821 | 822 | for (var i = 0; i < geekCredSites.length; i++) { 823 | let geekCredSite = geekCredSites[i]; 824 | if (new MatchPattern(geekCredSite).test(tab.url)) { 825 | ss.geekCredVisits++; 826 | if (ss.geekCredVisits >= 3) 827 | onObservation(cheevos.geekCred, true, "bronze"); 828 | if (ss.geekCredVisits >= 10) 829 | onObservation(cheevos.geekCred, true, "silver"); 830 | if (ss.geekCredVisits >= 20) 831 | onObservation(cheevos.geekCred, true, "gold"); 832 | break; 833 | } 834 | } 835 | 836 | if (tab.title && tab.title.toLowerCase().contains(_("noun.news"))) { 837 | ss.newsJunkieVisits++; 838 | if (ss.newsJunkieVisits >= 3) 839 | onObservation(cheevos.newsJunkie, true, "bronze"); 840 | if (ss.newsJunkieVisits >= 10) 841 | onObservation(cheevos.newsJunkie, true, "silver"); 842 | if (ss.newsJunkieVisits >= 20) 843 | onObservation(cheevos.newsJunkie, true, "gold"); 844 | } 845 | 846 | clearOldBuckets(); 847 | trackHost(tab.url); 848 | let hosts = getHostCount(); 849 | if (hosts >= 10) 850 | onObservation(cheevos.frequentFlyer, true, "bronze"); 851 | if (hosts >= 20) 852 | onObservation(cheevos.frequentFlyer, true, "silver"); 853 | if (hosts >= 30) 854 | onObservation(cheevos.frequentFlyer, true, "gold"); 855 | } 856 | 857 | function tabAdded() { 858 | ss.tabsCount++; 859 | if (ss.tabsCount >= 5) 860 | onObservation(cheevos.tabCandy, true, "bronze"); 861 | if (ss.tabsCount >= 50) 862 | onObservation(cheevos.tabCandy, true, "silver"); 863 | if (ss.tabsCount >= 500) 864 | onObservation(cheevos.tabCandy, true, "gold"); 865 | 866 | let concurrentTabs = tabs.length; 867 | if (concurrentTabs >= 5) 868 | onObservation(cheevos.concurrentTabs, true, "bronze"); 869 | if (concurrentTabs >= 25) 870 | onObservation(cheevos.concurrentTabs, true, "silver"); 871 | if (concurrentTabs >= 100) 872 | onObservation(cheevos.concurrentTabs, true, "gold"); 873 | } 874 | 875 | var windowDelegate = { 876 | onTrack: function (window) { 877 | function addMenuItem(window) { 878 | if (window.location != "chrome://browser/content/browser.xul") 879 | return; 880 | 881 | log("adding menu item"); 882 | const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 883 | const keysetID = "cheevo-keyset"; 884 | const keyID = "Cheevo:Cheevo"; 885 | const fileMenuitemID = "menu_CheevoItem"; 886 | let logo = data.url("trophy_icon.png"); 887 | var $ = function(id) window.document.getElementById(id); 888 | 889 | function removeMI(id) { 890 | var menuitem = $(id); 891 | menuitem && menuitem.parentNode.removeChild(menuitem); 892 | } 893 | removeMI(fileMenuitemID); 894 | removeMI("appmenu_CheevoItem"); 895 | 896 | // add the new menuitem to File menu 897 | let (cheevoMI = window.document.createElementNS(NS_XUL, "menuitem")) { 898 | cheevoMI.setAttribute("id", fileMenuitemID); 899 | cheevoMI.setAttribute("class", "menuitem-iconic"); 900 | cheevoMI.setAttribute("label","View Cheevos"); 901 | cheevoMI.setAttribute("key", keyID); 902 | cheevoMI.style.listStyleImage = "url('" + logo + "')"; 903 | cheevoMI.addEventListener("command", function() { loadCheevosPage(); }, true); 904 | 905 | if ($("menu_ToolsPopup")) 906 | $("menu_ToolsPopup").insertBefore(cheevoMI, $("devToolsSeparator")); 907 | 908 | // add app menu item to Firefox button for Windows 7 909 | let appMenu = $("appmenuSecondaryPane"), cheevoAMI; 910 | if (appMenu) { 911 | cheevoAMI = $(fileMenuitemID).cloneNode(false); 912 | cheevoAMI.setAttribute("id", "appmenu_CheevoItem"); 913 | cheevoAMI.setAttribute("class", "menuitem-iconic menuitem-iconic-tooltip"); 914 | cheevoAMI.style.listStyleImage = "url('" + logo + "')"; 915 | cheevoAMI.addEventListener("command", function() { loadCheevosPage(); }, true); 916 | appMenu.insertBefore(cheevoAMI, $("appmenuSecondaryPane-spacer")); 917 | } 918 | } 919 | } 920 | function addCustomizationEventListener(window) { 921 | function acquireGoldAddonsAchievement() { 922 | onObservation(cheevos.addOnsOpened, true, "bronze"); 923 | onObservation(cheevos.addOnsOpened, true, "silver"); 924 | onObservation(cheevos.addOnsOpened, true, "gold"); 925 | } 926 | if (window.location == "chrome://browser/content/browser.xul") { 927 | window.addEventListener("aftercustomization", function() { 928 | acquireGoldAddonsAchievement(); 929 | updateToolbarButtonLabel(acquiredPoints); 930 | }, false); 931 | window.addEventListener("TabOpen", tabAdded, false); 932 | } 933 | 934 | // add unloader to unload+'s queue 935 | var unloadFunc = function() { 936 | // todo: this event listener isn't being removed 937 | //window.removeEventListener("aftercustomization", acquireGoldAddonsAchievement, false); 938 | }; 939 | var index = destroyFuncs.push(unloadFunc) - 1; 940 | listen(window, window, "unload", function() { 941 | destroyFuncs[index] = null; 942 | }, false); 943 | unloaders.push(unload(unloadFunc, window)); 944 | } 945 | log("window opened: " + window.location); 946 | addMenuItem(window); 947 | addCustomizationEventListener(window); 948 | if (window.location == "chrome://mozapps/content/preferences/changemp.xul") 949 | onObservation(cheevos.pmLoginAdded, true, "gold"); 950 | if (window.location == "chrome://browser/content/preferences/preferences.xul") 951 | onObservation(cheevos.configOpened, true, "bronze"); 952 | if (window.location == "chrome://browser/content/aboutDialog.xul") { 953 | onObservation(cheevos.aboutMisc, true, "bronze"); 954 | let prefService = Cc["@mozilla.org/preferences-service;1"] 955 | .getService(Ci.nsIPrefService); 956 | let defaults = prefService.getBranch(""); 957 | let currentChannel = defaults.getCharPref("app.update.channel"); 958 | if (currentChannel == "beta") 959 | onObservation(cheevos.releaseChannels, true, "bronze"); 960 | if (currentChannel == "aurora") { 961 | onObservation(cheevos.releaseChannels, true, "bronze"); 962 | onObservation(cheevos.releaseChannels, true, "silver"); 963 | } 964 | if (currentChannel == "nightly" || currentChannel == "nightly-ux") { 965 | onObservation(cheevos.releaseChannels, true, "bronze"); 966 | onObservation(cheevos.releaseChannels, true, "silver"); 967 | onObservation(cheevos.releaseChannels, true, "gold"); 968 | } 969 | } 970 | if (window.location == "chrome://browser/content/scratchpad.xul" || 971 | window.location == "chrome://global/content/console.xul" || 972 | window.location == "chrome://global/content/viewSource.xul") { 973 | ss.scratchPadOpenings += window.location == "chrome://browser/content/scratchpad.xul" ? 1 : 0; 974 | ss.errorConsoleOpenings += window.location == "chrome://global/content/console.xul" ? 1 : 0; 975 | ss.viewSourceOpenings += window.location == "chrome://global/content/viewSource.xul" ? 1 : 0; 976 | onObservation(cheevos.devTools, true, "bronze"); 977 | if (ss.scratchPadOpenings > 10 || 978 | ss.errorConsoleOpenings > 10 || 979 | ss.viewSourceOpenings > 10) 980 | onObservation(cheevos.devTools, true, "silver"); 981 | if (ss.scratchPadOpenings > 15 && 982 | ss.errorConsoleOpenings > 15 && 983 | ss.viewSourceOpenings > 15) 984 | onObservation(cheevos.devTools, true, "gold"); 985 | } 986 | 987 | // Private browsing cheevos 988 | if (PrivateBrowsing.isPrivate(window)) { 989 | ss.privateBrowsingEntrances++; 990 | onObservation(cheevos.privateBrowsingEnter, true, "bronze"); 991 | if (ss.privateBrowsingEntrances > 10) 992 | onObservation(cheevos.privateBrowsingEnter, true, "silver"); 993 | if (ss.privateBrowsingEntrances > 50) 994 | onObservation(cheevos.privateBrowsingEnter, true, "gold"); 995 | } 996 | 997 | updateToolbarButtonLabel(acquiredPoints); 998 | }, 999 | onUntrack: function (window) { 1000 | if (window.location == "chrome://browser/content/browser.xul") { 1001 | log("removing menu item"); 1002 | const fileMenuitemID = "menu_CheevoItem"; 1003 | var $ = function(id) window.document.getElementById(id); 1004 | var menuitem = $(fileMenuitemID); 1005 | menuitem && menuitem.parentNode.removeChild(menuitem); 1006 | } 1007 | 1008 | window.removeEventListener("TabOpen", tabAdded, false); 1009 | 1010 | // run unload functions 1011 | destroyFuncs.forEach(function(f) f && f()); 1012 | destroyFuncs.length = 0; 1013 | 1014 | // remove unload functions from unload+'s queue 1015 | unloaders.forEach(function(f) f()); 1016 | unloaders.length = 0; 1017 | } 1018 | }; 1019 | var tracker = new winUtils.WindowTracker(windowDelegate); 1020 | 1021 | // pref observer 1022 | SimplePrefs.on(cheevos.homepageChanged.obs, function(name) { 1023 | onObservation(cheevos.homepageChanged, true); 1024 | }); 1025 | 1026 | var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"] 1027 | .getService(Ci.nsINavBookmarksService); 1028 | var myExt_bookmarkListener = { 1029 | onBeforeItemRemoved: function() {}, 1030 | onBeginUpdateBatch: function() {}, 1031 | onEndUpdateBatch: function() {}, 1032 | onFolderAdded: function() {}, 1033 | onFolderChanged: function() {}, 1034 | onFolderMoved: function() {}, 1035 | onFolderRemoved: function() {}, 1036 | onItemAdded: function(aItemId, aParentId, aIndex, aItemType, aURI) { if (!PlacesUtils.itemIsLivemark(aParentId)) onBookmarkAdded(); }, 1037 | onItemChanged: function() {}, 1038 | onItemMoved: function() {}, 1039 | onItemRemoved: function() {}, 1040 | onItemReplaced: function() {}, 1041 | onItemVisited: function() {}, 1042 | onSeparatorAdded: function() {}, 1043 | onSeparatorRemoved: function() {} 1044 | }; 1045 | bmsvc.addObserver(myExt_bookmarkListener, false); 1046 | 1047 | // set up about:cheevos 1048 | require('scheme/about').add({what: 'cheevos', url: data.url("cheevo.html")}); 1049 | --------------------------------------------------------------------------------