25 const Cc = Components.classes;
26 const Ci = Components.interfaces;
27 const Cr = Components.results;
28 const Ce = Components.Exception;
29 const Cu = Components.utils;
31 Cu.import(
"resource://gre/modules/XPCOMUtils.jsm");
32 Cu.import(
"resource://app/jsmodules/ArrayConverter.jsm");
33 Cu.import(
"resource://app/jsmodules/RDFHelper.jsm");
34 Cu.import(
"resource://app/jsmodules/sbProperties.jsm");
41 classID: Components.ID(
"{e63463d0-357c-4035-af33-db670ee1b7f2}"),
42 contractID:
"@songbirdnest.com/Songbird/MediaPageManager;1",
48 _defaultPlaylistPage:
null,
49 _defaultFilteredPlaylistPage:
null,
52 registerPage:
function(
aName, aURL, aIcon, aMatchInterface) {
57 for each (pageInfo
in this._pageInfoArray) {
58 if (pageInfo.contentUrl == aURL) {
59 throw new Error(
"Page URL already registered: " + aURL);
74 get matchInterface() {
75 return aMatchInterface;
78 if (!iid.equals(
Ci.sbIMediaPageInfo) &&
79 !iid.equals(
Ci.nsISupports))
80 throw Cr.NS_ERROR_NO_INTERFACE;
86 this._pageInfoArray.push(pageInfo);
92 unregisterPage:
function(aPageInfo) {
95 if (this._defaultFilteredPlaylistPage &&
96 this._defaultFilteredPlaylistPage.contentUrl == aPageInfo.contentUrl) {
97 this._defaultFilteredPlaylistPage =
null;
98 }
else if (this._defaultPlaylistPage &&
99 this._defaultPlaylistPage.contentUrl == aPageInfo.contentUrl) {
100 this._defaultPlaylistPage =
null;
104 for (var
i in this._pageInfoArray) {
105 if (aPageInfo.contentUrl ==
this._pageInfoArray[
i].contentUrl) {
107 this._pageInfoArray.splice(
i, 1);
112 throw new Error(
"Page " + aPageInfo.contentTitle +
" not found in unregisterPage");
116 this._ensureMediaPageRegistration();
119 return ArrayConverter.enumerator(this._pageInfoArray);
123 for (var
i in this._pageInfoArray) {
124 var pageInfo = this._pageInfoArray[
i];
125 if (pageInfo.matchInterface.match(aList,
aConstraint)) {
126 tempArray.push(pageInfo);
131 return ArrayConverter.enumerator(tempArray);
135 this._ensureMediaPageRegistration();
138 aList = this._getOutermostList(aList);
141 var remote =
Cc[
"@songbirdnest.com/Songbird/DataRemote;1"]
142 .createInstance(
Ci.sbIDataRemote);
143 var baseKey =
"mediapages." + aList.guid;
146 key = baseKey +
"." + aType;
147 remote.init(key,
null);
148 var savedPageURL = remote.stringValue;
149 if (savedPageURL && savedPageURL !=
"") {
152 let pageInfo = this._checkPageForList(aList, aConstraint, savedPageURL);
153 if (pageInfo)
return pageInfo;
157 let remote =
Cc[
"@songbirdnest.com/Songbird/DataRemote;1"]
158 .createInstance(
Ci.sbIDataRemote);
159 remote.init(baseKey,
null);
160 let savedOldPageURL = remote.stringValue;
161 if (savedOldPageURL && savedOldPageURL !=
"") {
164 let oldPageInfo = this._checkPageForList(aList,
167 if (oldPageInfo)
return oldPageInfo;
172 var defaultPageURL = aList.getProperty(SBProperties.defaultMediaPageURL);
173 if (defaultPageURL && defaultPageURL !=
"") {
176 var pageInfo = this._checkPageForList(aList, aConstraint, defaultPageURL);
177 if (pageInfo)
return pageInfo;
186 if (this._defaultPlaylistPage) {
187 return this._defaultPlaylistPage;
191 for (var
i in this._pageInfoArray) {
192 var pageInfo = this._pageInfoArray[
i];
193 if (pageInfo.matchInterface.match(aList, aConstraint)) {
200 throw new Error(
"MediaPageManager unable to determine a page for " + aList.guid);
206 setPage:
function(aList, aPageInfo, aType) {
208 aList = this._getOutermostList(aList);
211 var remote =
Cc[
"@songbirdnest.com/Songbird/DataRemote;1"]
212 .createInstance(
Ci.sbIDataRemote);
213 var
key =
"mediapages." + aList.guid;
215 key = key +
"." + aType;
216 remote.init(key,
null);
217 remote.stringValue = aPageInfo.contentUrl;
223 _getOutermostList:
function(aList) {
224 var outerGuid = aList.getProperty(SBProperties.outerGUID);
226 aList = aList.library.getMediaItem(outerGuid);
232 _checkPageForList:
function(aList,
aConstraint, aUrl) {
233 for (var
i in this._pageInfoArray) {
234 var pageInfo = this._pageInfoArray[
i];
235 if (pageInfo.contentUrl != aUrl)
continue;
236 if (!pageInfo.matchInterface.match(aList, aConstraint))
continue;
242 _ensureMediaPageRegistration:
function() {
243 if(this._registrationComplete) {
return };
245 this._registerDefaults();
246 MediaPageMetadataReader.loadMetadata(
this);
248 this._registrationComplete =
true;
251 _registerDefaults:
function() {
252 var playlistString =
"mediapages.playlistpage";
253 var filteredPlaylistString =
"mediapages.filteredplaylistpage";
255 var stringBundleService =
Cc[
"@mozilla.org/intl/stringbundle;1"]
256 .getService(
Ci.nsIStringBundleService);
257 var stringBundle = stringBundleService.createBundle(
258 "chrome://songbird/locale/songbird.properties" );
259 playlistString = stringBundle.GetStringFromName(playlistString);
260 filteredPlaylistString = stringBundle.GetStringFromName(
261 filteredPlaylistString);
262 stringBundleService =
null;
265 Component.utils.reportError(
"MediaPageManager: Couldn't localize default media page name.\n")
269 var matchAll = {
match:
function()
true};
272 this._defaultFilteredPlaylistPage =
273 this.registerPage( filteredPlaylistString,
274 "chrome://songbird/content/mediapages/filtersPage.xul",
279 this._defaultPlaylistPage =
280 this.registerPage( playlistString,
281 "chrome://songbird/content/mediapages/playlistPage.xul",
294 var MediaPageMetadataReader = {
295 loadMetadata:
function(manager) {
296 this._manager = manager;
299 "rdf:addon-metadata",
300 "urn:songbird:addon:root",
304 for (var
i = 0;
i < addons.length;
i++) {
306 if (!addons[
i].mediaPage)
309 var
pages = addons[
i].mediaPage;
310 for (var j = 0; j < pages.length; j++) {
311 this._registerMediaPage(addons[
i], pages[j])
314 this._reportErrors(
"", [
"An error occurred while processing " +
315 "extension " + addons[
i].Value +
". Exception: " + e ]);
323 _registerMediaPage:
function _registerMediaPage(addon, page) {
326 var warningList = [];
329 for (property in page) {
331 info[property] = page[property][0];
334 this._validateProperties(info, errorList, warningList);
339 var matchList = this._createMatchList(page, warningList);
340 matchFunction = this._createMatchFunction(matchList);
343 matchFunction = this._createMatchAllFunction();
347 if (warningList.length > 0){
349 "Warning: " + addon.Value +
" install.rdf loading media page: " , warningList);
351 if (errorList.length > 0) {
353 "ERROR: " + addon.Value +
" install.rdf IGNORED media page: ", errorList);
358 this._manager.registerPage( info.contentTitle,
361 {
match: matchFunction}
368 _validateProperties:
function(info, errorList, warningList) {
369 var requiredProperties = [
"contentTitle",
"contentUrl"];
370 var optionalProperties = [
"contentIcon",
"match"];
373 for (var
p in requiredProperties) {
374 if (!info[requiredProperties[
p]]) {
375 errorList.push(
"Missing required property " + requiredProperties[p] +
".\n")
381 for(var
i in requiredProperties) {
382 template[requiredProperties[
i]] =
"required";
384 for(var
i in optionalProperties) {
385 template[optionalProperties[
i]] =
"optional";
388 for (var
p in info) {
390 warningList.push(
"Unrecognized property " +
p +
".\n")
395 _createMatchList:
function(page, warningList) {
401 for (var
i = 0;
i < page.match.length;
i++) {
402 var fields = page.match[
i].split(/\s+/);
404 for(var f in fields) {
406 [
key,
value] = fields[f].split(
":");
407 if(!value) { value =
key; key =
"type" };
412 if(properties[key]) {
413 warningList.push(
"Attempting to match two values for "
414 +key+
": "+properties[key]+
" and "+value+
".");
420 matchList.push(properties);
426 _createMatchFunction:
function(matchList) {
428 var matchFunction =
function(mediaList,
aConstraint) {
436 for (var m in matchList) {
437 let
match = matchList[m];
444 var numProperties = 0;
445 for (var
i in match) {
450 if (numProperties == 1 && match[
"type"]) {
451 if (mediaList.getProperty(SBProperties.onlyCustomMediaPages) ==
"1") {
456 var thisListMatches =
true;
457 for (var
i in match) {
462 for (let
group in ArrayConverter.JSEnum(aConstraint.groups)) {
463 if (!(
group instanceof
Ci.sbILibraryConstraintGroup)) {
466 if (!
group.hasProperty(SBProperties.contentType)) {
470 ArrayConverter.JSArray(
group.getValues(SBProperties.contentType));
471 if (contentTypes.indexOf(match[
i]) == -1) {
472 thisListMatches =
false;
479 if (
i in mediaList) {
480 thisListMatches &= (match[
i] == mediaList[
i]);
486 thisListMatches &= (match[
i] == mediaList.getProperty(SBProperties[
i]));
489 if (!thisListMatches) {
493 if (thisListMatches) {
503 return matchFunction;
506 _createMatchAllFunction:
function() {
507 var matchFunction =
function(mediaList) {
510 return(mediaList && mediaList.getProperty(SBProperties.onlyCustomMediaPages) !=
"1");
512 return matchFunction;
521 _reportErrors:
function _reportErrors(contextMessage, errorList) {
522 var consoleService =
Cc[
"@mozilla.org/consoleservice;1"]
523 .getService(
Ci.nsIConsoleService);
524 for (var
i = 0;
i < errorList.length;
i++) {
525 Cu.reportError(
"MediaPage Addon Metadata: " + contextMessage + errorList[
i]);
function MediaPageManager()
sbDeviceFirmwareAutoCheckForUpdate prototype contractID
sbOSDControlService prototype QueryInterface
sbDeviceFirmwareAutoCheckForUpdate prototype classDescription
function RDFHelper(aRdf, aDatasource, aResource, aNamespaces)
ExtensionSchemeMatcher prototype match
sbDeviceFirmwareAutoCheckForUpdate prototype classID
_getSelectedPageStyle s i