diff --git a/mobile/app/mobile.js b/mobile/app/mobile.js index bc01c9c46ade..481b54a458c7 100644 --- a/mobile/app/mobile.js +++ b/mobile/app/mobile.js @@ -589,3 +589,53 @@ pref("image.mem.decodeondraw", true); pref("content.image.allow_locking", false); pref("image.mem.min_discard_timeout_ms", 20000); +#ifdef MOZ_SAFE_BROWSING +// Safe browsing does nothing unless this pref is set +pref("browser.safebrowsing.enabled", true); + +// Prevent loading of pages identified as malware +pref("browser.safebrowsing.malware.enabled", true); + +// Non-enhanced mode (local url lists) URL list to check for updates +pref("browser.safebrowsing.provider.0.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.2"); + +pref("browser.safebrowsing.dataProvider", 0); + +// Does the provider name need to be localizable? +pref("browser.safebrowsing.provider.0.name", "Google"); +pref("browser.safebrowsing.provider.0.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client={moz:client}&appver={moz:version}&pver=2.2"); +pref("browser.safebrowsing.provider.0.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?"); +pref("browser.safebrowsing.provider.0.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client={moz:client}&appver={moz:version}&pver=2.2"); + +// HTML report pages +pref("browser.safebrowsing.provider.0.reportGenericURL", "http://{moz:locale}.phish-generic.mozilla.com/?hl={moz:locale}"); +pref("browser.safebrowsing.provider.0.reportErrorURL", "http://{moz:locale}.phish-error.mozilla.com/?hl={moz:locale}"); +pref("browser.safebrowsing.provider.0.reportPhishURL", "http://{moz:locale}.phish-report.mozilla.com/?hl={moz:locale}"); +pref("browser.safebrowsing.provider.0.reportMalwareURL", "http://{moz:locale}.malware-report.mozilla.com/?hl={moz:locale}"); +pref("browser.safebrowsing.provider.0.reportMalwareErrorURL", "http://{moz:locale}.malware-error.mozilla.com/?hl={moz:locale}"); + +// FAQ URLs +pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/%APP%/phishing-protection/"); +pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/%APP%/geolocation/"); + +// Name of the about: page contributed by safebrowsing to handle display of error +// pages on phishing/malware hits. (bug 399233) +pref("urlclassifier.alternate_error_page", "blocked"); + +// The number of random entries to send with a gethash request. +pref("urlclassifier.gethashnoise", 4); + +// The list of tables that use the gethash request to confirm partial results. +pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar"); + +// If an urlclassifier table has not been updated in this number of seconds, +// a gethash request will be forced to check that the result is still in +// the database. +pref("urlclassifier.confirm-age", 2700); + +// Maximum size of the sqlite3 cache during an update, in bytes +pref("urlclassifier.updatecachemax", 4194304); + +// URL for checking the reason for a malware warning. +pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site="); +#endif \ No newline at end of file diff --git a/mobile/chrome/content/blockedSite.xhtml b/mobile/chrome/content/blockedSite.xhtml new file mode 100644 index 000000000000..f454dd4d61a9 --- /dev/null +++ b/mobile/chrome/content/blockedSite.xhtml @@ -0,0 +1,230 @@ + + + + %htmlDTD; + + %globalDTD; + + %brandDTD; + + %blockedSiteDTD; +]> + + + + + + + + + + + + + +
+ + +
+

&safeb.blocked.phishingPage.title;

+

&safeb.blocked.malwarePage.title;

+
+ +
+ + +
+

&safeb.blocked.phishingPage.shortDesc;

+

&safeb.blocked.malwarePage.shortDesc;

+
+ + +
+

&safeb.blocked.phishingPage.longDesc;

+

&safeb.blocked.malwarePage.longDesc;

+
+ + +
+ + + +
+
+
+ +
+
+ + + + diff --git a/mobile/chrome/content/browser.js b/mobile/chrome/content/browser.js index 2777724ed655..bf24e4189550 100644 --- a/mobile/chrome/content/browser.js +++ b/mobile/chrome/content/browser.js @@ -351,6 +351,7 @@ var Browser = { messageManager.addMessageListener("Browser:CanUnload:Return", this); messageManager.addMessageListener("scroll", this); messageManager.addMessageListener("Browser:CertException", this); + messageManager.addMessageListener("Browser:BlockedSite", this); // broadcast a UIReady message so add-ons know we are finished with startup let event = document.createEvent("Events"); @@ -434,6 +435,7 @@ var Browser = { messageManager.removeMessageListener("Browser:ZoomToPoint:Return", this); messageManager.removeMessageListener("scroll", this); messageManager.removeMessageListener("Browser:CertException", this); + messageManager.removeMessageListener("Browser:BlockedSite", this); var os = Services.obs; os.removeObserver(XPInstallObserver, "addon-install-blocked"); @@ -816,7 +818,7 @@ var Browser = { }, /** - * Handle cert exception event bubbling up from content. + * Handle cert exception message from content. */ _handleCertException: function _handleCertException(aMessage) { let json = aMessage.json; @@ -844,6 +846,43 @@ var Browser = { } }, + /** + * Handle blocked site message from content. + */ + _handleBlockedSite: function _handleBlockedSite(aMessage) { + let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter); + let json = aMessage.json; + switch (json.action) { + case "leave": { + // Get the start page from the *default* pref branch, not the user's + let url = Browser.getHomePage({ useDefault: true }); + this.loadURI(url); + break; + } + case "report-malware": { + // Get the stop badware "why is this blocked" report url, append the current url, and go there. + try { + let reportURL = formatter.formatURLPref("browser.safebrowsing.malware.reportURL"); + reportURL += json.url; + this.loadURI(reportURL); + } catch (e) { + Cu.reportError("Couldn't get malware report URL: " + e); + } + break; + } + case "report-phishing": { + // It's a phishing site, not malware + try { + let reportURL = formatter.formatURLPref("browser.safebrowsing.warning.infoURL"); + this.loadURI(reportURL); + } catch (e) { + Cu.reportError("Couldn't get phishing info URL: " + e); + } + break; + } + } + }, + /** * Compute the sidebar percentage visibility. * @@ -1125,6 +1164,9 @@ var Browser = { case "Browser:CertException": this._handleCertException(aMessage); break; + case "Browser:BlockedSite": + this._handleBlockedSite(aMessage); + break; } } }; diff --git a/mobile/chrome/content/content.js b/mobile/chrome/content/content.js index db793c679ab0..0a33f3081c1c 100644 --- a/mobile/chrome/content/content.js +++ b/mobile/chrome/content/content.js @@ -275,10 +275,15 @@ let Content = { addEventListener("DOMActivate", this, true); addEventListener("MozApplicationManifest", this, false); - addEventListener("command", this, false); addEventListener("pagehide", this, false); addEventListener("keypress", this, false, false); + // Attach a listener to watch for "click" events bubbling up from error + // pages and other similar page. This lets us fix bugs like 401575 which + // require error page UI to do privileged things, without letting error + // pages have any privilege themselves. + addEventListener("click", this, false); + docShell.QueryInterface(Ci.nsIDocShellHistory).useGlobalHistory = true; }, @@ -327,7 +332,7 @@ let Content = { break; } - case "command": { + case "click": { // Don't trust synthetic events if (!aEvent.isTrusted) return; @@ -343,16 +348,39 @@ let Content = { if (ot == temp || ot == perm) { let action = (ot == perm ? "permanent" : "temporary"); sendAsyncMessage("Browser:CertException", { url: errorDoc.location.href, action: action }); - } - else if (ot == errorDoc.getElementById("getMeOutOfHereButton")) { + } else if (ot == errorDoc.getElementById("getMeOutOfHereButton")) { sendAsyncMessage("Browser:CertException", { url: errorDoc.location.href, action: "leave" }); } - } - else if (/^about:neterror\?e=netOffline/.test(errorDoc.documentURI)) { + } else if (/^about:neterror\?e=netOffline/.test(errorDoc.documentURI)) { if (ot == errorDoc.getElementById("errorTryAgain")) { // Make sure we're online before attempting to load Util.forceOnline(); } + } else if (/^about:blocked/.test(errorDoc.documentURI)) { + // The event came from a button on a malware/phishing block page + // First check whether it's malware or phishing, so that we can + // use the right strings/links + let isMalware = /e=malwareBlocked/.test(errorDoc.documentURI); + + if (ot == errorDoc.getElementById("getMeOutButton")) { + sendAsyncMessage("Browser:BlockedSite", { url: errorDoc.location.href, action: "leave" }); + } else if (ot == errorDoc.getElementById("reportButton")) { + // This is the "Why is this site blocked" button. For malware, + // we can fetch a site-specific report, for phishing, we redirect + // to the generic page describing phishing protection. + let action = isMalware ? "report-malware" : "report-phising"; + sendAsyncMessage("Browser:BlockedSite", { url: errorDoc.location.href, action: action }); + } else if (ot == errorDoc.getElementById("ignoreWarningButton")) { + // Allow users to override and continue through to the site, + // but add a notify bar as a reminder, so that they don't lose + // track after, e.g., tab switching. + let webNav = docShell.QueryInterface(Ci.nsIWebNavigation); + webNav.loadURI(content.location, Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER, null, null, null); + + // TODO: We'll need to impl notifications in the parent process and use the preference code found here: + // http://hg.mozilla.org/mozilla-central/file/855e5cd3c884/browser/base/content/browser.js#l2672 + // http://hg.mozilla.org/mozilla-central/file/855e5cd3c884/browser/components/safebrowsing/content/globalstore.js + } } break; } diff --git a/mobile/chrome/jar.mn b/mobile/chrome/jar.mn index d2533570ce9b..b7fb93ad9292 100644 --- a/mobile/chrome/jar.mn +++ b/mobile/chrome/jar.mn @@ -16,6 +16,7 @@ chrome.jar: content/aboutCertError.css (content/aboutCertError.css) content/aboutHome.xhtml (content/aboutHome.xhtml) * content/aboutRights.xhtml (content/aboutRights.xhtml) + content/blockedSite.xhtml (content/blockedSite.xhtml) content/languages.properties (content/languages.properties) * content/browser.xul (content/browser.xul) * content/browser.js (content/browser.js) diff --git a/mobile/components/AboutRedirector.js b/mobile/components/AboutRedirector.js index 63e4bd4ae6a4..b3e4a374c1b6 100644 --- a/mobile/components/AboutRedirector.js +++ b/mobile/components/AboutRedirector.js @@ -65,6 +65,10 @@ let modules = { #endif privileged: false }, + blocked: { + uri: "chrome://browser/content/blockedSite.xhtml", + privileged: true + }, certerror: { uri: "chrome://browser/content/aboutCertError.xhtml", privileged: true @@ -152,6 +156,12 @@ AboutHome.prototype = { classID: Components.ID("{b071364f-ab68-4669-a9db-33fca168271a}") } +function AboutBlocked() {} +AboutBlocked.prototype = { + __proto__: AboutGeneric.prototype, + classID: Components.ID("{88fd40b6-c5c2-4120-9238-f2cb9ff98928}") +} + const components = [AboutEmpty, AboutFirstrun, AboutFennec, AboutRights, - AboutCertError, AboutFirefox, AboutHome]; + AboutCertError, AboutFirefox, AboutHome, AboutBlocked]; const NSGetFactory = XPCOMUtils.generateNSGetFactory(components); diff --git a/mobile/components/Makefile.in b/mobile/components/Makefile.in index dcd6cb217c72..0fc566c1df26 100644 --- a/mobile/components/Makefile.in +++ b/mobile/components/Makefile.in @@ -77,6 +77,10 @@ EXTRA_COMPONENTS = \ BlocklistPrompt.js \ $(NULL) +ifdef MOZ_SAFE_BROWSING +EXTRA_COMPONENTS += SafeBrowsing.js +endif + ifdef MOZ_UPDATER EXTRA_COMPONENTS += UpdatePrompt.js endif diff --git a/mobile/components/MobileComponents.manifest b/mobile/components/MobileComponents.manifest index 2dc9d0722b9d..dd9457f4d525 100644 --- a/mobile/components/MobileComponents.manifest +++ b/mobile/components/MobileComponents.manifest @@ -13,6 +13,10 @@ component {972efe64-8ac0-4e91-bdb0-22835d987815} AboutRedirector.js contract @mozilla.org/network/protocol/about;1?what=certerror {972efe64-8ac0-4e91-bdb0-22835d987815} component {b071364f-ab68-4669-a9db-33fca168271a} AboutRedirector.js contract @mozilla.org/network/protocol/about;1?what=home {b071364f-ab68-4669-a9db-33fca168271a} +#ifdef MOZ_SAFE_BROWSING +component {88fd40b6-c5c2-4120-9238-f2cb9ff98928} AboutRedirector.js +contract @mozilla.org/network/protocol/about;1?what=blocked {88fd40b6-c5c2-4120-9238-f2cb9ff98928} +#endif # DirectoryProvider.js component {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b} DirectoryProvider.js @@ -106,6 +110,13 @@ contract @mozilla.org/login-manager/prompter;1 {97d12931-abe2-11df-94e2-0800200c component {4e6ea350-b09a-11df-94e2-0800200c9a66} BlocklistPrompt.js contract @mozilla.org/addons/blocklist-prompt;1 {4e6ea350-b09a-11df-94e2-0800200c9a66} +#ifdef MOZ_SAFE_BROWSING +# SafeBrowsing.js +component {aadaed90-6c03-42d0-924a-fc61198ff283} SafeBrowsing.js +contract @mozilla.org/safebrowsing/application;1 {aadaed90-6c03-42d0-924a-fc61198ff283} +category app-startup SafeBrowsing service,@mozilla.org/safebrowsing/application;1 +#endif + #ifdef MOZ_UPDATER # UpdatePrompt.js component {88b3eb21-d072-4e3b-886d-f89d8c49fe59} UpdatePrompt.js diff --git a/mobile/components/SafeBrowsing.js b/mobile/components/SafeBrowsing.js new file mode 100644 index 000000000000..57cb8fba12f0 --- /dev/null +++ b/mobile/components/SafeBrowsing.js @@ -0,0 +1,200 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Safe Browsing. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Finkle + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +const kPhishWardenEnabledPref = "browser.safebrowsing.enabled"; +const kMalwareWardenEnabledPref = "browser.safebrowsing.malware.enabled"; + +// This XPCOM object doesn't have a public interface. It just works quietly in the background +function SafeBrowsing() { + this.listManager = null; + + // Once we register tables, their respective names will be listed here. + this.phishing = { + pref: kPhishWardenEnabledPref, + blackTables: [], + whiteTables: [] + }; + this.malware = { + pref: kMalwareWardenEnabledPref, + blackTables: [], + whiteTables: [] + }; + + // Get notifications when the phishing or malware warden enabled pref changes + Services.prefs.addObserver(kPhishWardenEnabledPref, this, true); + Services.prefs.addObserver(kMalwareWardenEnabledPref, this, true); +} + +SafeBrowsing.prototype = { + classID: Components.ID("{aadaed90-6c03-42d0-924a-fc61198ff283}"), + + QueryInterface: XPCOMUtils.generateQI([Ci.nsISessionStore, + Ci.nsIDOMEventListener, + Ci.nsIObserver, + Ci.nsISupportsWeakReference]), + + observe: function sb_observe(aSubject, aTopic, aData) { + switch (aTopic) { + case "app-startup": + Services.obs.addObserver(this, "final-ui-startup", true); + Services.obs.addObserver(this, "xpcom-shutdown", true); + break; + case "final-ui-startup": + Services.obs.removeObserver(this, "final-ui-startup"); + this._startup(); + break; + case "xpcom-shutdown": + Services.obs.removeObserver(this, "xpcom-shutdown"); + this._shutdown(); + break; + case "nsPref:changed": + if (aData == kPhishWardenEnabledPref) + this.maybeToggleUpdateChecking(this.phishing); + else if (aData == kMalwareWardenEnabledPref) + this.maybeToggleUpdateChecking(this.malware); + break; + } + }, + + _startup: function sb_startup() { + this.listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].getService(Ci.nsIUrlListManager); + + // Add a test chunk to the database + let testData = "mozilla.com/firefox/its-an-attack.html"; + let testUpdate = + "n:1000\ni:test-malware-simple\nad:1\n" + + "a:1:32:" + testData.length + "\n" + + testData; + + testData = "mozilla.com/firefox/its-a-trap.html"; + testUpdate += + "n:1000\ni:test-phish-simple\nad:1\n" + + "a:1:32:" + testData.length + "\n" + + testData; + + let dbService = Cc["@mozilla.org/url-classifier/dbservice;1"].getService(Ci.nsIUrlClassifierDBService); + + let listener = { + QueryInterface: function(aIID) { + if (aIID.equals(Ci.nsISupports) || aIID.equals(Ci.nsIUrlClassifierUpdateObserver)) + return this; + throw Cr.NS_ERROR_NO_INTERFACE; + }, + + updateUrlRequested: function(aURL) { }, + streamFinished: function(aStatus) { }, + updateError: function(aErrorCode) { }, + updateSuccess: function(aRequestedTimeout) { } + }; + + try { + dbService.beginUpdate(listener, "test-malware-simple,test-phish-simple", ""); + dbService.beginStream("", ""); + dbService.updateStream(testUpdate); + dbService.finishStream(); + dbService.finishUpdate(); + } catch(ex) {} + + this.registerBlackTable("goog-malware-shavar", this.malware); + this.maybeToggleUpdateChecking(this.malware); + + this.registerBlackTable("goog-phish-shavar", this.phishing); + this.maybeToggleUpdateChecking(this.phishing); + }, + + _shutdown: function sb_shutdown() { + Services.prefs.removeObserver(kPhishWardenEnabledPref, this); + Services.prefs.removeObserver(kMalwareWardenEnabledPref, this); + + this.listManager = null; + }, + + enableBlacklistTableUpdates: function sb_enableBlacklistTableUpdates(aWarden) { + for (let i = 0; i < aWarden.blackTables.length; ++i) { + this.listManager.enableUpdate(aWarden.blackTables[i]); + } + }, + + disableBlacklistTableUpdates: function sb_disableBlacklistTableUpdates(aWarden) { + for (let i = 0; i < aWarden.blackTables.length; ++i) { + this.listManager.disableUpdate(aWarden.blackTables[i]); + } + }, + + enableWhitelistTableUpdates: function sb_enableWhitelistTableUpdates(aWarden) { + for (let i = 0; i < this.whiteTables.length; ++i) { + this.listManager.enableUpdate(this.whiteTables[i]); + } + }, + + disableWhitelistTableUpdates: function sb_disableWhitelistTableUpdates(aWarden) { + for (let i = 0; i < aWarden.whiteTables.length; ++i) { + this.listManager.disableUpdate(aWarden.whiteTables[i]); + } + }, + + registerBlackTable: function sb_registerBlackTable(aTableName, aWarden) { + let result = this.listManager.registerTable(aTableName, false); + if (result) + aWarden.blackTables.push(aTableName); + return result; + }, + + registerWhiteTable: function sb_registerWhiteTable(aTableName, aWarden) { + let result = this.listManager.registerTable(aTableName, false); + if (result) + aWarden.whiteTables.push(aTableName); + return result; + }, + + maybeToggleUpdateChecking: function sb_maybeToggleUpdateChecking(aWarden) { + let enabled = Services.prefs.getBoolPref(aWarden.pref); + if (enabled) + this.enableBlacklistTableUpdates(aWarden); + else + this.disableBlacklistTableUpdates(aWarden); + } +} + +const NSGetFactory = XPCOMUtils.generateNSGetFactory([SafeBrowsing]); diff --git a/mobile/confvars.sh b/mobile/confvars.sh index 750cb578bda2..07a904d81a71 100644 --- a/mobile/confvars.sh +++ b/mobile/confvars.sh @@ -44,6 +44,7 @@ MOZ_BRANDING_DIRECTORY=mobile/branding/nightly MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/branding/official # MOZ_APP_DISPLAYNAME is set by branding/configure.sh +MOZ_SAFE_BROWSING=0 MOZ_SERVICES_SYNC=1 MOZ_ENABLE_LIBXUL=1 diff --git a/mobile/installer/package-manifest.in b/mobile/installer/package-manifest.in index b2fdf2564b6e..2c70ffc0d39a 100644 --- a/mobile/installer/package-manifest.in +++ b/mobile/installer/package-manifest.in @@ -405,12 +405,12 @@ @BINPATH@/modules/* ; Safe Browsing -@BINPATH@/components/nsSafebrowsingApplication.manifest -@BINPATH@/components/nsSafebrowsingApplication.js +#ifdef MOZ_SAFE_BROWSING @BINPATH@/components/nsURLClassifier.manifest @BINPATH@/components/nsUrlClassifierListManager.js @BINPATH@/components/nsUrlClassifierLib.js @BINPATH@/components/url-classifier.xpt +#endif ; GNOME hooks #ifdef MOZ_ENABLE_GNOME_COMPONENT @@ -606,6 +606,9 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@ @BINPATH@/components/PromptService.js @BINPATH@/components/SessionStore.js @BINPATH@/components/Sidebar.js +#ifdef MOZ_SAFE_BROWSING +@BINPATH@/components/SafeBrowsing.js +#endif #ifdef MOZ_UPDATER @BINPATH@/components/UpdatePrompt.js #endif diff --git a/mobile/locales/en-US/chrome/phishing.dtd b/mobile/locales/en-US/chrome/phishing.dtd new file mode 100644 index 000000000000..8e7a616fc739 --- /dev/null +++ b/mobile/locales/en-US/chrome/phishing.dtd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + has been reported as an attack page and has been blocked based on your security preferences."> +Attack pages try to install programs that steal private information, use your computer to attack others, or damage your system.

Some attack pages intentionally distribute harmful software, but many are compromised without the knowledge or permission of their owners.

"> + + + + has been reported as a web forgery and has been blocked based on your security preferences."> +Web forgeries are designed to trick you into revealing personal or financial information by imitating sources you may trust.

Entering any information on this web page may result in identity theft or other fraud.

"> diff --git a/mobile/locales/jar.mn b/mobile/locales/jar.mn index 16cfea4a5188..49414e01e4c1 100644 --- a/mobile/locales/jar.mn +++ b/mobile/locales/jar.mn @@ -17,6 +17,7 @@ locale/@AB_CD@/browser/sync.properties (%chrome/sync.properties) locale/@AB_CD@/browser/prompt.dtd (%chrome/prompt.dtd) locale/@AB_CD@/browser/feedback.dtd (%chrome/feedback.dtd) + locale/@AB_CD@/browser/phishing.dtd (%chrome/phishing.dtd) locale/@AB_CD@/browser/bookmarks.json (bookmarks.json) locale/@AB_CD@/browser/searchplugins/list.txt (%searchplugins/list.txt)