Bug 455906: Support severities for blocklist entries. r=robstrong, r=jst

--HG--
rename : toolkit/mozapps/extensions/content/list.xul => toolkit/mozapps/extensions/content/blocklist.xul
rename : toolkit/mozapps/extensions/public/nsIBlocklistService.idl => xpcom/system/nsIBlocklistService.idl
This commit is contained in:
Dave Townsend 2008-11-02 01:34:45 +00:00
parent b7fa702c3b
commit f6b515d08c
33 changed files with 1399 additions and 238 deletions

View File

@ -80,6 +80,9 @@ pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LO
// Blocklist preferences
pref("extensions.blocklist.enabled", true);
pref("extensions.blocklist.interval", 86400);
// Controls what level the blocklist switches from warning about items to forcibly
// blocking them.
pref("extensions.blocklist.level", 2);
pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/2/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/");
pref("extensions.blocklist.detailsURL", "http://%LOCALE%.www.mozilla.com/%LOCALE%/blocklist/");

View File

@ -92,6 +92,7 @@
#include "nsIPrefBranch2.h"
#include "nsIScriptChannel.h"
#include "nsPrintfCString.h"
#include "nsIBlocklistService.h"
// Friggin' X11 has to "#define None". Lame!
#ifdef None
@ -5129,13 +5130,14 @@ nsresult nsPluginHostImpl::ScanPluginsDirectory(nsIFile * pluginsDir,
RemoveCachedPluginsInfo(NS_ConvertUTF16toUTF8(pfd->mFilename).get(),
getter_AddRefs(pluginTag));
PRUint32 oldFlags = NS_PLUGIN_FLAG_ENABLED;
PRBool enabled = PR_TRUE;
PRBool seenBefore = PR_FALSE;
if (pluginTag) {
seenBefore = PR_TRUE;
// If plugin changed, delete cachedPluginTag and don't use cache
if (LL_NE(fileModTime, pluginTag->mLastModifiedTime)) {
// Plugins has changed. Don't use cached plugin info.
oldFlags = pluginTag->Flags() &
(NS_PLUGIN_FLAG_ENABLED | NS_PLUGIN_FLAG_BLOCKLISTED);
enabled = (pluginTag->Flags() & NS_PLUGIN_FLAG_ENABLED) != 0;
pluginTag = nsnull;
// plugin file changed, flag this fact
@ -5211,12 +5213,25 @@ nsresult nsPluginHostImpl::ScanPluginsDirectory(nsIFile * pluginsDir,
pluginTag->mLibrary = pluginLibrary;
pluginTag->mLastModifiedTime = fileModTime;
if (!(oldFlags & NS_PLUGIN_FLAG_ENABLED) ||
(pluginTag->mIsJavaPlugin && !mJavaEnabled))
pluginTag->UnMark(NS_PLUGIN_FLAG_ENABLED);
if (oldFlags & NS_PLUGIN_FLAG_BLOCKLISTED)
pluginTag->Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
nsCOMPtr<nsIBlocklistService> blocklist = do_GetService("@mozilla.org/extensions/blocklist;1");
if (blocklist) {
PRUint32 state;
rv = blocklist->GetPluginBlocklistState(pluginTag, EmptyString(),
EmptyString(), &state);
if (NS_SUCCEEDED(rv)) {
// If the blocklist says so then block the plugin. If the blocklist says
// it is risky and we have never seen this plugin before then disable it
if (state == nsIBlocklistService::STATE_BLOCKED)
pluginTag->Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
else if (state == nsIBlocklistService::STATE_SOFTBLOCKED && !seenBefore)
enabled = PR_FALSE;
}
}
if (!enabled || (pluginTag->mIsJavaPlugin && !mJavaEnabled))
pluginTag->UnMark(NS_PLUGIN_FLAG_ENABLED);
// if this is unwanted plugin we are checkin for, or this is a duplicate plugin,
// add it to our cache info list so we can cache the unwantedness of this plugin

View File

@ -0,0 +1,10 @@
<!ENTITY blocklist.title "Add-ons may be causing problems">
<!ENTITY blocklist.style "width: 45em; height: 30em">
<!ENTITY blocklist.summary "&brandShortName; has determined that the following add-ons are known to cause stability or security problems:">
<!ENTITY blocklist.softblocked "For your protection, it is highly recommended that you restart with these add-ons disabled.">
<!ENTITY blocklist.hardblocked "These add-ons have a high risk of causing stability or security problems and have been blocked, but a restart is required to disable them completely.">
<!ENTITY blocklist.softandhard "The add-ons that have a high risk of causing stability or security problems have been blocked. The others are lower risk, but it is highly recommended that you restart with them disabled.">
<!ENTITY blocklist.moreinfo "More information">
<!ENTITY blocklist.accept.label "Restart &brandShortName;">
<!ENTITY blocklist.accept.accesskey "R">

View File

@ -112,6 +112,7 @@
<!ENTITY insecureUpdate.label "Does not provide secure updates.">
<!ENTITY needsDependencies.label "Requires additional items.">
<!ENTITY blocklisted.label "Disabled for your protection.">
<!ENTITY softBlocklisted.label "Known to cause security or stability issues.">
<!ENTITY toBeDisabled.label "This add-on will be disabled when &brandShortName; is restarted.">
<!ENTITY toBeEnabled.label "This add-on will be enabled when &brandShortName; is restarted.">
<!ENTITY toBeInstalled.label "This add-on will be installed when &brandShortName; is restarted.">
@ -168,3 +169,6 @@
<!ENTITY eula.width "560px">
<!ENTITY eula.height "400px">
<!ENTITY eula.accept "Accept and Install…">
<!ENTITY blocklist.blocked.label "Blocked">
<!ENTITY blocklist.checkbox.label "Disable">

View File

@ -59,11 +59,12 @@ invalidGUIDMessage="%S" could not be installed because of an error in its Instal
invalidVersionMessage="%S" could not be installed because of an error in its Install Manifest ("%S" is not a valid Version String). Please contact the author of this item about the problem.
incompatiblePlatformMessage="%S" could not be installed because it is not compatible with your %S build type (%S). Please contact the author of this item about the problem.
blocklistedInstallTitle=This extension is not secure
blocklistedInstallMsg=The extension %S is known to be dangerous, and can't be installed.
blocklistNotifyTitle2=Add-ons may be causing problems
blocklistNotifyMsg2=%S has determined that the following add-ons may be unstable or insecure.
blocklistRestartMsg2=You should restart %S so that these add-ons can be disabled.
blocklistedInstallTitle2=This add-on is dangerous to use
blocklistedInstallMsg2=The add-on %S has a high risk of causing stability or security problems and can't be installed.
softBlockedInstallTitle=This add-on may be dangerous to use
softBlockedInstallMsg=The add-on %S may cause stability or security problems. It is highly recommended that you do not install it.
softBlockedInstallAcceptLabel=Install Anyway
softBlockedInstallAcceptKey=I
missingFileTitle=Missing File
missingFileMessage=%S could not load this item because the file %S was missing.

View File

@ -77,6 +77,7 @@
locale/@AB_CD@/mozapps/downloads/downloads.properties (%chrome/mozapps/downloads/downloads.properties)
locale/@AB_CD@/mozapps/extensions/extensions.dtd (%chrome/mozapps/extensions/extensions.dtd)
locale/@AB_CD@/mozapps/extensions/extensions.properties (%chrome/mozapps/extensions/extensions.properties)
locale/@AB_CD@/mozapps/extensions/blocklist.dtd (%chrome/mozapps/extensions/blocklist.dtd)
locale/@AB_CD@/mozapps/extensions/about.dtd (%chrome/mozapps/extensions/about.dtd)
locale/@AB_CD@/mozapps/extensions/errors.dtd (%chrome/mozapps/extensions/errors.dtd)
locale/@AB_CD@/mozapps/extensions/update.dtd (%chrome/mozapps/extensions/update.dtd)

View File

@ -0,0 +1,11 @@
hbox.addon-name-version {
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#addon-name-version");
}
.hardBlockedAddon {
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#hardblockedaddon");
}
.softBlockedAddon {
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#softblockedaddon");
}

View File

@ -0,0 +1,81 @@
# ***** 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 the Extension Blocklist UI.
#
# The Initial Developer of the Original Code is
# Mozilla Corporation
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Dave Townsend <dtownsend@oxymoronical.com>
#
# 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 *****
var gArgs;
function init() {
var hasHardBlocks = false;
var hasSoftBlocks = false;
gArgs = window.arguments[0].wrappedJSObject;
var richlist = document.getElementById("addonList");
var list = gArgs.list;
list.sort(function(a, b) { return String.localeCompare(a.name, b.name); });
for (let i = 0; i < list.length; i++) {
let item = document.createElement("richlistitem");
item.setAttribute("name", list[i].name);
item.setAttribute("version", list[i].version);
item.setAttribute("icon", list[i].icon);
if (list[i].blocked) {
item.setAttribute("class", "hardBlockedAddon");
hasHardBlocks = true;
}
else {
item.setAttribute("class", "softBlockedAddon");
hasSoftBlocks = true;
}
richlist.appendChild(item);
}
if (hasHardBlocks && hasSoftBlocks)
document.getElementById("bothMessage").hidden = false;
else if (hasHardBlocks)
document.getElementById("hardBlockMessage").hidden = false;
else
document.getElementById("softBlockMessage").hidden = false;
}
function accept() {
gArgs.restart = true;
var list = gArgs.list;
var items = document.getElementById("addonList").childNodes;
for (let i = 0; i < list.length; i++) {
if (!list[i].blocked)
list[i].disable = items[i].checked;
}
return true;
}

View File

@ -0,0 +1,80 @@
<?xml version="1.0"?>
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# ***** 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 the Extension List UI.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2005
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <ben@mozilla.org>
# Robert Strong <robert.bugzilla@gmail.com>
# Dave Townsend <dtownsend@oxymoronical.com>
#
# 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 *****
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://mozapps/skin/extensions/blocklist.css"?>
<?xml-stylesheet href="chrome://mozapps/content/extensions/blocklist.css"?>
<!DOCTYPE dialog [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%brandDTD;
<!ENTITY % extensionsDTD SYSTEM "chrome://mozapps/locale/extensions/blocklist.dtd">
%extensionsDTD;
]>
<dialog windowtype="Addons:Blocklist" title="&blocklist.title;" align="stretch"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="init();" ondialogaccept="return accept()"
buttons="accept,cancel" style="&blocklist.style;"
buttonlabelaccept="&blocklist.accept.label;"
buttonaccesskeyaccept="&blocklist.accept.accesskey;">
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript" src="chrome://mozapps/content/extensions/blocklist.js"/>
<hbox align="stretch" flex="1">
<vbox pack="start">
<image class="error-icon"/>
</vbox>
<vbox flex="1">
<label>&blocklist.summary;</label>
<separator class="thin"/>
<richlistbox id="addonList" flex="1"/>
<separator class="thin"/>
<description id="bothMessage" hidden="true" class="bold">&blocklist.softandhard;</description>
<description id="hardBlockMessage" hidden="true" class="bold">&blocklist.hardblocked;</description>
<description id="softBlockMessage" hidden="true" class="bold">&blocklist.softblocked;</description>
<hbox pack="start">
<label class="text-link" value="&blocklist.moreinfo;"/>
</hbox>
</vbox>
</hbox>
</dialog>

View File

@ -298,6 +298,7 @@ function showView(aView) {
["availableUpdateURL", "?availableUpdateURL"],
["availableUpdateVersion", "?availableUpdateVersion"],
["blocklisted", "?blocklisted"],
["blocklistedsoft", "?blocklistedsoft"],
["compatible", "?compatible"],
["description", "?description"],
["downloadURL", "?downloadURL"],
@ -384,6 +385,7 @@ function showView(aView) {
["availableUpdateVersion", "?availableUpdateVersion"],
["availableUpdateInfo", "?availableUpdateInfo"],
["blocklisted", "?blocklisted"],
["blocklistedsoft", "?blocklistedsoft"],
["homepageURL", "?homepageURL"],
["iconURL", "?iconURL"],
["internalName", "?internalName"],
@ -410,6 +412,7 @@ function showView(aView) {
["availableUpdateURL", "?availableUpdateURL"],
["availableUpdateVersion", "?availableUpdateVersion"],
["blocklisted", "?blocklisted"],
["blocklistedsoft", "?blocklistedsoft"],
["compatible", "?compatible"],
["description", "?description"],
["downloadURL", "?downloadURL"],
@ -918,6 +921,8 @@ function rebuildPluginsDS()
gPlugins[name][desc].plugins.push(plugin);
}
var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsIBlocklistService);
for (var pluginName in gPlugins) {
for (var pluginDesc in gPlugins[pluginName]) {
plugin = gPlugins[pluginName][pluginDesc];
@ -953,6 +958,11 @@ function rebuildPluginsDS()
gRDF.GetResource(PREFIX_NS_EM + "blocklisted"),
gRDF.GetLiteral(plugin.blocklisted ? "true" : "false"),
true);
var softblocked = blocklist.getPluginBlocklistState(plugin) == Ci.nsIBlocklistService.STATE_SOFTBLOCKED;
gPluginsDS.Assert(pluginNode,
gRDF.GetResource(PREFIX_NS_EM + "blocklistedsoft"),
gRDF.GetLiteral(softblocked ? "true" : "false"),
true);
gPluginsDS.Assert(pluginNode,
gRDF.GetResource(PREFIX_NS_EM + "compatible"),
gRDF.GetLiteral("true"),

View File

@ -95,6 +95,7 @@
<property name="type" onget="return parseInt(this.getAttribute('type'));"/>
<property name="isCompatible" onget="return this.getAttribute('compatible') == 'true';"/>
<property name="isBlocklisted" onget="return this.getAttribute('blocklisted') == 'true';"/>
<property name="isSoftBlocklisted" onget="return this.getAttribute('blocklistedsoft') == 'true';"/>
<property name="isDisabled" onget="return this.getAttribute('isDisabled') == 'true';"/>
<property name="providesUpdatesSecurely" onget="return this.getAttribute('providesUpdatesSecurely') == 'true';"/>
<property name="satisfiesDependencies" onget="return this.getAttribute('satisfiesDependencies') == 'true';"/>
@ -133,10 +134,36 @@
<xul:vbox flex="1" class="addonTextBox">
<xul:hbox class="addon-name-version" xbl:inherits="name, version"/>
<xul:hbox anonid="addonDescription" class="addon-description" xbl:inherits="description, opType"/>
<xul:vbox anonid="addonSelectedStatusMsgs" class="selectedStatusMsgs">
<xul:hbox flex="1" class="blocklistedBox attention" align="center">
<xul:label class="blocklistedLabel" value="&blocklisted.label;" crop="end"/>
<xul:label class="softBlocklistedLabel" value="&softBlocklisted.label;" crop="end"/>
<xul:label anonid="blocklistMoreInfo" class="text-link" value="&moreInfo.label;"
onclick="if (event.button == 0) { openURL(this.getAttribute('moreInfoURL')); }" />
</xul:hbox>
</xul:vbox>
</xul:vbox>
</xul:hbox>
</content>
<implementation implements="nsIAccessibleProvider, nsIDOMXULSelectControlItemElement">
<constructor>
<![CDATA[
if (this.isBlocklisted || this.isSoftBlocklisted) {
try {
var blocklistMoreInfo = document.getAnonymousElementByAttribute(this, "anonid", "blocklistMoreInfo");
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
.getService(Components.interfaces.nsIURLFormatter);
var url = formatter.formatURLPref("extensions.blocklist.detailsURL");
blocklistMoreInfo.setAttribute("moreInfoURL", url);
} catch(e) {
blocklistMoreInfo.hidden = true;
}
}
]]>
</constructor>
<field name="_addonDescription">
document.getAnonymousElementByAttribute(this, "anonid", "addonDescription");
</field>
@ -214,7 +241,8 @@
<xul:label value="&needsDependencies.label;" crop="end"/>
</xul:hbox>
<xul:hbox flex="1" class="blocklistedBox attention" align="center">
<xul:label value="&blocklisted.label;" crop="end"/>
<xul:label class="blocklistedLabel" value="&blocklisted.label;" crop="end"/>
<xul:label class="softBlocklistedLabel" value="&softBlocklisted.label;" crop="end"/>
<xul:label anonid="blocklistMoreInfo" class="text-link" value="&moreInfo.label;"
onclick="if (event.button == 0) { openURL(this.getAttribute('moreInfoURL')); }" />
</xul:hbox>
@ -259,7 +287,7 @@
<implementation implements="nsIAccessibleProvider, nsIDOMXULSelectControlItemElement">
<constructor>
<![CDATA[
if (this.isBlocklisted) {
if (this.isBlocklisted || this.isSoftBlocklisted) {
try {
var blocklistMoreInfo = document.getAnonymousElementByAttribute(this, "anonid", "blocklistMoreInfo");
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
@ -924,4 +952,40 @@
</implementation>
</binding>
<binding id="hardblockedaddon">
<content align="start">
<xul:image xbl:inherits="src=icon"/>
<xul:vbox flex="1">
<xul:hbox class="addon-name-version" xbl:inherits="name, version"/>
<xul:hbox>
<xul:spacer flex="1"/>
<xul:label class="blockedLabel" value="&blocklist.blocked.label;"/>
</xul:hbox>
</xul:vbox>
</content>
</binding>
<binding id="softblockedaddon">
<content align="start">
<xul:image xbl:inherits="src=icon"/>
<xul:vbox flex="1">
<xul:hbox class="addon-name-version" xbl:inherits="name, version"/>
<xul:hbox>
<xul:spacer flex="1"/>
<xul:checkbox class="disableCheckbox" checked="true" label="&blocklist.checkbox.label;"/>
</xul:hbox>
</xul:vbox>
</content>
<implementation>
<field name="_checkbox">
document.getAnonymousElementByAttribute(this, "class", "disableCheckbox")
</field>
<property name="checked" readonly="true">
<getter>
return this._checkbox.checked;
</getter>
</property>
</implementation>
</binding>
</bindings>

View File

@ -81,11 +81,9 @@ function init() {
var de = document.documentElement;
var items = [];
if (window.arguments[0] instanceof Components.interfaces.nsIDialogParamBlock) {
// This is a warning about a blocklisted item the user is trying to install
var args = window.arguments[0];
var fromInstall = args.GetInt(0) == 1 ? true : false;
var numberOfItems = args.GetInt(1);
for (var i = 0; i < numberOfItems; ++i)
items.push(args.GetString(i));
var softblocked = args.GetInt(0) == 1 ? true : false;
var extensionsBundle = document.getElementById("extensionsBundle");
try {
@ -95,45 +93,29 @@ function init() {
}
catch (e) { }
if (fromInstall) { // Blocklist blocked install
var params = {
message1: extensionsBundle.getFormattedString("blocklistedInstallMsg",
[items[0]]),
moreInfoURL: url,
title: extensionsBundle.getString("blocklistedInstallTitle")
};
items = [];
var button = document.getElementById("centeredButton");
button.setAttribute("dlgtype", "accept");
var params = {
moreInfoURL: url,
};
if (softblocked) {
params.title = extensionsBundle.getString("softBlockedInstallTitle");
params.message1 = extensionsBundle.getFormattedString("softBlockedInstallMsg",
[args.GetString(0)]);
var accept = de.getButton("accept");
accept.label = extensionsBundle.getString("softBlockedInstallAcceptLabel");
accept.accessKey = extensionsBundle.getString("softBlockedInstallAcceptKey");
de.getButton("cancel").focus();
document.addEventListener("dialogaccept", allowInstall, false);
}
else {
params.title = extensionsBundle.getString("blocklistedInstallTitle2");
params.message1 = extensionsBundle.getFormattedString("blocklistedInstallMsg2",
[args.GetString(0)]);
de.buttons = "accept";
de.getButton("accept").focus();
}
else { // Blocklist background notification
// only hide when not used due to focus issues
document.getElementById("buttonCenteredBox").hidden = true;
var brandBundle = document.getElementById("brandBundle");
var brandShortName = brandBundle.getString("brandShortName");
params = {
message1: extensionsBundle.getFormattedString("blocklistNotifyMsg2",
[brandShortName]),
message2: extensionsBundle.getFormattedString("blocklistRestartMsg2",
[brandShortName]),
moreInfoURL: url,
title: extensionsBundle.getString("blocklistNotifyTitle2")
};
de.buttons = "extra1,cancel";
button = de.getButton("cancel");
button.label = extensionsBundle.getString("laterButton");
de.setAttribute("ondialogextra1", "restartApp();");
button.focus();
button = de.getButton("extra1");
button.label = extensionsBundle.getFormattedString("restartButton",
[brandShortName]);
}
}
else {
// only hide when not used due to focus issues
document.getElementById("buttonCenteredBox").hidden = true;
items = window.arguments[0];
params = window.arguments[1];
}
@ -143,7 +125,7 @@ function init() {
document.getElementById("addonsTree").hidden = false;
// Fill the addons list
for (i = 0; i < items.length; ++i) {
for (var i = 0; i < items.length; ++i) {
var treeitem = document.createElementNS(kXULNS, "treeitem");
var treerow = document.createElementNS(kXULNS, "treerow");
var treecell = document.createElementNS(kXULNS, "treecell");
@ -185,7 +167,7 @@ function init() {
buttonString += "," + buttonType;
de.buttons = buttonString.substr(1);
for (buttonType in gButtons) {
button = de.getButton(buttonType);
var button = de.getButton(buttonType);
button.label = gButtons[buttonType].label;
if (gButtons[buttonType].focused)
button.focus();
@ -195,25 +177,13 @@ function init() {
}
function shutdown() {
for (buttonType in gButtons)
for (var buttonType in gButtons)
document.removeEventListener(kDialog + buttonType, handleButtonCommand, true);
}
function restartApp() {
const nsIAppStartup = Components.interfaces.nsIAppStartup;
// Notify all windows that an application quit has been requested.
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
.createInstance(Components.interfaces.nsISupportsPRBool);
os.notifyObservers(cancelQuit, "quit-application-requested", null);
// Something aborted the quit process.
if (cancelQuit.data)
return;
Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(nsIAppStartup)
.quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit);
function allowInstall() {
var args = window.arguments[0];
args.SetInt(1, 1);
}
/**

View File

@ -58,7 +58,7 @@
<vbox>
<image id="infoIcon"/>
</vbox>
<vbox class="spaced" style="min-width: 20em;">
<vbox class="spaced" style="min-width: 20em; max-width: 40em">
<label id="message1" class="spaced" hidden="true"/>
<separator class="thin"/>
<tree id="addonsTree" rows="6" hidecolumnpicker="true" hidden="true" class="spaced">
@ -75,9 +75,4 @@
</hbox>
</vbox>
</hbox>
<hbox id="buttonCenteredBox">
<spacer flex="1"/>
<button id="centeredButton"/>
<spacer flex="1"/>
</hbox>
</dialog>

View File

@ -9,6 +9,9 @@ toolkit.jar:
* content/mozapps/extensions/about.js (content/about.js)
* content/mozapps/extensions/list.xul (content/list.xul)
* content/mozapps/extensions/list.js (content/list.js)
* content/mozapps/extensions/blocklist.xul (content/blocklist.xul)
* content/mozapps/extensions/blocklist.js (content/blocklist.js)
* content/mozapps/extensions/blocklist.css (content/blocklist.css)
* content/mozapps/extensions/errors.xul (content/errors.xul)
* content/mozapps/extensions/update.xul (content/update.xul)
* content/mozapps/extensions/update.js (content/update.js)

View File

@ -46,7 +46,6 @@ XPIDL_MODULE = extensions
XPIDLSRCS = \
nsIExtensionManager.idl \
nsIBlocklistService.idl \
nsIAddonRepository.idl \
$(NULL)

View File

@ -199,7 +199,7 @@ interface nsIInstallLocation : nsISupports
* XXXben - Some of this stuff should go into a management-ey interface,
* some into an app-startup-ey interface.
*/
[scriptable, uuid(23080b61-dab9-48b7-bd68-b5ea23cae14b)]
[scriptable, uuid(7fbb049a-00e6-4ce2-82fc-854c52788df9)]
interface nsIExtensionManager : nsISupports
{
/**
@ -470,15 +470,20 @@ interface nsIExtensionManager : nsISupports
[retval, array, size_is(itemCount)] out nsIUpdateItem items);
/**
* Checks for changes to the blocklist using the local blocklist file,
* application disables / enables items that have been added / removed from
* the blocklist, and if there are additions to the blocklist this will
* inform the user by displaying a list of the items added.
* Checks for changes to the blocklist using the local blocklist file.
* This will immediately application disable items that have been hard blocked
* and application enable items that are no longer hard blocked. It will also
* return items that are either soft or hard blocked and aren't already
* disabled or disabled pending a restart.
*
* XXXrstrong - this method is not terribly useful and was added so we can
* trigger this check from the additional timer used by blocklisting.
* This is likely to change or go away in the future and should not be used
* by anyone outside of the blocklist service.
*
* @returns An array of nsIUpdateItems that are blocklisted or the user should
* be warned about but are currently enabled.
*/
void checkForBlocklistChanges();
void updateAndGetNewBlocklistedItems(out unsigned long itemCount,
[retval, array, size_is(itemCount)] out nsIUpdateItem items);
/**
* Sorts addons of the specified type by the specified property in the

View File

@ -53,6 +53,7 @@ const FILE_BLOCKLIST = "blocklist.xml";
const PREF_BLOCKLIST_URL = "extensions.blocklist.url";
const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled";
const PREF_BLOCKLIST_INTERVAL = "extensions.blocklist.interval";
const PREF_BLOCKLIST_LEVEL = "extensions.blocklist.level";
const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale";
const PREF_PARTNER_BRANCH = "app.partner.";
const PREF_APP_DISTRIBUTION = "distribution.id";
@ -62,6 +63,10 @@ const PREF_EM_LOGGING_ENABLED = "extensions.logging.enabled";
const XMLURI_BLOCKLIST = "http://www.mozilla.org/2006/addons-blocklist";
const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml"
const UNKNOWN_XPCOM_ABI = "unknownABI";
const URI_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"
const DEFAULT_SEVERITY = 3;
const DEFAULT_LEVEL = 2;
const MAX_BLOCK_LEVEL = 3;
const MODE_RDONLY = 0x01;
const MODE_WRONLY = 0x02;
@ -80,6 +85,8 @@ var gVersionChecker = null;
var gLoggingEnabled = null;
var gABI = null;
var gOSVersion = null;
var gBlocklistEnabled = true;
var gBlocklistLevel = DEFAULT_LEVEL;
// shared code for suppressing bad cert dialogs
#include ../../shared/src/badCertHandler.js
@ -187,6 +194,24 @@ function newURI(spec) {
return ioServ.newURI(spec, null, null);
}
// Restarts the application checking in with observers first
function restartApp() {
// Notify all windows that an application quit has been requested.
var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
createInstance(Ci.nsISupportsPRBool);
os.notifyObservers(cancelQuit, "quit-application-requested", null);
// Something aborted the quit process.
if (cancelQuit.data)
return;
var as = Cc["@mozilla.org/toolkit/app-startup;1"].
getService(Ci.nsIAppStartup);
as.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
}
/**
* Checks whether this blocklist element is valid for the current OS and ABI.
* If the element has an "os" attribute then the current OS must appear in
@ -217,9 +242,7 @@ function matchesOSABI(blocklistElement) {
function getLocale() {
try {
// Get the default branch
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
var defaultPrefs = prefs.getDefaultBranch(null);
var defaultPrefs = gPref.getDefaultBranch(null);
return defaultPrefs.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
} catch (e) {}
@ -236,9 +259,7 @@ function getUpdateChannel() {
var prefName;
var prefValue;
var defaults =
gPref.QueryInterface(Components.interfaces.nsIPrefService).
getDefaultBranch(null);
var defaults = gPref.getDefaultBranch(null);
try {
channel = defaults.getCharPref(PREF_APP_UPDATE_CHANNEL);
} catch (e) {
@ -268,9 +289,7 @@ function getUpdateChannel() {
function getDistributionPrefValue(aPrefName) {
var prefValue = "default";
var defaults =
gPref.QueryInterface(Components.interfaces.nsIPrefService).
getDefaultBranch(null);
var defaults = gPref.getDefaultBranch(null);
try {
prefValue = defaults.getCharPref(aPrefName);
} catch (e) {
@ -291,7 +310,8 @@ function Blocklist() {
gApp = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
gApp.QueryInterface(Ci.nsIXULRuntime);
gPref = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
getService(Ci.nsIPrefService).
QueryInterface(Ci.nsIPrefBranch2);
gVersionChecker = Cc["@mozilla.org/xpcom/version-comparator;1"].
getService(Ci.nsIVersionComparator);
gConsole = Cc["@mozilla.org/consoleservice;1"].
@ -363,24 +383,24 @@ Blocklist.prototype = {
observe: function (aSubject, aTopic, aData) {
switch (aTopic) {
case "app-startup":
gOS.addObserver(this, "plugins-list-updated", false);
gOS.addObserver(this, "profile-after-change", false);
gOS.addObserver(this, "quit-application", false);
break;
case "profile-after-change":
gLoggingEnabled = getPref("getBoolPref", PREF_EM_LOGGING_ENABLED, false);
gBlocklistEnabled = getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true);
gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL),
MAX_BLOCK_LEVEL);
gPref.addObserver("extensions.blocklist.", this, false);
var tm = Cc["@mozilla.org/updates/timer-manager;1"].
getService(Ci.nsIUpdateTimerManager);
var interval = getPref("getIntPref", PREF_BLOCKLIST_INTERVAL, 86400);
tm.registerTimer("blocklist-background-update-timer", this, interval);
break;
case "plugins-list-updated":
this._checkPluginsList();
break;
case "quit-application":
gOS.removeObserver(this, "plugins-list-updated");
gOS.removeObserver(this, "profile-after-change");
gOS.removeObserver(this, "quit-application");
gPref.removeObserver("extensions.blocklist.", this);
break;
case "xpcom-shutdown":
gOS.removeObserver(this, "xpcom-shutdown");
@ -390,30 +410,79 @@ Blocklist.prototype = {
gVersionChecker = null;
gApp = null;
break;
case "nsPref:changed":
switch (aData) {
case PREF_BLOCKLIST_ENABLED:
gBlocklistEnabled = getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true);
this._loadBlocklist();
this._blocklistUpdated(null, null);
break;
case PREF_BLOCKLIST_LEVEL:
gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL),
MAX_BLOCK_LEVEL);
this._blocklistUpdated(null, null);
break;
}
break;
}
},
/* See nsIBlocklistService */
isAddonBlocklisted: function(id, version, appVersion, toolkitVersion) {
return this.getAddonBlocklistState(id, version, appVersion, toolkitVersion) ==
Ci.nsIBlocklistService.STATE_BLOCKED;
},
/* See nsIBlocklistService */
getAddonBlocklistState: function(id, version, appVersion, toolkitVersion) {
if (!this._addonEntries)
this._loadBlocklist();
return this._getAddonBlocklistState(id, version, this._addonEntries,
appVersion, toolkitVersion);
},
/**
* Private version of getAddonBlocklistState that allows the caller to pass in
* the add-on blocklist entries to compare against.
*
* @param id
* The ID of the item to get the blocklist state for.
* @param version
* The version of the item to get the blocklist state for.
* @param addonEntries
* The add-on blocklist entries to compare against.
* @param appVersion
* The application version to compare to, will use the current
* version if null.
* @param toolkitVersion
* The toolkit version to compare to, will use the current version if
* null.
* @returns The blocklist state for the item, one of the STATE constants as
* defined in nsIBlocklistService.
*/
_getAddonBlocklistState: function(id, version, addonEntries, appVersion, toolkitVersion) {
if (!gBlocklistEnabled)
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
if (!appVersion)
appVersion = gApp.version;
if (!toolkitVersion)
toolkitVersion = gApp.platformVersion;
var blItem = this._addonEntries[id];
var blItem = addonEntries[id];
if (!blItem)
return false;
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
for (var i = 0; i < blItem.length; ++i) {
if (blItem[i].includesItem(version, appVersion, toolkitVersion))
return true;
return blItem[i].severity >= gBlocklistLevel ? Ci.nsIBlocklistService.STATE_BLOCKED :
Ci.nsIBlocklistService.STATE_SOFTBLOCKED;
}
return false;
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
},
notify: function(aTimer) {
if (getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true) == false)
if (!gBlocklistEnabled)
return;
try {
@ -463,6 +532,11 @@ Blocklist.prototype = {
request.onerror = function(event) { self.onXMLError(event); };
request.onload = function(event) { self.onXMLLoad(event); };
request.send(null);
// When the blocklist loads we need to compare it to the current copy so
// make sure we have loaded it.
if (!this._addonEntries)
this._loadBlocklist();
},
onXMLLoad: function(aEvent) {
@ -486,11 +560,14 @@ Blocklist.prototype = {
var fos = openSafeFileOutputStream(blocklistFile);
fos.write(request.responseText, request.responseText.length);
closeSafeFileOutputStream(fos);
var oldAddonEntries = this._addonEntries;
var oldPluginEntries = this._pluginEntries;
this._addonEntries = { };
this._pluginEntries = { };
this._loadBlocklistFromFile(getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]));
var em = Cc["@mozilla.org/extensions/manager;1"].
getService(Ci.nsIExtensionManager);
em.checkForBlocklistChanges();
this._checkPluginsList();
this._blocklistUpdated(oldAddonEntries, oldPluginEntries);
},
onXMLError: function(aEvent) {
@ -584,7 +661,7 @@ Blocklist.prototype = {
*/
_loadBlocklistFromFile: function(file) {
if (getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true) == false) {
if (!gBlocklistEnabled) {
LOG("Blocklist::_loadBlocklistFromFile: blocklist is disabled");
return;
}
@ -690,11 +767,47 @@ Blocklist.prototype = {
if (matchElement.localName == "versionRange")
blockEntry.versions.push(new BlocklistItemData(matchElement));
}
// Add a default versionRange if there wasn't one specified
if (blockEntry.versions.length == 0)
blockEntry.versions.push(new BlocklistItemData(null));
result.push(blockEntry);
},
_isPluginBlocklisted: function(plugin, appVersion, toolkitVersion) {
for each (var blockEntry in this._pluginEntries) {
/* See nsIBlocklistService */
getPluginBlocklistState: function(plugin, appVersion, toolkitVersion) {
if (!this._pluginEntries)
this._loadBlocklist();
return this._getPluginBlocklistState(plugin, this._pluginEntries,
appVersion, toolkitVersion);
},
/**
* Private version of getPluginBlocklistState that allows the caller to pass in
* the plugin blocklist entries.
*
* @param plugin
* The nsIPluginTag to get the blocklist state for.
* @param pluginEntries
* The plugin blocklist entries to compare against.
* @param appVersion
* The application version to compare to, will use the current
* version if null.
* @param toolkitVersion
* The toolkit version to compare to, will use the current version if
* null.
* @returns The blocklist state for the item, one of the STATE constants as
* defined in nsIBlocklistService.
*/
_getPluginBlocklistState: function(plugin, pluginEntries, appVersion, toolkitVersion) {
if (!gBlocklistEnabled)
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
if (!appVersion)
appVersion = gApp.version;
if (!toolkitVersion)
toolkitVersion = gApp.platformVersion;
for each (var blockEntry in pluginEntries) {
var matchFailed = false;
for (var name in blockEntry.matches) {
if (!(name in plugin) ||
@ -708,30 +821,104 @@ Blocklist.prototype = {
if (matchFailed)
continue;
// No version ranges means match any versions
if (blockEntry.versions.length == 0)
return true;
for (var i = 0; i < blockEntry.versions.length; i++) {
if (blockEntry.versions[i].includesItem(plugin.version, appVersion,
toolkitVersion))
return true;
return blockEntry.versions[i].severity >= gBlocklistLevel ?
Ci.nsIBlocklistService.STATE_BLOCKED :
Ci.nsIBlocklistService.STATE_SOFTBLOCKED;
}
}
return false;
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
},
_checkPluginsList: function() {
if (!this._addonEntries)
this._loadBlocklist();
_blocklistUpdated: function(oldAddonEntries, oldPluginEntries) {
var addonList = [];
var em = Cc["@mozilla.org/extensions/manager;1"].
getService(Ci.nsIExtensionManager);
var addons = em.updateAndGetNewBlocklistedItems({});
for (let i = 0; i < addons.length; i++) {
let oldState = -1;
if (oldAddonEntries)
oldState = this._getAddonBlocklistState(addons[i].id, addons[i].version,
oldAddonEntries);
let state = this.getAddonBlocklistState(addons[i].id, addons[i].version);
// We don't want to re-warn about items
if (state == oldState)
continue;
addonList.push({
name: addons[i].name,
version: addons[i].version,
icon: addons[i].iconURL,
disable: false,
blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
item: addons[i]
});
}
var phs = Cc["@mozilla.org/plugin/host;1"].
getService(Ci.nsIPluginHost);
var plugins = phs.getPluginTags({});
for (var i = 0; i < plugins.length; i++)
plugins[i].blocklisted = this._isPluginBlocklisted(plugins[i],
gApp.version,
gApp.platformVersion);
for (let i = 0; i < plugins.length; i++) {
let oldState = -1;
if (oldPluginEntries)
oldState = this._getPluginBlocklistState(plugins[i], oldPluginEntries);
let state = this.getPluginBlocklistState(plugins[i]);
// We don't want to re-warn about items
if (state == oldState)
continue;
if (plugins[i].blocklisted) {
if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
plugins[i].disabled = true;
}
else if (!plugins[i].disabled && state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
addonList.push({
name: plugins[i].name,
version: plugins[i].version,
icon: "chrome://mozapps/skin/plugins/pluginGeneric.png",
disable: false,
blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
item: plugins[i]
});
}
plugins[i].blocklisted = state == Ci.nsIBlocklistService.STATE_BLOCKED;
}
if (addonList.length == 0)
return;
var args = {
restart: false,
list: addonList
};
// This lets the dialog get the raw js object
args.wrappedJSObject = args;
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
ww.openWindow(null, URI_BLOCKLIST_DIALOG, "",
"chrome,centerscreen,dialog,modal,titlebar", args);
for (let i = 0; i < addonList.length; i++) {
if (!addonList[i].disable)
continue;
if (addonList[i].item instanceof Ci.nsIUpdateItem)
em.disableItem(addonList[i].item.id);
else if (addonList[i].item instanceof Ci.nsIPluginTag)
addonList[i].item.disabled = true;
else
LOG("Unknown add-on type: " + addonList[i].item);
}
if (args.restart)
restartApp();
},
classDescription: "Blocklist Service",
@ -753,6 +940,10 @@ function BlocklistItemData(versionRangeElement) {
var versionRange = this.getBlocklistVersionRange(versionRangeElement);
this.minVersion = versionRange.minVersion;
this.maxVersion = versionRange.maxVersion;
if (versionRangeElement && versionRangeElement.hasAttribute("severity"))
this.severity = versionRangeElement.getAttribute("severity");
else
this.severity = DEFAULT_SEVERITY;
this.targetApps = { };
var found = false;

View File

@ -152,6 +152,7 @@ const INSTALLERROR_BLOCKLISTED = -6;
const INSTALLERROR_INSECURE_UPDATE = -7;
const INSTALLERROR_INVALID_MANIFEST = -8;
const INSTALLERROR_RESTRICTED = -9;
const INSTALLERROR_SOFTBLOCKED = -10;
const MODE_RDONLY = 0x01;
const MODE_WRONLY = 0x02;
@ -769,33 +770,30 @@ function showMessage(titleKey, titleParams, messageKey, messageParams) {
}
/**
* Shows a dialog for blocklisted items.
* @param items
* An array of nsIUpdateItems.
* @param fromInstall
* Whether this is called from an install or from the blocklist
* background check.
* Shows a dialog for a blocklisted item. For soft blocked items this will
* return true if the item should still be installed
* @param item
* The nsIUpdateItem that is blocklisted
* @param softblocked
* True if this item is only soft blocked and may still be installed.
*/
function showBlocklistMessage(items, fromInstall) {
var win = null;
function showBlocklistMessage(item, softblocked) {
var params = Cc["@mozilla.org/embedcomp/dialogparam;1"].
createInstance(Ci.nsIDialogParamBlock);
params.SetInt(0, (fromInstall ? 1 : 0));
params.SetInt(1, items.length);
params.SetNumberStrings(items.length * 2);
for (var i = 0; i < items.length; ++i)
params.SetString(i, items[i].name + " " + items[i].version);
params.SetInt(0, softblocked ? 1 : 0);
params.SetInt(1, 0);
params.SetNumberStrings(1);
params.SetString(0, item.name + " " + item.version);
// if this was initiated from an install try to find the appropriate manager
if (fromInstall) {
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
win = wm.getMostRecentWindow("Extension:Manager");
}
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow("Extension:Manager");
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
ww.openWindow(win, URI_EXTENSION_LIST_DIALOG, "",
"chrome,centerscreen,modal,dialog,titlebar", params);
return params.GetInt(1) == 0 ? false : true;
}
/**
@ -2979,6 +2977,11 @@ ExtensionManager.prototype = {
callback(installManifest, installData.id, location, installData.type);
this._appDisableItem(id);
}
else if (installData.error == INSTALLERROR_SOFTBLOCKED) {
LOG("... success, item installed but is soft blocked, item will be disabled");
callback(installManifest, installData.id, location, installData.type);
this.disableItem(id);
}
else {
/**
* Turns an error code into a message for logging
@ -4256,9 +4259,11 @@ ExtensionManager.prototype = {
if (!gBlocklist)
gBlocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsIBlocklistService);
if (gBlocklist.isAddonBlocklisted(installData.id, installData.version,
null, null))
var state = gBlocklist.getAddonBlocklistState(installData.id, installData.version);
if (state == Ci.nsIBlocklistService.STATE_BLOCKED)
installData.error = INSTALLERROR_BLOCKLISTED;
else if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
installData.error = INSTALLERROR_SOFTBLOCKED;
return installData;
},
@ -4482,7 +4487,7 @@ ExtensionManager.prototype = {
* @param installRDF
* The install.rdf file that was extracted from the xpi.
*/
checkForUpdates: function EM_checkForUpdates(item, installManifest, xpiFile) {
checkForUpdates: function IncObs_checkForUpdates(item, installManifest, xpiFile) {
this._xpi = xpiFile;
this._installManifest = installManifest;
@ -4495,21 +4500,21 @@ ExtensionManager.prototype = {
/**
* See nsIExtensionManager.idl
*/
onUpdateStarted: function EM_onUpdateStarted() {
onUpdateStarted: function IncObs_onUpdateStarted() {
LOG("Phone Home Listener: Update Started");
},
/**
* See nsIExtensionManager.idl
*/
onUpdateEnded: function EM_onUpdateEnded() {
onUpdateEnded: function IncObs_onUpdateEnded() {
LOG("Phone Home Listener: Update Ended");
},
/**
* See nsIExtensionManager.idl
*/
onAddonUpdateStarted: function EM_onAddonUpdateStarted(addon) {
onAddonUpdateStarted: function IncObs_onAddonUpdateStarted(addon) {
if (!addon)
throw Cr.NS_ERROR_INVALID_ARG;
@ -4521,7 +4526,7 @@ ExtensionManager.prototype = {
/**
* See nsIExtensionManager.idl
*/
onAddonUpdateEnded: function EM_onAddonUpdateEnded(addon, status) {
onAddonUpdateEnded: function IncObs_onAddonUpdateEnded(addon, status) {
if (!addon)
throw Cr.NS_ERROR_INVALID_ARG;
@ -4666,6 +4671,10 @@ ExtensionManager.prototype = {
gApp.platformVersion + ". Remote compatibility check was not performed.");
}
break;
case INSTALLERROR_SOFTBLOCKED:
if (!showBlocklistMessage(installData, true))
break;
// Fall through to continue the install
case INSTALLERROR_SUCCESS:
// Installation of multiple extensions / themes contained within a single xpi.
if (installData.type == Ci.nsIUpdateItem.TYPE_MULTI_XPI) {
@ -4759,7 +4768,7 @@ ExtensionManager.prototype = {
case INSTALLERROR_BLOCKLISTED:
LOG("Blocklisted Item: Item: \"" + installData.id + "\" version " +
installData.version + " was not installed.");
showBlocklistMessage([installData], true);
showBlocklistMessage(installData, false);
break;
case INSTALLERROR_INSECURE_UPDATE:
LOG("No secure updates: Item: \"" + installData.id + "\" version " +
@ -5489,32 +5498,51 @@ ExtensionManager.prototype = {
},
/**
* Checks for changes to the blocklist using the local blocklist file,
* application disables / enables items that have been added / removed from
* the blocklist, and if there are additions to the blocklist this will
* inform the user by displaying a list of the items added.
*
* XXXrstrong - this method is not terribly useful and was added so we can
* trigger this check from the additional timer used by blocklisting.
* See nsIExtensionManager.idl
*/
checkForBlocklistChanges: function EM_checkForBlocklistChanges() {
updateAndGetNewBlocklistedItems: function EM_updateAndGetNewBlocklistedItems(itemCount) {
if (!gBlocklist)
gBlocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsIBlocklistService);
var list = [];
var ds = this.datasource;
var items = this.getItemList(Ci.nsIUpdateItem.TYPE_ANY, { });
for (var i = 0; i < items.length; ++i) {
var id = items[i].id;
ds.updateProperty(id, "blocklisted");
if (this._isUsableItem(id))
// Get whether the add-on is currently disabled or set to be disabled.
var appDisabled = (ds.getItemProperty(id, "appDisabled") == "true" ||
ds.getItemProperty(id, "appDisabled") == OP_NEEDS_DISABLE);
var userDisabled = (ds.getItemProperty(id, "userDisabled") == "true" ||
ds.getItemProperty(id, "userDisabled") == OP_NEEDS_DISABLE);
var usable = this._isUsableItem(id);
var state = gBlocklist.getAddonBlocklistState(items[i].id, items[i].version);
// We only return items that are now blocked or to be warned about and aren't
// already disabled for some reason.
if (!appDisabled && !userDisabled && state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED)
list.push(items[i]);
// Update the appDisabled status based on the new blocked state
if (usable)
this._appEnableItem(id);
else
this._appDisableItem(id);
// If the item was appDisabled and is now usable then it is something
// that is no longer hard blocked. If it is still to be warned about then
// just user disable it.
if (appDisabled && usable && !userDisabled &&
state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
this.disableItem(id);
ds.updateProperty(id, "blocklisted");
ds.updateProperty(id, "blocklistedsoft");
}
items = ds.getBlocklistedItemList(null, null, Ci.nsIUpdateItem.TYPE_ANY,
false);
for (i = 0; i < items.length; ++i)
this._appDisableItem(items[i].id);
// show the blocklist notification window if there are new blocklist items.
if (items.length > 0)
showBlocklistMessage(items, false);
itemCount.value = list.length;
return list;
},
/**
@ -5563,14 +5591,7 @@ ExtensionManager.prototype = {
return this.datasource.getDependentItemListForID(id, includeDisabled, countRef);
},
/**
* Retrieves a list of nsIUpdateItems of items matching the specified type.
* @param type
* The type of item to return.
* @param countRef
* The XPCJS reference to the number of items returned.
* @returns An array of nsIUpdateItems matching the id/type filter.
*/
/* See nsIExtensionManager.idl */
getItemList: function EM_getItemList(type, countRef) {
return this.datasource.getItemList(type, countRef);
},
@ -6311,8 +6332,10 @@ ExtensionItemUpdater.prototype = {
if (!gBlocklist)
gBlocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsIBlocklistService);
// Denies updates that are hard blocked, soft blocked items will be warned
// about during the install.
if (gBlocklist.isAddonBlocklisted(aLocalItem.id, aRemoteItem.version,
null, null))
this._appVersion, this._platformVersion))
return false;
return true;
@ -7242,49 +7265,6 @@ ExtensionsDataSource.prototype = {
return items;
},
/**
* Retrieves a list of items that will be blocklisted by the application for
* a specific application or toolkit version.
* @param appVersion
* The Version of the application to check the blocklist against.
* @param platformVersion
* The Version of the toolkit to check the blocklist against.
* @param desiredType
* The nsIUpdateItem type of items to look for
* @param includeAppDisabled
* Whether or not items that are or are already set to be disabled
* by the app on next restart should be included in the set returned
* @returns An array of nsIUpdateItems that are blocklisted with the application
* or toolkit version supplied.
*/
getBlocklistedItemList: function EMDS_getBlocklistedItemList(appVersion,
platformVersion,
desiredType,
includeAppDisabled) {
if (!gBlocklist)
gBlocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsIBlocklistService);
var items = [];
var ctr = getContainer(this._inner, this._itemRoot);
var elements = ctr.GetElements();
while (elements.hasMoreElements()) {
var item = elements.getNext().QueryInterface(Ci.nsIRDFResource);
var id = stripPrefix(item.Value, PREFIX_ITEM_URI);
var type = this.getItemProperty(id, "type");
if (!includeAppDisabled &&
(this.getItemProperty(id, "appDisabled") == "true" ||
this.getItemProperty(id, "appDisabled") == OP_NEEDS_DISABLE))
continue;
var version = this.getItemProperty(id, "version");
if (type != -1 && (type & desiredType) &&
gBlocklist.isAddonBlocklisted(id, version, appVersion, platformVersion))
items.push(this.getItemForID(id));
}
return items;
},
/**
* Gets a list of items of a specific type
* @param desiredType
@ -8455,7 +8435,23 @@ ExtensionsDataSource.prototype = {
if (!gBlocklist)
gBlocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsIBlocklistService);
if (gBlocklist.isAddonBlocklisted(id, version, null, null))
if (gBlocklist.getAddonBlocklistState(id, version) == Ci.nsIBlocklistService.STATE_BLOCKED)
return EM_L("true");
return EM_L("false");
},
/**
* Get the em:blocklistedsoft property (whether or not this item is listed in the blocklist
* at a low severity)
*/
_rdfGet_blocklistedsoft: function EMDS__rdfGet_blocklistedsoft(item, property) {
var id = stripPrefix(item.Value, PREFIX_ITEM_URI);
var version = this.getItemProperty(id, "version");
if (!gBlocklist)
gBlocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsIBlocklistService);
if (gBlocklist.getAddonBlocklistState(id, version) == Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
return EM_L("true");
return EM_L("false");

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem id="test_bug455906_1@tests.mozilla.org"/>
<emItem id="test_bug455906_2@tests.mozilla.org"/>
<emItem id="test_bug455906_3@tests.mozilla.org"/>
<emItem id="test_bug455906_4@tests.mozilla.org"/>
<emItem id="test_bug455906_5@tests.mozilla.org"/>
<emItem id="test_bug455906_6@tests.mozilla.org"/>
<emItem id="test_bug455906_7@tests.mozilla.org"/>
</emItems>
<pluginItems>
<pluginItem>
<match name="name" exp="^test_bug455906"/>
</pluginItem>
</pluginItems>
</blocklist>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem id="dummy_bug455906_2@tests.mozilla.org"/>
</emItems>
</blocklist>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem id="test_bug455906_4@tests.mozilla.org">
<versionRange severity="0"/>
</emItem>
<emItem id="test_bug455906_5@tests.mozilla.org">
<versionRange severity="1"/>
</emItem>
<emItem id="test_bug455906_6@tests.mozilla.org">
<versionRange severity="2"/>
</emItem>
<emItem id="dummy_bug455906_1@tests.mozilla.org"/>
</emItems>
<pluginItems>
<pluginItem>
<match name="name" exp="^test_bug455906_4$"/>
<versionRange severity="0"/>
</pluginItem>
<pluginItem>
<match name="name" exp="^test_bug455906_5$"/>
<versionRange severity="1"/>
</pluginItem>
<pluginItem>
<match name="name" exp="^test_bug455906_6$"/>
<versionRange severity="2"/>
</pluginItem>
</pluginItems>
</blocklist>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem id="test_bug455906_1@tests.mozilla.org">
<versionRange severity="0"/>
</emItem>
<emItem id="test_bug455906_2@tests.mozilla.org">
<versionRange severity="0"/>
</emItem>
<emItem id="test_bug455906_3@tests.mozilla.org">
<versionRange severity="0"/>
</emItem>
<emItem id="test_bug455906_4@tests.mozilla.org">
<versionRange severity="0"/>
</emItem>
<emItem id="test_bug455906_5@tests.mozilla.org">
<versionRange severity="0"/>
</emItem>
<emItem id="test_bug455906_6@tests.mozilla.org">
<versionRange severity="0"/>
</emItem>
<emItem id="test_bug455906_7@tests.mozilla.org">
<versionRange severity="0"/>
</emItem>
</emItems>
<pluginItems>
<pluginItem>
<match name="name" exp="^test_bug455906"/>
<versionRange severity="0"/>
</pluginItem>
</pluginItems>
</blocklist>

View File

@ -35,7 +35,7 @@
*
* ***** END LICENSE BLOCK *****
*/
const URI_EXTENSION_LIST_DIALOG = "chrome://mozapps/content/extensions/list.xul";
const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
do_import_script("netwerk/test/httpserver/httpd.js");
@ -426,14 +426,15 @@ var PluginHostFactory = {
var WindowWatcher = {
openWindow: function(parent, url, name, features, arguments) {
// Should be called to list the newly blocklisted items
do_check_eq(url, URI_EXTENSION_LIST_DIALOG);
do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG);
do_check_neq(gCallback, null);
do_check_true(arguments instanceof Components.interfaces.nsIDialogParamBlock);
var args = arguments.wrappedJSObject;
gNewBlocks = [];
var count = arguments.GetInt(1);
for (var i = 0; i < count; i++)
gNewBlocks.push(arguments.GetString(i));
var list = args.list;
for (var i = 0; i < list.length; i++)
gNewBlocks.push(list[i].name + " " + list[i].version);
// Call the callback after the blocklist has finished up
do_timeout(0, "gCallback()");
@ -518,6 +519,13 @@ function check_state(test, lastTest) {
expected++;
}
}
for (i = 0; i < PLUGINS.length; i++) {
if (PLUGINS[i][test] && !PLUGINS[i][lastTest]) {
if (gNewBlocks.indexOf(PLUGINS[i].name + " " + PLUGINS[i].version) < 0)
do_throw("Plugin " + (i + 1) + " should have been listed in the blocklist notification for test " + test);
expected++;
}
}
do_check_eq(expected, gNewBlocks.length);
}
@ -540,6 +548,7 @@ function run_test() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8");
startupEM();
gTestserver = new nsHttpServer();
gTestserver.registerDirectory("/data/", do_get_file("toolkit/mozapps/extensions/test/unit/data"));
gTestserver.start(4444);

View File

@ -0,0 +1,531 @@
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Dave Townsend <dtownsend@oxymoronical.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
do_import_script("netwerk/test/httpserver/httpd.js");
var ADDONS = [{
// Tests how the blocklist affects a disabled add-on
id: "test_bug455906_1@tests.mozilla.org",
name: "Bug 455906 Addon Test 1",
version: "5",
appVersion: "3"
}, {
// Tests how the blocklist affects an enabled add-on
id: "test_bug455906_2@tests.mozilla.org",
name: "Bug 455906 Addon Test 2",
version: "5",
appVersion: "3"
}, {
// Tests how the blocklist affects an enabled add-on, to be disabled by the notification
id: "test_bug455906_3@tests.mozilla.org",
name: "Bug 455906 Addon Test 3",
version: "5",
appVersion: "3"
}, {
// Tests how the blocklist affects a disabled add-on that was already warned about
id: "test_bug455906_4@tests.mozilla.org",
name: "Bug 455906 Addon Test 4",
version: "5",
appVersion: "3"
}, {
// Tests how the blocklist affects an enabled add-on that was already warned about
id: "test_bug455906_5@tests.mozilla.org",
name: "Bug 455906 Addon Test 5",
version: "5",
appVersion: "3"
}, {
// Tests how the blocklist affects an already blocked add-on
id: "test_bug455906_6@tests.mozilla.org",
name: "Bug 455906 Addon Test 6",
version: "5",
appVersion: "3"
}, {
// Tests how the blocklist affects an incompatible add-on
id: "test_bug455906_7@tests.mozilla.org",
name: "Bug 455906 Addon Test 7",
version: "5",
appVersion: "2"
}, {
// Spare add-on used to ensure we get a notification when switching lists
id: "dummy_bug455906_1@tests.mozilla.org",
name: "Dummy Addon 1",
version: "5",
appVersion: "3"
}, {
// Spare add-on used to ensure we get a notification when switching lists
id: "dummy_bug455906_2@tests.mozilla.org",
name: "Dummy Addon 2",
version: "5",
appVersion: "3"
}];
var PLUGINS = [{
// Tests how the blocklist affects a disabled plugin
name: "test_bug455906_1",
version: "5",
disabled: true,
blocklisted: false
}, {
// Tests how the blocklist affects an enabled plugin
name: "test_bug455906_2",
version: "5",
disabled: false,
blocklisted: false
}, {
// Tests how the blocklist affects an enabled plugin, to be disabled by the notification
name: "test_bug455906_3",
version: "5",
disabled: false,
blocklisted: false
}, {
// Tests how the blocklist affects a disabled plugin that was already warned about
name: "test_bug455906_4",
version: "5",
disabled: true,
blocklisted: false
}, {
// Tests how the blocklist affects an enabled plugin that was already warned about
name: "test_bug455906_5",
version: "5",
disabled: false,
blocklisted: false
}, {
// Tests how the blocklist affects an already blocked plugin
name: "test_bug455906_6",
version: "5",
disabled: false,
blocklisted: true
}];
var gNotificationCheck = null;
var gTestCheck = null;
var gTestserver = null;
// A fake plugin host for the blocklist service to use
var PluginHost = {
getPluginTags: function(countRef) {
countRef.value = PLUGINS.length;
return PLUGINS;
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsIPluginHost)
|| iid.equals(Ci.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
}
var PluginHostFactory = {
createInstance: function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return PluginHost.QueryInterface(iid);
}
};
// Don't need the full interface, attempts to call other methods will just
// throw which is just fine
var WindowWatcher = {
openWindow: function(parent, url, name, features, arguments) {
// Should be called to list the newly blocklisted items
do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG);
if (gNotificationCheck) {
var args = arguments.wrappedJSObject;
gNotificationCheck(args);
}
// Call the next test after the blocklist has finished up
do_timeout(0, "gTestCheck()");
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsIWindowWatcher)
|| iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
}
var WindowWatcherFactory = {
createInstance: function createInstance(outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return WindowWatcher.QueryInterface(iid);
}
};
var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"),
"Fake Plugin Host",
"@mozilla.org/plugin/host;1", PluginHostFactory);
registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"),
"Fake Window Watcher",
"@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory);
function create_addon(addon) {
var installrdf = "<?xml version=\"1.0\"?>\n" +
"\n" +
"<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" +
" xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" +
" <Description about=\"urn:mozilla:install-manifest\">\n" +
" <em:id>" + addon.id + "</em:id>\n" +
" <em:version>" + addon.version + "</em:version>\n" +
" <em:targetApplication>\n" +
" <Description>\n" +
" <em:id>xpcshell@tests.mozilla.org</em:id>\n" +
" <em:minVersion>" + addon.appVersion + "</em:minVersion>\n" +
" <em:maxVersion>" + addon.appVersion + "</em:maxVersion>\n" +
" </Description>\n" +
" </em:targetApplication>\n" +
" <em:name>" + addon.name + "</em:name>\n" +
" </Description>\n" +
"</RDF>\n";
var target = gProfD.clone();
target.append("extensions");
target.append(addon.id);
target.append("install.rdf");
target.create(target.NORMAL_FILE_TYPE, 0644);
var stream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
stream.init(target, 0x04 | 0x08 | 0x20, 0664, 0); // write, create, truncate
stream.write(installrdf, installrdf.length);
stream.close();
}
function load_blocklist(file) {
gPrefs.setCharPref("extensions.blocklist.url", "http://localhost:4444/data/" + file);
var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService(Ci.nsITimerCallback);
blocklist.notify(null);
}
function isUserDisabled(id) {
return getManifestProperty(id, "userDisabled") == "true";
}
function isAppDisabled(id) {
return getManifestProperty(id, "appDisabled") == "true";
}
function check_addon_state(id) {
return isUserDisabled(id) + "," + isAppDisabled(id);
}
function check_plugin_state(plugin) {
return plugin.disabled + "," + plugin.blocklisted;
}
// Performs the initial setup
function run_test() {
// Setup for test
dump("Setting up tests\n");
// Rather than keeping lots of identical add-ons in version control, just
// write them into the profile.
for (var i = 0; i < ADDONS.length; i++)
create_addon(ADDONS[i]);
// Copy the initial blocklist into the profile to check add-ons start in the
// right state.
var blocklist = do_get_file("toolkit/mozapps/extensions/test/unit/data/bug455906_start.xml")
blocklist.copyTo(gProfD, "blocklist.xml");
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8");
startupEM();
gTestserver = new nsHttpServer();
gTestserver.registerDirectory("/data/", do_get_file("toolkit/mozapps/extensions/test/unit/data"));
gTestserver.start(4444);
do_test_pending();
check_test_pt1();
}
// Before every main test this is the state the add-ons are meant to be in
function check_initial_state() {
do_check_eq(check_addon_state(ADDONS[0].id), "true,false");
do_check_eq(check_addon_state(ADDONS[1].id), "false,false");
do_check_eq(check_addon_state(ADDONS[2].id), "false,false");
do_check_eq(check_addon_state(ADDONS[3].id), "true,false");
do_check_eq(check_addon_state(ADDONS[4].id), "false,false");
do_check_eq(check_addon_state(ADDONS[5].id), "false,true");
do_check_eq(check_addon_state(ADDONS[6].id), "false,true");
do_check_eq(check_plugin_state(PLUGINS[0]), "true,false");
do_check_eq(check_plugin_state(PLUGINS[1]), "false,false");
do_check_eq(check_plugin_state(PLUGINS[2]), "false,false");
do_check_eq(check_plugin_state(PLUGINS[3]), "true,false");
do_check_eq(check_plugin_state(PLUGINS[4]), "false,false");
do_check_eq(check_plugin_state(PLUGINS[5]), "false,true");
}
// Tests the add-ons were installed and the initial blocklist applied as expected
function check_test_pt1() {
dump("Checking pt 1\n");
for (var i = 0; i < ADDONS.length; i++) {
if (!gEM.getItemForID(ADDONS[i].id))
do_throw("Addon " + (i + 1) + " did not get installed correctly");
}
do_check_eq(check_addon_state(ADDONS[0].id), "false,false");
do_check_eq(check_addon_state(ADDONS[1].id), "false,false");
do_check_eq(check_addon_state(ADDONS[2].id), "false,false");
// Warn add-ons should be user disabled automatically
do_check_eq(check_addon_state(ADDONS[3].id), "true,false");
do_check_eq(check_addon_state(ADDONS[4].id), "true,false");
// Blocked and incompatible should be app disabled only
do_check_eq(check_addon_state(ADDONS[5].id), "false,true");
do_check_eq(check_addon_state(ADDONS[6].id), "false,true");
// We've overridden the plugin host so we cannot tell what that would have
// initialised the plugins as
// Put the add-ons into the base state
gEM.disableItem(ADDONS[0].id);
gEM.enableItem(ADDONS[4].id);
restartEM();
check_initial_state();
gNotificationCheck = check_notification_pt2;
gTestCheck = check_test_pt2;
load_blocklist("bug455906_warn.xml");
}
function check_notification_pt2(args) {
dump("Checking notification pt 2\n");
do_check_eq(args.list.length, 4);
for (let i = 0; i < args.list.length; i++) {
let addon = args.list[i];
if (addon.item instanceof Ci.nsIUpdateItem) {
switch (addon.item.id) {
case "test_bug455906_2@tests.mozilla.org":
do_check_false(addon.blocked);
break;
case "test_bug455906_3@tests.mozilla.org":
do_check_false(addon.blocked);
addon.disable = true;
break;
default:
do_throw("Unknown addon: " + addon.item.id);
}
}
else if (addon.item instanceof Ci.nsIPluginTag) {
switch (addon.item.name) {
case "test_bug455906_2":
do_check_false(addon.blocked);
break;
case "test_bug455906_3":
do_check_false(addon.blocked);
addon.disable = true;
break;
default:
do_throw("Unknown addon: " + addon.item.name);
}
}
else {
do_throw("Unknown add-on type " + addon.item);
}
}
}
function check_test_pt2() {
restartEM();
dump("Checking results pt 2\n");
// Should have disabled this add-on as requested
do_check_eq(check_addon_state(ADDONS[2].id), "true,false");
do_check_eq(check_plugin_state(PLUGINS[2]), "true,false");
// The blocked add-on should have changed to user disabled
do_check_eq(check_addon_state(ADDONS[5].id), "true,false");
do_check_eq(check_plugin_state(PLUGINS[5]), "true,false");
// These should have been unchanged
do_check_eq(check_addon_state(ADDONS[0].id), "true,false");
do_check_eq(check_addon_state(ADDONS[1].id), "false,false");
do_check_eq(check_addon_state(ADDONS[3].id), "true,false");
do_check_eq(check_addon_state(ADDONS[4].id), "false,false");
do_check_eq(check_addon_state(ADDONS[6].id), "false,true");
do_check_eq(check_plugin_state(PLUGINS[0]), "true,false");
do_check_eq(check_plugin_state(PLUGINS[1]), "false,false");
do_check_eq(check_plugin_state(PLUGINS[3]), "true,false");
do_check_eq(check_plugin_state(PLUGINS[4]), "false,false");
// Back to starting state
gEM.enableItem(ADDONS[2].id);
gEM.enableItem(ADDONS[5].id);
PLUGINS[2].disabled = false;
PLUGINS[5].disabled = false;
restartEM();
gNotificationCheck = null;
gTestCheck = run_test_pt3;
load_blocklist("bug455906_start.xml");
}
function run_test_pt3() {
restartEM();
check_initial_state();
gNotificationCheck = check_notification_pt3;
gTestCheck = check_test_pt3;
load_blocklist("bug455906_block.xml");
}
function check_notification_pt3(args) {
dump("Checking notification pt 3\n");
do_check_eq(args.list.length, 6);
for (let i = 0; i < args.list.length; i++) {
let addon = args.list[i];
if (addon.item instanceof Ci.nsIUpdateItem) {
switch (addon.item.id) {
case "test_bug455906_2@tests.mozilla.org":
do_check_true(addon.blocked);
break;
case "test_bug455906_3@tests.mozilla.org":
do_check_true(addon.blocked);
break;
case "test_bug455906_5@tests.mozilla.org":
do_check_true(addon.blocked);
break;
default:
do_throw("Unknown addon: " + addon.item.id);
}
}
else if (addon.item instanceof Ci.nsIPluginTag) {
switch (addon.item.name) {
case "test_bug455906_2":
do_check_true(addon.blocked);
break;
case "test_bug455906_3":
do_check_true(addon.blocked);
break;
case "test_bug455906_5":
do_check_true(addon.blocked);
break;
default:
do_throw("Unknown addon: " + addon.item.name);
}
}
else {
do_throw("Unknown add-on type " + addon.item);
}
}
}
function check_test_pt3() {
restartEM();
dump("Checking results pt 3\n");
// All should have gained the blocklist state, user disabled as previously
do_check_eq(check_addon_state(ADDONS[0].id), "true,true");
do_check_eq(check_addon_state(ADDONS[1].id), "false,true");
do_check_eq(check_addon_state(ADDONS[2].id), "false,true");
do_check_eq(check_addon_state(ADDONS[3].id), "true,true");
do_check_eq(check_addon_state(ADDONS[4].id), "false,true");
do_check_eq(check_plugin_state(PLUGINS[0]), "true,true");
do_check_eq(check_plugin_state(PLUGINS[1]), "false,true");
do_check_eq(check_plugin_state(PLUGINS[2]), "false,true");
do_check_eq(check_plugin_state(PLUGINS[3]), "true,true");
do_check_eq(check_plugin_state(PLUGINS[4]), "false,true");
// Shouldn't be changed
do_check_eq(check_addon_state(ADDONS[5].id), "false,true");
do_check_eq(check_addon_state(ADDONS[6].id), "false,true");
do_check_eq(check_plugin_state(PLUGINS[5]), "false,true");
// Back to starting state
gNotificationCheck = null;
gTestCheck = run_test_pt4;
load_blocklist("bug455906_start.xml");
}
function run_test_pt4() {
gEM.enableItem(ADDONS[4].id);
PLUGINS[4].disabled = false;
restartEM();
check_initial_state();
gNotificationCheck = check_notification_pt4;
gTestCheck = check_test_pt4;
load_blocklist("bug455906_empty.xml");
}
function check_notification_pt4(args) {
dump("Checking notification pt 4\n");
// Should be just the dummy add-on to force this notification
do_check_eq(args.list.length, 1);
do_check_true(args.list[0].item instanceof Ci.nsIUpdateItem);
do_check_eq(args.list[0].item.id, "dummy_bug455906_2@tests.mozilla.org");
}
function check_test_pt4() {
restartEM();
dump("Checking results pt 4\n");
// This should have become unblocked
do_check_eq(check_addon_state(ADDONS[5].id), "false,false");
do_check_eq(check_plugin_state(PLUGINS[5]), "false,false");
// No change for anything else
do_check_eq(check_addon_state(ADDONS[0].id), "true,false");
do_check_eq(check_addon_state(ADDONS[1].id), "false,false");
do_check_eq(check_addon_state(ADDONS[2].id), "false,false");
do_check_eq(check_addon_state(ADDONS[3].id), "true,false");
do_check_eq(check_addon_state(ADDONS[4].id), "false,false");
do_check_eq(check_addon_state(ADDONS[6].id), "false,true");
do_check_eq(check_plugin_state(PLUGINS[0]), "true,false");
do_check_eq(check_plugin_state(PLUGINS[1]), "false,false");
do_check_eq(check_plugin_state(PLUGINS[2]), "false,false");
do_check_eq(check_plugin_state(PLUGINS[3]), "true,false");
do_check_eq(check_plugin_state(PLUGINS[4]), "false,false");
finish();
}
function finish() {
gTestserver.stop();
do_test_finished();
}

View File

@ -166,6 +166,7 @@ richlistitem[availableUpdateURL][updateable="true"] .updateAvailableBox,
richlistitem[compatible="false"] .notifyBadge,
richlistitem[providesUpdatesSecurely="false"] .notifyBadge,
richlistitem[blocklisted="true"] .notifyBadge,
richlistitem[blocklistedsoft="true"] .notifyBadge,
richlistitem[satisfiesDependencies="false"] .notifyBadge {
display: -moz-box;
}
@ -198,7 +199,10 @@ richlistitem[satisfiesDependencies="false"] .notifyBadge {
richlistitem[compatible="true"] .incompatibleBox,
richlistitem[providesUpdatesSecurely="true"] .insecureUpdateBox,
richlistitem[satisfiesDependencies="true"] .needsDependenciesBox,
richlistitem[blocklisted="false"] .blocklistedBox,
richlistitem:not([blocklisted="true"]):not([blocklistedsoft="true"]) .blocklistedBox,
richlistitem[blocklistedsoft="false"]:not([selected="true"]) .blocklistedBox,
richlistitem[blocklisted="false"] .blocklistedLabel,
richlistitem[blocklistedsoft="false"] .softBlocklistedLabel,
richlistitem[opType="needs-uninstall"] .blocklistedBox,
richlistitem[opType="needs-uninstall"] .incompatibleBox,
richlistitem[opType="needs-uninstall"] .needsDependenciesBox,

View File

@ -0,0 +1,16 @@
richlistitem {
padding-top: 6px;
padding-bottom: 6px;
-moz-padding-start: 7px;
-moz-padding-end: 7px;
border-bottom: 1px solid #C0C0C0;
}
.addon-name-version {
font-size: 110%;
}
.blockedLabel {
font-weight: bold;
font-style: italic;
}

View File

@ -164,6 +164,7 @@ richlistitem[availableUpdateURL][updateable="true"] .updateAvailableBox,
richlistitem[compatible="false"] .notifyBadge,
richlistitem[providesUpdatesSecurely="false"] .notifyBadge,
richlistitem[blocklisted="true"] .notifyBadge,
richlistitem[blocklistedsoft="true"] .notifyBadge,
richlistitem[satisfiesDependencies="false"] .notifyBadge {
display: -moz-box;
}
@ -197,7 +198,10 @@ richlistitem[satisfiesDependencies="false"] .notifyBadge {
richlistitem[compatible="true"] .incompatibleBox,
richlistitem[providesUpdatesSecurely="true"] .insecureUpdateBox,
richlistitem[satisfiesDependencies="true"] .needsDependenciesBox,
richlistitem[blocklisted="false"] .blocklistedBox,
richlistitem:not([blocklisted="true"]):not([blocklistedsoft="true"]) .blocklistedBox,
richlistitem[blocklistedsoft="false"]:not([selected="true"]) .blocklistedBox,
richlistitem[blocklisted="false"] .blocklistedLabel,
richlistitem[blocklistedsoft="false"] .softBlocklistedLabel,
richlistitem[opType="needs-uninstall"] .blocklistedBox,
richlistitem[opType="needs-uninstall"] .incompatibleBox,
richlistitem[opType="needs-uninstall"] .needsDependenciesBox,
@ -205,8 +209,6 @@ richlistitem[opType="needs-uninstall"] .blocklistedBox {
display: none;
}
richlistitem[loading="true"] .updateBadge {
display: -moz-box;
width: 16px;

View File

@ -18,6 +18,7 @@ classic.jar:
skin/classic/mozapps/extensions/extensions.xml (extensions/extensions.xml)
skin/classic/mozapps/extensions/update.css (extensions/update.css)
skin/classic/mozapps/extensions/eula.css (extensions/eula.css)
skin/classic/mozapps/extensions/blocklist.css (extensions/blocklist.css)
skin/classic/mozapps/passwordmgr/key.png (passwordmgr/key.png)
skin/classic/mozapps/plugins/missingPlugin.css (plugins/missingPlugin.css)
skin/classic/mozapps/plugins/pluginGeneric.png (plugins/pluginGeneric.png)

View File

@ -0,0 +1,16 @@
richlistitem {
padding-top: 6px;
padding-bottom: 6px;
-moz-padding-start: 7px;
-moz-padding-end: 7px;
border-bottom: 1px solid #C0C0C0;
}
.addonName {
font-weight: bold;
}
.blockedLabel {
font-weight: bold;
font-style: italic;
}

View File

@ -157,6 +157,7 @@ richlistitem[availableUpdateURL][updateable="true"] .updateAvailableBox,
richlistitem[compatible="false"] .notifyBadge,
richlistitem[providesUpdatesSecurely="false"] .notifyBadge,
richlistitem[blocklisted="true"] .notifyBadge,
richlistitem[blocklistedsoft="true"] .notifyBadge,
richlistitem[satisfiesDependencies="false"] .notifyBadge {
display: -moz-box;
}
@ -189,7 +190,10 @@ richlistitem[satisfiesDependencies="false"] .notifyBadge {
richlistitem[compatible="true"] .incompatibleBox,
richlistitem[providesUpdatesSecurely="true"] .insecureUpdateBox,
richlistitem[satisfiesDependencies="true"] .needsDependenciesBox,
richlistitem[blocklisted="false"] .blocklistedBox,
richlistitem:not([blocklisted="true"]):not([blocklistedsoft="true"]) .blocklistedBox,
richlistitem[blocklistedsoft="false"]:not([selected="true"]) .blocklistedBox,
richlistitem[blocklisted="false"] .blocklistedLabel,
richlistitem[blocklistedsoft="false"] .softBlocklistedLabel,
richlistitem[opType="needs-uninstall"] .blocklistedBox,
richlistitem[opType="needs-uninstall"] .incompatibleBox,
richlistitem[opType="needs-uninstall"] .needsDependenciesBox,

View File

@ -8,6 +8,7 @@ classic.jar:
skin/classic/mozapps/downloads/downloads.css (downloads/downloads.css)
skin/classic/mozapps/downloads/unknownContentType.css (downloads/unknownContentType.css)
skin/classic/mozapps/extensions/about.css (extensions/about.css)
skin/classic/mozapps/extensions/blocklist.css (extensions/blocklist.css)
skin/classic/mozapps/extensions/extensions.css (extensions/extensions.css)
skin/classic/mozapps/extensions/itemDisabledFader.png (extensions/itemDisabledFader.png)
skin/classic/mozapps/extensions/itemEnabledFader.png (extensions/itemEnabledFader.png)

View File

@ -49,6 +49,7 @@ XPIDLSRCS = \
nsIXULAppInfo.idl \
nsIGConfService.idl \
nsIGnomeVFSService.idl \
nsIBlocklistService.idl \
$(NULL)
ifdef MOZ_CRASHREPORTER

View File

@ -39,13 +39,23 @@
#include "nsISupports.idl"
[scriptable, uuid(0c3fe697-d50d-4f42-b747-0c5855cfc60e)]
interface nsIPluginTag;
[scriptable, uuid(8439f9c0-da03-4260-8b21-dc635eed28fb)]
interface nsIBlocklistService : nsISupports
{
// Indicates that the item does not appear in the blocklist.
const unsigned long STATE_NOT_BLOCKED = 0;
// Indicates that the item is in the blocklist but the problem is not severe
// enough to warant forcibly blocking.
const unsigned long STATE_SOFTBLOCKED = 1;
// Indicates that the item should be blocked and never used.
const unsigned long STATE_BLOCKED = 2;
/**
* Determine if an item is blocklisted
* @param id
* The GUID of the item.
* The ID of the item.
* @param version
* The item's version.
* @param appVersion
@ -60,5 +70,44 @@ interface nsIBlocklistService : nsISupports
* application or this version of the toolkit, false, otherwise.
*/
boolean isAddonBlocklisted(in AString id, in AString version,
in AString appVersion, in AString toolkitVersion);
[optional] in AString appVersion,
[optional] in AString toolkitVersion);
/**
* Determine the blocklist state of an add-on
* @param id
* The ID of the item.
* @param version
* The item's version.
* @param appVersion
* The version of the application we are checking in the blocklist.
* If this parameter is null, the version of the running application
* is used.
* @param toolkitVersion
* The version of the toolkit we are checking in the blocklist.
* If this parameter is null, the version of the running toolkit
* is used.
* @returns The STATE constant.
*/
unsigned long getAddonBlocklistState(in AString id, in AString version,
[optional] in AString appVersion,
[optional] in AString toolkitVersion);
/**
* Determine the blocklist state of a plugin
* @param plugin
* The plugin to get the state for
* @param appVersion
* The version of the application we are checking in the blocklist.
* If this parameter is null, the version of the running application
* is used.
* @param toolkitVersion
* The version of the toolkit we are checking in the blocklist.
* If this parameter is null, the version of the running toolkit
* is used.
* @returns The STATE constant.
*/
unsigned long getPluginBlocklistState(in nsIPluginTag plugin,
[optional] in AString appVersion,
[optional] in AString toolkitVersion);
};