Rewrite the extension manager as a js component (170006 - not accessible yet)

This commit is contained in:
ben%bengoodger.com 2004-03-31 08:58:21 +00:00
parent 2607b954dc
commit f4f167dc73
20 changed files with 933 additions and 41 deletions

View File

@ -51,7 +51,6 @@ else
DIRS = \
autocomplete \
console \
extensions \
filepicker \
help \
history \

View File

@ -45,7 +45,6 @@ REQUIRES = \
docshell \
autocomplete \
downloads \
extensions \
mimetype \
webbrowserpersist \
progressDlg \
@ -68,7 +67,6 @@ CPPSRCS = nsModule.cpp
LOCAL_INCLUDES = \
-I$(srcdir)/../autocomplete/src \
-I$(srcdir)/../downloads/src \
-I$(srcdir)/../extensions/src \
-I$(srcdir)/../history/src \
-I$(srcdir)/../satchel/src \
-I$(srcdir)/../passwordmgr/base \
@ -81,7 +79,6 @@ endif
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/$(LIB_PREFIX)autocomplete_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)download_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)extensions_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)history_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)satchel_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)passwordmgr_s.$(LIB_SUFFIX) \

View File

@ -46,7 +46,6 @@
#include "nsAutoCompleteMdbResult.h"
#include "nsDownloadManager.h"
#include "nsDownloadProxy.h"
#include "nsExtensionManager.h"
#include "nsFormHistory.h"
#include "nsFormFillController.h"
#include "nsGlobalHistory.h"
@ -62,7 +61,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteController)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteMdbResult)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDownloadManager, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsExtensionManager, Init)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsFormHistory, nsFormHistory::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormFillController)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGlobalHistory, Init)
@ -108,13 +106,6 @@ static const nsModuleComponentInfo components[] =
NS_DOWNLOAD_CONTRACTID,
nsDownloadProxyConstructor },
{ "Extension Manager",
NS_EXTENSIONMANAGER_CID,
NS_EXTENSIONMANAGER_CONTRACTID,
nsExtensionManagerConstructor,
nsExtensionManager::Register,
nsnull },
{ "HTML Form History",
NS_FORMHISTORY_CID,
NS_FORMHISTORY_CONTRACTID,

View File

@ -50,9 +50,6 @@
#define NS_DOWNLOADMANAGER_CONTRACTID \
"@mozilla.org/download-manager;1"
#define NS_EXTENSIONMANAGER_CONTRACTID \
"@mozilla.org/extension-manager;1"
#define NS_FORMHISTORY_CONTRACTID \
"@mozilla.org/satchel/form-history;1"
@ -85,10 +82,6 @@
#define NS_DOWNLOADMANAGER_CID \
{ 0xedb0490e, 0x1dd1, 0x11b2, { 0x83, 0xb8, 0xdb, 0xf8, 0xd8, 0x59, 0x06, 0xa6 } }
// {8A115FAA-7DCB-4e8f-979B-5F53472F51CF}
#define NS_EXTENSIONMANAGER_CID \
{ 0x8a115faa, 0x7dcb, 0x4e8f, { 0x97, 0x9b, 0x5f, 0x53, 0x47, 0x2f, 0x51, 0xcf } }
// {895DB6C7-DBDF-40ea-9F64-B175033243DC}
#define NS_FORMFILLCONTROLLER_CID \
{ 0x895db6c7, 0xdbdf, 0x40ea, { 0x9f, 0x64, 0xb1, 0x75, 0x3, 0x32, 0x43, 0xdc } }

View File

@ -48,11 +48,11 @@ interface nsIExtensionManager : nsISupports
void uninstallExtension(in string aExtensionID);
void enableExtension(in string aExtensionID);
void disableExtension(in string aExtensionID);
void updateExtension(in string aExtensionID);
void installTheme(in string aThemeID);
void uninstallTheme(in string aThemeID);
void enableTheme(in string aThemeID);
void disableTheme(in string aThemeID);
void updateTheme(in string aThemeID);
readonly attribute nsIRDFDataSource datasource;
};

View File

@ -103,6 +103,20 @@ nsExtensionManager::DisableExtension(const char* aExtensionID)
return mDataSource->DisableExtension(aExtensionID);
}
NS_IMETHODIMP
nsExtensionManager::UpdateExtension(const char* aExtensionID)
{
nsXPIDLString updateURL;
mDataSource->GetUpdateURL(getter_Copies(updateURL));
if (str) {
}
return NS_OK;
}
NS_IMETHODIMP
nsExtensionManager::InstallTheme(const char* aThemeID)
{
@ -127,6 +141,12 @@ nsExtensionManager::DisableTheme(const char* aThemeID)
return NS_OK;
}
NS_IMETHODIMP
nsExtensionManager::UpdateTheme(const char* aThemeID)
{
return NS_OK;
}
NS_METHOD
nsExtensionManager::Register(nsIComponentManager* aCompMgr,
nsIFile* aPath,

View File

@ -43,14 +43,12 @@
#include "nsIIOService.h"
#include "nsILocalFile.h"
#include "nsIProtocolHandler.h"
#include "nsIRDFContainer.h"
#include "nsIRDFRemoteDataSource.h"
#include "nsIRDFService.h"
#include "nsLiteralString.h"
#include "rdf.h"
///////////////////////////////////////////////////////////////////////////////
// nsIRDFDataSource
NS_IMPL_ISUPPORTS2(nsExtensionManagerDataSource, nsIRDFDataSource, nsIRDFRemoteDataSource)
static nsIRDFService* gRDFService = nsnull;
@ -82,9 +80,17 @@ static nsIRDFLiteral* gTrueValue = nsnull;
static nsIRDFLiteral* gFalseValue = nsnull;
static nsIRDFLiteral* gInstallProfile = nsnull;
static nsIRDFLiteral* gInstallGlobal = nsnull;
static nsIRDFResource* gExtensionsRoot = nsnull;
static nsIRDFResource* gThemesRoot = nsnull;
#define EM_RDF_URI "http://www.mozilla.org/2004/em-rdf#"
#define PREF_EM_DEFAULTUPDATEURL "update.url.extensions"
#define PREF_EM_APP_ID "app.id"
///////////////////////////////////////////////////////////////////////////////
// nsIRDFDataSource
nsExtensionManagerDataSource::nsExtensionManagerDataSource()
{
if (!gRDFService)
@ -103,6 +109,9 @@ nsExtensionManagerDataSource::nsExtensionManagerDataSource()
gRDFService->GetLiteral(NS_LITERAL_STRING("global").get(), &gInstallGlobal);
gRDFService->GetLiteral(NS_LITERAL_STRING("true").get(), &gTrueValue);
gRDFService->GetLiteral(NS_LITERAL_STRING("false").get(), &gFalseValue);
gRDFService->GetResource(NS_LITERAL_CSTRING("urn:mozilla:extension:root"), &gExtensionsRoot);
gRDFService->GetResource(NS_LITERAL_CSTRING("urn:mozilla:themes:root"), &gThemesRoot);
}
nsExtensionManagerDataSource::~nsExtensionManagerDataSource()
@ -135,6 +144,8 @@ nsExtensionManagerDataSource::~nsExtensionManagerDataSource()
NS_IF_RELEASE(gFalseValue);
NS_IF_RELEASE(gInstallProfile);
NS_IF_RELEASE(gInstallGlobal);
NS_IF_RELEASE(gExtensionsRoot);
NS_IF_RELEASE(gThemesRoot);
}
///////////////////////////////////////////////////////////////////////////////
@ -330,9 +341,115 @@ nsExtensionManagerDataSource::DisableExtension(const char* aExtensionID)
nsresult
nsExtensionManagerDataSource::UninstallExtension(const char* aExtensionID)
{
nsCOMPtr<nsIRDFContainer> ctr(do_CreateInstance("@mozilla.org/rdf/container;1"));
ctr->Init(this, gExtensionsRoot);
nsCString resourceURI = NS_LITERAL_CSTRING("urn:mozilla:extension:");
resourceURI += aExtensionID;
nsCOMPtr<nsIRDFResource> extension;
gRDFService->GetResource(resourceURI, getter_AddRefs(extension));
ctr->RemoveElement(extension, PR_TRUE);
return SetExtensionProperty(aExtensionID, gToBeUninstalledArc, gTrueValue);
}
// This returns an array of URIs in the form:
// http://www.foo.com/software/ext1/update.cgi
// http://www.bar.com/update.php?ext=%7B0e4007ea-0b6b-4487-8e1b-479f65599e74%7D
// http://update.mozilla.org/genericUpdate.php?ext=%7B0e4007ea-0b6b-4487-8e1b-479f65599e74%7D%2C%7B0e4007ea-0b6b-4487-8e1b-479f65599e74%7D&app=%7Bec8030f7-c20a-464f-9b0e-13a3a9e97384%7D
// (specific URLs first, followed by a generic
nsresult
nsExtensionManagerDataSource::GetConsolidatedUpdateURLs(nsISupportsArray* aURIs)
{
nsCOMPtr<nsIRDFContainer> ctr(do_CreateInstance("@mozilla.org/rdf/container;1"));
ctr->Init(this, gExtensionsRoot);
nsCOMPtr<nsISimpleEnumerator> e;
ctr->GetElements(getter_AddRefs(e));
do {
e->HasMoreElements(&hasMore);
if (!hasMore)
break;
nsCOMPtr<nsIRDFResource> res;
e->GetNext(getter_AddRefs(res));
nsCAutoString url;
GetUpdateURLForExtensionInternal(res, url);
// If there's no specific Update URL specified for this extension, we want to
// add this extension to the list that we'll pass to the generic update server.
if (url.IsEmpty()) {
}
}
while (PR_TRUE);
}
nsresult
nsExtensionManagerDataSource::GetUpdateURLForExtension(const char* aExtensionID, PRUnichar* aResult)
{
nsCString resourceURI = NS_LITERAL_CSTRING("urn:mozilla:extension:");
resourceURI += aExtensionID;
nsCOMPtr<nsIRDFResource> extension;
gRDFService->GetResource(resourceURI, getter_AddRefs(extension));
nsCAutoString url;
GetUpdateURLForExtensionInternal(extension, url);
}
void
nsExtensionManagerDataSource::GetUpdateURLForExtensionInternal(nsIRDFResource* aResource, nsACString& aResult)
{
PRBool hasUpdateURLArc;
mDataSource->HasArcOut(extension, gUpdateURLArc, &hasUpdateURLArc);
if (hasUpdateURLArc) {
nsCOMPtr<nsIRDFNode> updateURL;
mDataSource->GetTarget(extension, gUpdateURLArc, PR_TRUE, getter_AddRefs(updateURL));
nsCOMPtr<nsIRDFResource> updateURLResource(do_QueryInterface(updateURL));
if (updateURLResource) {
nsXPIDLCString value;
updateURLResource->GetValueConst(getter_Shares(value));
nsXPIDLCString app;
nsCOMPtr<nsIPrefBranch> prefSvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
prefSvc->GetCharPref(PREF_EM_APP_ID, getter_Copies(app));
nsXPIDLCString id;
extension->GetValue(getter_Copies(id));
const nsACString& extensionPrefix = NS_LITERAL_CSTRING("urn:mozilla:extension:");
PRInt32 prefixLength = extensionPrefix.Length();
id.Cut(prefixLength, id.Length() - prefixLength);
ReplaceAll(value, NS_LITERAL_CSTRING("%APP%"), app);
ReplaceAll(value, NS_LITERAL_CSTRING("%ITEM%"), id);
aResult = value;
}
}
}
void
nsExtensionManagerDataSource::ReplaceAll(nsACString& aString, const nsACString& aKey, const nsACString& aReplace)
{
nsACString::const_iterator startString, startSubstring, end;
aString.BeginReading(startString);
aString.BeginReading(startSubstring);
aString.EndReading(end);
while (FindInReadable(aKey, startSubstring, end))
aString.Replace(Distance(startString, startSubstring), aKey.Length(), aReplace);
}
///////////////////////////////////////////////////////////////////////////////
// nsIRDFDataSource

View File

@ -66,6 +66,12 @@ public:
nsresult LoadExtensions(PRBool aProfile);
nsresult GetUpdateURL(PRUnichar** aResult);
void GetUpdateURLForExtensionInternal(nsIRDFResource* aResource,
nsACString& aResult);
void ReplaceAll(nsACString& aString, const nsACString& aKey,
const nsACString& aReplace);
protected:
nsresult SetExtensionProperty(const char* aExtensionID,
nsIRDFResource* aPropertyArc,

View File

@ -42,7 +42,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = downloads xpinstall
DIRS = downloads extensions xpinstall
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
# XXXben this is temporary, until Thunderbird is converted to Pinstripe on MacOS X. For now,

View File

@ -44,7 +44,10 @@ function flushDataSource()
// Event Handlers
function onExtensionSelect(aEvent)
{
if (aEvent.target.selected)
aEvent.target.setAttribute("last-selected", aEvent.target.selected.id);
else
aEvent.target.removeAttribute("last-selected");
}
///////////////////////////////////////////////////////////////////////////////
@ -270,7 +273,6 @@ var gExtensionsViewController = {
commands: {
cmd_close: function ()
{
dump("*** close \n");
closeWindow(true);
},
@ -363,24 +365,61 @@ var gExtensionsViewController = {
cmd_update: function ()
{
var updateURL = gExtensionsView.selected.getAttribute("updateURL");
if (updateURL) {
}
else {
"smartupdate.update.extensions"
}
if (gWindowState == "extensions")
gExtensionManager.updateExtension(gExtensionsView.selected ? stripPrefix(gExtensionsView.selected.id) : null);
else if (gWindowState == "themes")
gExtensionManager.updateTheme(gExtensionsView.selected ? stripPrefix(gExtensionsView.selected.id) : null);
},
cmd_uninstall: function ()
{
// Confirm the uninstall
var extensionsStrings = document.getElementById("extensionsStrings");
var brandStrings = document.getElementById("brandStrings");
var name = gExtensionsView.selected.getAttribute("name");
var title = extensionsStrings.getFormattedString("queryUninstallTitle", [name]);
if (gWindowState == "extensions")
message = extensionsStrings.getFormattedString("queryUninstallExtensionMessage", [name, name]);
else if (gWindowState == "themes")
message = extensionsStrings.getFormattedString("queryUninstallThemeMessage", [name]);
// XXXben - improve the wording on the buttons here!
var promptSvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
if (!promptSvc.confirm(window, title, message))
return;
var selectedID = gExtensionsView.selected.id;
var selectedElement = document.getElementById(selectedID);
var nextElement = selectedElement.nextSibling;
if (!nextElement)
nextElement = selectedElement.previousSibling;
nextElement = nextElement.id;
if (gWindowState == "extensions")
gExtensionManager.uninstallExtension(stripPrefix(selectedID));
else if (gWindowState == "themes")
gExtensionManager.uninstallTheme(stripPrefix(selectedID));
gExtensionsView.selected = document.getElementById(nextElement);
#if ANNOYING_ASS_ALERTS
// Show an alert message telling the user they need to restart for the
// action to take effect.
message = extensionsStrings.getFormattedString("restartBeforeUninstallMessage",
[gExtensionsView.selected.getAttribute("name"),
brandStrings.getString("brandShortName")]);
promptSvc.alert(window, extensionsStrings.getString("restartBeforeUninstallTitle"), message);
#endif
},
cmd_disable: function ()
{
gExtensionManager.disableExtension(stripPrefix(gExtensionsView.selected.id));
#if ANNOYING_ASS_ALERTS
// Show an alert message telling the user they need to restart for the
// action to take effect.
var extensionsStrings = document.getElementById("extensionsStrings");
@ -393,12 +432,14 @@ var gExtensionsViewController = {
var promptSvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
promptSvc.alert(window, extensionsStrings.getString("restartBeforeDisableTitle"), message);
#endif
},
cmd_enable: function ()
{
gExtensionManager.enableExtension(stripPrefix(gExtensionsView.selected.id));
#if ANNOYING_ASS_ALERTS
// Show an alert message telling the user they need to restart for the
// action to take effect.
var extensionsStrings = document.getElementById("extensionsStrings");
@ -411,6 +452,7 @@ var gExtensionsViewController = {
var promptSvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
promptSvc.alert(window, extensionsStrings.getString("restartBeforeEnableTitle"), message);
#endif
},
}
};

View File

@ -186,7 +186,7 @@
<separator id="commandBarSeparator"/>
<button id="updateButton"
label="&cmd.update.label;" accesskey="&cmd.update.accesskey;" tooltiptext="&cmd.update.tooltip;"
oncommand="onSoftwareUpdateCheck();"/>
command="cmd_update"/>
</hbox>
<resizer id="windowResizer" dir="bottomright"/>

View File

@ -6,4 +6,8 @@ restartBeforeEnableTitle=Enable Extension
restartBeforeDisableTitle=Disable Extension
restartBeforeEnableMessage=%S will be enabled the next time you restart %S.
restartBeforeDisableMessage=%S will be disabled the next time you restart %S.
restartBeforeUninstallTitle=Uninstall
restartBeforeUninstallMessage=%S will be uninstalled the next time you restart %S.
queryUninstallExtensionMessage=If you uninstall %S, the functionality it offers will no longer be available. Do you want to uninstall %S?
queryUninstallThemeMessage=Do you want to uninstall %S?
queryUninstallTitle=Uninstall %S

View File

@ -0,0 +1,50 @@
# ***** 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 Manager.
#
# The Initial Developer of the Original Code is Ben Goodger.
# Portions created by the Initial Developer are Copyright (C) 2004
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <ben@mozilla.org>
#
# 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = extensions
XPIDL_MODULE = extensions
XPIDLSRCS = nsIExtensionManager.idl
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,59 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 Manager.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.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 ***** */
#include "nsISupports.idl"
interface nsIInputStream;
interface nsIRDFDataSource;
[scriptable, uuid(c3515b0f-99f4-453b-805e-1fdf5724d6d9)]
interface nsIExtensionManager : nsISupports
{
void installExtensionFromStream(in nsIInputStream aStream, in boolean aUseProfile);
void uninstallExtension(in string aExtensionID);
void enableExtension(in string aExtensionID);
void disableExtension(in string aExtensionID);
void updateExtension(in string aExtensionID);
void installTheme(in string aThemeID);
void uninstallTheme(in string aThemeID);
void updateTheme(in string aThemeID);
readonly attribute nsIRDFDataSource datasource;
};

View File

@ -2,6 +2,10 @@
background-color: ThreeDFace;
}
#extensionsView {
background-image: url("chrome://mozapps/skin/extensions/viewWatermark.png");
}
/* Extension Manager Command Bar */
#commandBar {
padding: 0px 10px 5px 10px;
@ -10,13 +14,13 @@
#uninstallButton {
margin: 0px;
-moz-user-focus: ignore;
list-style-image: url("chrome://mozapps/skin/extensions/extensionUninstall.png");
list-style-image: url("chrome://mozapps/skin/extensions/placeholder.gif");
}
#updateButton {
margin: 0px;
-moz-user-focus: ignore;
list-style-image: url("chrome://mozapps/skin/extensions/extensionUpdate.png");
list-style-image: url("chrome://mozapps/skin/extensions/placeholder.gif");
}
#uninstallButton .button-icon, #updateButton .button-icon {
@ -24,7 +28,7 @@
}
#uninstallButton[disabled="true"] {
list-style-image: url("chrome://mozapps/skin/downloads/downloadCleanupDisabled.png");
list-style-image: url("chrome://mozapps/skin/extensions/placeholder.gif");
}
#commandBarSeparator {

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,37 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = extensions
EXTRA_COMPONENTS = nsExtensionManager.js
include $(topsrcdir)/config/rules.mk
nsExtensionManager.js: nsExtensionManager.js.in
$(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $^ > $@

View File

@ -0,0 +1,571 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 Manager.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.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 gExtensionManager = null;
function nsExtensionManager()
{
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "profile-after-change", false);
dump("*** global extensions startup!\n");
}
nsExtensionManager.prototype = {
// nsIObserver
observe: function (aSubject, aTopic, aData)
{
if (aTopic == "profile-after-change") {
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.removeObserver(this, "profile-after-change");
dump("*** profile extensions startup\n");
}
},
// nsIExtensionManager
installExtensionFromStream: function (aStream, aUseProfile)
{
var parser = Components.classes["@mozilla.org/rdf/xml-parser;1"]
.createInstance(Components.interfaces.nsIRDFXMLParser);
var ds = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
.createInstance(Components.interfaces.nsIRDFDataSource);
var streamListener = parser.parseAsync(ds, null);
var bytesAvailable;
do {
bytesAvailable = aStream.available();
if (!bytesAvailable)
break;
streamListener.onDataAvailable(null, null, aStream, 0, bytesAvailable);
}
while (1);
this._ensureDS();
this._ds.installExtension(ds, aUseProfile);
},
uninstallExtension: function (aExtensionID)
{
this._ds.uninstallExtension(aExtensionID);
},
enableExtension: function (aExtensionID)
{
this._ds.enableExtension(aExtensionID);
},
disableExtension: function (aExtensionID)
{
this._ds.disableExtension(aExtensionID);
},
updateExtension: function (aExtensionID)
{
this._ds.getUpdateURLs(aExtensionID);
},
// Themes
installTheme: function (aThemeID)
{
},
uninstallTheme: function (aThemeID)
{
},
updateTheme: function (aThemeID)
{
},
get datasource()
{
this._ensureDS();
return this._ds;
},
//
_ds: null,
// Other
_ensureDS: function ()
{
if (!this._ds) {
this._ds = new nsExtensionsDataSource();
if (this._ds) {
this._ds.loadExtensions(false);
this._ds.loadExtensions(true);
}
}
},
/////////////////////////////////////////////////////////////////////////////
// nsISupports
QueryInterface: function (aIID)
{
if (!aIID.equals(Components.interfaces.nsIExtensionManager) &&
!aIID.equals(Components.interfaces.nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
}
};
const PREF_EM_DEFAULTUPDATEURL = "update.url.extensions";
const PREF_EM_APP_ID = "app.id";
function EM_NS(aProperty)
{
return "http://www.mozilla.org/2004/em-rdf#" + aProperty;
}
function nsExtensionsDataSource()
{
this._rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
}
nsExtensionsDataSource.prototype = {
_rdf: null,
_emR: function (aProperty)
{
return this._rdf.GetResource(EM_NS(aProperty));
},
_emL: function (aLiteral)
{
return this._rdf.GetLiteral(aLiteral);
},
_setProperty: function (aDS, aSource, aProperty, aNewValue)
{
var oldValue = aDS.GetTarget(aSource, aProperty, true);
if (oldValue)
aDS.Change(aSource, aProperty, oldValue, aNewValue);
else
aDS.Assert(aSource, aProperty, aNewValue, true);
},
_setExtensionProperty: function (aExtensionID, aPropertyArc, aPropertyValue)
{
var extension = this._rdf.GetResource("urn:mozilla:extension:" + aExtensionID);
var installLocation = this.GetTarget(extension, this._emR("installLocation"), true);
var isProfile = installLocation.EqualsNode(this._emR("profile"));
var ds = isProfile ? this._profileExtensions : this._appExtensions;
this._setProperty(ds, extension, aPropertyArc, aPropertyValue);
this._flush(isProfile);
},
enableExtension: function (aExtensionID)
{
this._setExtensionProperty(aExtensionID, this._emR("toBeEnabled"), this._emL("true"));
this._setExtensionProperty(aExtensionID, this._emR("toBeDisabled"), this._emL("false"));
this._setExtensionProperty(aExtensionID, this._emR("disabled"), this._emL("false"));
},
disableExtension: function (aExtensionID)
{
this._setExtensionProperty(aExtensionID, this._emR("toBeDisabled"), this._emL("true"));
this._setExtensionProperty(aExtensionID, this._emR("toBeEnabled"), this._emL("false"));
this._setExtensionProperty(aExtensionID, this._emR("disabled"), this._emL("true"));
},
uninstallExtension: function (aExtensionID)
{
var ctr = Components.classes["@mozilla.org/rdf/container;1"]
.createInstance(Components.interfaces.nsIRDFContainer);
ctr.Init(this, this._rdf.GetResource("urn:mozilla:extension:root"));
var extension = this._rdf.GetResource("urn:mozilla:extension:" + aExtensionID);
ctr.RemoveElement(extension, true);
this._setExtensionProperty(aExtensionID, this._emR("toBeUninstalled"), this._emL("true"));
},
getUpdateURLs: function (aExtensionID)
{
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var appID = pref.getCharPref(PREF_EM_APP_ID);
var urls = [];
if (aExtensionID) {
var updateURL = this._getUpdateURLInternal(aExtensionID);
updateURL = updateURL.replace(/%APP%/g, escape(appID));
updateURL = updateURL.replace(/%ITEM%/g, escape(aExtensionID));
urls.push(updateURL);
}
else {
var ctr = Components.classes["@mozilla.org/rdf/container;1"]
.createInstance(Components.interfaces.nsIRDFContainer);
ctr.Init(this, this._rdf.GetResource("urn:mozilla:extension:root"));
var urlHash = { };
var e = ctr.GetElements();
while (e.hasMoreElements()) {
var r = e.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
var extensionID = r.Value.substr("urn:mozilla:extension:".length, r.Value.length);
var updateURL = this._getUpdateURLInternal(extensionID);
if (!(updateURL in urlHash))
urlHash[updateURL] = [];
urlHash[updateURL].push(extensionID);
}
for (var url in urlHash) {
var guidString = "";
var urlCount = urlHash[url].length;
for (var i = 0; i < urlCount; ++i)
guidString += escape(urlHash[url][i] + (i < urlCount - 1 ? "," : ""));
dump("*** guidString = " + guidString + "\n");
url = url.replace(/%APP%/g, appID);
url = url.replace(/%ITEM%/g, guidString);
urls.push(url);
}
}
dump("*** urls = " + urls + "\n");
return urls;
},
_getUpdateURLInternal: function (aExtensionID)
{
var updateURL;
var extension = this._rdf.GetResource("urn:mozilla:extension:" + aExtensionID);
if (this.hasArcOut(extension, this._emR("updateURL"))) {
updateURL = this.GetTarget(extension, this._emR("updateURL"), true);
if (updateURL)
updateURL = updateURL.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
}
if (!updateURL) {
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
updateURL = pref.getCharPref(PREF_EM_DEFAULTUPDATEURL);
}
return updateURL;
},
loadExtensions: function (aProfile)
{
var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var key = aProfile ? "ProfD" : "ProfD"; // XCurProcDir
var extensionsFile = fileLocator.get(key, Components.interfaces.nsIFile);
extensionsFile.append("Extensions");
extensionsFile.append("extensions.rdf");
if (!extensionsFile.exists())
return;
var ioServ = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var fph = ioServ.getProtocolHandler("file").QueryInterface(Components.interfaces.nsIFileProtocolHandler);
var dsURL = fph.getURLSpecFromFile(extensionsFile);
var ds = this._rdf.GetDataSourceBlocking(dsURL);
if (aProfile) {
this._profileExtensions = ds;
if (!this._composite)
this._composite = Components.classes["@mozilla.org/rdf/datasource;1?name=composite-datasource"]
.createInstance(Components.interfaces.nsIRDFDataSource);
if (this._appExtensions)
this._composite.RemoveDataSource(this._appExtensions);
this._composite.AddDataSource(this._profileExtensions);
if (this._appExtensions)
this._composite.AddDataSource(this._appExtensions);
}
else {
this._appExtensions = ds;
if (!this._composite)
this._composite = Components.classes["@mozilla.org/rdf/datasource;1?name=composite-datasource"]
.createInstance(Components.interfaces.nsIRDFCompositeDataSource);
this._composite.AddDataSource(this._appExtensions);
}
},
/////////////////////////////////////////////////////////////////////////////
// nsIRDFDataSource
_appExtensions: null,
_profileExtensions: null,
_composite: null,
get URI()
{
return "rdf:extensions";
},
GetSource: function (aProperty, aTarget, aTruthValue)
{
return this._composite.GetSource(aProperty, aTarget, aTruthValue);
},
GetSources: function (aProperty, aTarget, aTruthValue)
{
return this._composite.GetSources(aProperty, aTarget, aTruthValue);
},
GetTarget: function (aSource, aProperty, aTruthValue)
{
if (aProperty.EqualsNode(this._emR("iconURL"))) {
var hasIconURL = this._composite.hasArcOut(aSource, aProperty);
// If the download entry doesn't have a IconURL property, use a
// generic icon URL instead.
if (!hasIconURL)
return this._rdf.GetResource("chrome://mozapps/skin/xpinstall/xpinstallItemGeneric.png");
}
else if (aProperty.EqualsNode(this._emR("installLocation"))) {
var hasNameArc = this._profileExtensions.hasArcOut(aSource, this._emR("name"));
var hasVersionArc = this._profileExtensions.hasArcOut(aSource, this._emR("version"));
return hasNameArc && hasVersionArc ? this._emL("profile") : this._emL("global");
}
return this._composite.GetTarget(aSource, aProperty, aTruthValue);
},
GetTargets: function (aSource, aProperty, aTruthValue)
{
return this._composite.GetTargets(aSource, aProperty, aTruthValue);
},
Assert: function (aSource, aProperty, aTarget, aTruthValue)
{
return Components.results.NS_RDF_ASSERTION_REJECTED;
},
Unassert: function (aSource, aProperty, aTarget)
{
return Components.results.NS_RDF_ASSERTION_REJECTED;
},
Change: function (aSource, aProperty, aOldTarget, aNewTarget)
{
return Components.results.NS_RDF_ASSERTION_REJECTED;
},
Move: function (aSource, aNewSource, aProperty, aTarget)
{
return Components.results.NS_RDF_ASSERTION_REJECTED;
},
HasAssertion: function (aSource, aProperty, aTarget, aTruthValue)
{
return this._composite.HasAssertion(aSource, aProperty, aTarget, aTruthValue);
},
AddObserver: function (aObserver)
{
this._composite.AddObserver(aObserver);
},
RemoveObserver: function (aObserver)
{
this._composite.RemoveObserver(aObserver);
},
ArcLabelsIn: function (aNode)
{
return this._composite.ArcLabelsIn(aNode);
},
ArcLabelsOut: function (aSource)
{
return this._composite.ArcLabelsOut(aSource);
},
GetAllResources: function ()
{
return this._composite.GetAllResources();
},
IsCommandEnabled: function (aSources, aCommand, aArguments)
{
return this._composite.IsCommandEnabled(aSources, aCommand, aArguments);
},
DoCommand: function (aSources, aCommand, aArguments)
{
this._composite.DoCommand(aSources, aCommand, aArguments);
},
GetAllCmds: function (aSource)
{
return this._composite.GetAllCmds(aSource);
},
hasArcIn: function (aNode, aArc)
{
return this._composite.hasArcIn(aNode, aArc);
},
hasArcOut: function (aSource, aArc)
{
return this._composite.hasArcOut(aSource, aArc);
},
beginUpdateBatch: function ()
{
return this._composite.beginUpdateBatch();
},
endUpdateBatch: function ()
{
return this._composite.endUpdateBatch();
},
/////////////////////////////////////////////////////////////////////////////
// nsIRDFRemoteDataSource
get loaded()
{
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
init: function (aURI)
{
},
refresh: function (aBlocking)
{
},
flush: function ()
{
this._flush(false);
this._flush(true);
},
flushTo: function (aURI)
{
},
_flush: function (aIsProfile)
{
var ds = aIsProfile ? this._profileExtensions : this._appExtensions;
var rds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
rds.Flush();
},
/////////////////////////////////////////////////////////////////////////////
// nsISupports
QueryInterface: function (aIID)
{
if (!aIID.equals(Components.interfaces.nsIRDFDataSource) &&
!aIID.equals(Components.interfaces.nsIRDFRemoteDataSource) &&
!aIID.equals(Components.interfaces.nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
}
};
var gModule = {
_firstTime: true,
registerSelf: function (aComponentManager, aFileSpec, aLocation, aType)
{
if (this._firstTime) {
this._firstTime = false;
throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
}
aComponentManager = aComponentManager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
aComponentManager.registerFactoryLocation(this._cid,
"Extension Manager",
this._contractId,
aFileSpec,
aLocation,
aType);
// Make the Extension Manager a startup observer
var categoryManager = Components.classes["@mozilla.org/categorymanager;1"]
.getService(Components.interfaces.nsICategoryManager);
categoryManager.addCategoryEntry("app-startup", "Extension Manager",
"service," + this._contractId, true, true, null);
},
getClassObject: function (aComponentManager, aCID, aIID)
{
if (!aCID.equals(this._cid))
throw Components.results.NS_ERROR_NO_INTERFACE;
if (!aIID.equals(Components.interfaces.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
return this._factory;
},
_cid: Components.ID("{8A115FAA-7DCB-4e8f-979B-5F53472F51CF}"),
_contractId: "@mozilla.org/extension-manager;1",
_factory: {
createInstance: function (aOuter, aIID)
{
if (aOuter != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
if (!gExtensionManager)
gExtensionManager = new nsExtensionManager();
return gExtensionManager.QueryInterface(aIID);
}
},
canUnload: function (aComponentManager)
{
return true;
}
};
function NSGetModule(compMgr, fileSpec)
{
return gModule;
}

View File

@ -38,6 +38,8 @@ en-US.jar:
classic.jar:
skin/classic/mozapps/extensions/extensions.css (extensions/skin/extensions.css)
skin/classic/mozapps/extensions/about.css (extensions/skin/about.css)
skin/classic/mozapps/extensions/placeholder.gif (extensions/skin/placeholder.gif)
skin/classic/mozapps/extensions/viewWatermark.png (extensions/skin/viewWatermark.png)
skin/classic/mozapps/shared/richview.xml (shared/skin/richview.xml)
skin/classic/mozapps/shared/richview.css (shared/skin/richview.css)
skin/classic/mozapps/shared/viewFader.png (shared/skin/viewFader.png)