2008-08-20 05:08:37 +04:00
|
|
|
/* ***** 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 Snowl.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Mozilla.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2008
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Myk Melez <myk@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 ***** */
|
|
|
|
|
|
|
|
const Cc = Components.classes;
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cr = Components.results;
|
|
|
|
const Cu = Components.utils;
|
|
|
|
|
2008-08-29 00:49:58 +04:00
|
|
|
// modules that come with Firefox
|
2008-11-19 03:06:01 +03:00
|
|
|
// FIXME: remove this import of XPCOMUtils, as it is no longer being used.
|
2008-08-29 00:49:58 +04:00
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
|
2008-11-04 23:11:07 +03:00
|
|
|
// modules that are generic
|
2008-08-20 05:08:37 +04:00
|
|
|
Cu.import("resource://snowl/modules/log4moz.js");
|
2008-09-02 06:01:56 +04:00
|
|
|
Cu.import("resource://snowl/modules/Observers.js");
|
2009-06-06 10:02:12 +04:00
|
|
|
Cu.import("resource://snowl/modules/Sync.js");
|
2008-11-04 23:11:07 +03:00
|
|
|
Cu.import("resource://snowl/modules/URI.js");
|
2008-08-20 05:08:37 +04:00
|
|
|
|
2008-08-29 00:49:58 +04:00
|
|
|
// modules that are Snowl-specific
|
2008-08-20 05:08:37 +04:00
|
|
|
Cu.import("resource://snowl/modules/datastore.js");
|
2009-08-25 04:44:30 +04:00
|
|
|
Cu.import("resource://snowl/modules/collection2.js");
|
2008-12-29 04:56:01 +03:00
|
|
|
Cu.import("resource://snowl/modules/constants.js");
|
2008-08-26 05:20:52 +04:00
|
|
|
Cu.import("resource://snowl/modules/utils.js");
|
2008-11-04 23:24:08 +03:00
|
|
|
Cu.import("resource://snowl/modules/twitter.js");
|
|
|
|
Cu.import("resource://snowl/modules/service.js");
|
2008-08-20 05:08:37 +04:00
|
|
|
|
|
|
|
let SnowlMessageView = {
|
|
|
|
get _log() {
|
|
|
|
delete this._log;
|
2008-11-19 03:06:01 +03:00
|
|
|
return this._log = Log4Moz.repository.getLogger("Snowl.Stream");
|
2008-08-20 05:08:37 +04:00
|
|
|
},
|
|
|
|
|
2008-11-20 01:53:55 +03:00
|
|
|
get _writeButton() {
|
|
|
|
delete this._writeButton;
|
2009-03-06 07:38:46 +03:00
|
|
|
return this._writeButton = document.getElementById("writeButton");
|
2008-11-05 05:34:10 +03:00
|
|
|
},
|
|
|
|
|
2008-11-20 01:53:55 +03:00
|
|
|
get _writeForm() {
|
|
|
|
delete this._writeForm;
|
|
|
|
return this._writeForm = document.getElementById("writeForm");
|
2008-08-20 05:08:37 +04:00
|
|
|
},
|
|
|
|
|
2009-11-12 05:03:07 +03:00
|
|
|
get _refreshButton() {
|
|
|
|
delete this._refreshButton;
|
|
|
|
return this._refreshButton = document.getElementById("snowlRefreshButton");
|
|
|
|
},
|
|
|
|
|
2008-08-20 05:08:37 +04:00
|
|
|
_window: null,
|
|
|
|
_document: null,
|
|
|
|
|
|
|
|
// The set of messages to display in the view.
|
|
|
|
_collection: null,
|
|
|
|
|
2008-08-22 01:01:22 +04:00
|
|
|
// the width (narrower dimension) of the vertical and horizontal scrollbars;
|
|
|
|
// useful for calculating the viewable size of the viewport, since window.
|
|
|
|
// innerWidth and innerHeight include the area taken up by the scrollbars
|
|
|
|
// XXX Is this value correct, and does it vary by platform?
|
|
|
|
scrollbarWidth: 15,
|
|
|
|
|
|
|
|
get stylesheet() {
|
|
|
|
for (let i = 0; i < document.styleSheets.length; i++)
|
|
|
|
if (document.styleSheets[i].href == "chrome://snowl/content/stream.css")
|
|
|
|
return document.styleSheets[i];
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
|
|
|
_updateRule: function(position, newValue) {
|
|
|
|
this.stylesheet.deleteRule(position);
|
|
|
|
this.stylesheet.insertRule(newValue, position);
|
|
|
|
},
|
|
|
|
|
2008-08-20 05:08:37 +04:00
|
|
|
|
|
|
|
//**************************************************************************//
|
|
|
|
// Initialization & Destruction
|
|
|
|
|
|
|
|
onLoad: function() {
|
2009-11-12 05:03:07 +03:00
|
|
|
Observers.add("snowl:message:added", this.onMessageAdded, this);
|
|
|
|
Observers.add("snowl:source:added", this.onSourcesChanged, this);
|
|
|
|
Observers.add("snowl:source:unstored", this.onSourceRemoved, this);
|
|
|
|
Observers.add("snowl:messages:completed", this.onMessagesCompleted, this);
|
2008-08-29 00:49:58 +04:00
|
|
|
|
2008-08-22 01:01:22 +04:00
|
|
|
this.onResize();
|
|
|
|
|
2008-08-20 05:08:37 +04:00
|
|
|
// Explicitly wrap |window| in an XPCNativeWrapper to make sure
|
|
|
|
// it's a real native object! This will throw an exception if we
|
|
|
|
// get a non-native object.
|
|
|
|
this._window = new XPCNativeWrapper(window);
|
|
|
|
this._document = this._window.document;
|
|
|
|
|
2009-08-25 04:44:30 +04:00
|
|
|
// We sort in descending order by ID (the default sort in StorageCollection)
|
|
|
|
// in order to do an implicit sort on received time (so that we show
|
|
|
|
// messages in the order they are received) while making sure that we always
|
|
|
|
// show messages in the same order even when their received times are
|
|
|
|
// the same.
|
2008-12-09 21:52:19 +03:00
|
|
|
//
|
|
|
|
// We could instead sort by received and timestamp, to show messages
|
|
|
|
// as they are received, with messages received at the same time being
|
|
|
|
// sorted by timestamp; but since we add messages to the view as they
|
|
|
|
// are received, regardless of their timestamp, doing that would cause
|
|
|
|
// there to be a difference between what the user sees when they leave
|
|
|
|
// the view open (and messages accumulate in it over time) versus what
|
|
|
|
// they see when they open it anew.
|
2008-12-21 09:34:29 +03:00
|
|
|
|
2009-08-25 04:44:30 +04:00
|
|
|
// We show only the last couple hundred messages.
|
2008-12-21 09:34:29 +03:00
|
|
|
// We used to show all messages within a certain time period, like the last
|
|
|
|
// week or the last day, but the purpose of the stream view is to let users
|
|
|
|
// glance at recent activity as it scrolls by, not browse messages over long
|
|
|
|
// periods of time, and a week's worth of messages is too many to usefully
|
2009-08-25 04:44:30 +04:00
|
|
|
// browse in the view. And a day's worth of messages means that if you
|
|
|
|
// start your browser after not having used it for a day, you'll see nothing
|
2008-12-21 09:34:29 +03:00
|
|
|
// in the view when you first open it, which is confusing and unexpected.
|
|
|
|
|
2009-08-25 04:44:30 +04:00
|
|
|
this._collection = new StorageCollection({ limit: 250 });
|
2009-02-12 21:32:28 +03:00
|
|
|
|
2008-11-20 22:59:28 +03:00
|
|
|
this._initWriteForm();
|
2008-11-04 23:24:08 +03:00
|
|
|
this._updateWriteButton();
|
2009-06-09 14:27:16 +04:00
|
|
|
|
|
|
|
this._rebuildView();
|
2008-10-17 06:11:46 +04:00
|
|
|
},
|
|
|
|
|
2008-10-29 03:33:20 +03:00
|
|
|
onunLoad: function() {
|
2009-11-12 05:03:07 +03:00
|
|
|
Observers.remove("snowl:message:added", this.onMessageAdded, this);
|
|
|
|
Observers.remove("snowl:source:added", this.onSourcesChanged, this);
|
|
|
|
Observers.remove("snowl:source:unstored", this.onSourceRemoved, this);
|
|
|
|
Observers.remove("snowl:messages:completed", this.onMessagesCompleted, this);
|
2008-10-29 03:33:20 +03:00
|
|
|
},
|
|
|
|
|
2008-11-20 22:59:28 +03:00
|
|
|
_initWriteForm: function() {
|
|
|
|
// For some reason setting hidden="true" in the XUL file prevents us
|
|
|
|
// from showing the box later via writeForm.hidden = false, so we set it
|
|
|
|
// here instead.
|
|
|
|
// FIXME: file a bug on this abnormality.
|
2008-12-24 04:01:38 +03:00
|
|
|
// XXX Note: setting hidden="true" and then showing the box later
|
|
|
|
// via writeForm.hidden = false works fine in the list sidebar, so I'm
|
|
|
|
// not sure why it isn't working here.
|
2008-11-20 22:59:28 +03:00
|
|
|
this._writeForm.hidden = true;
|
|
|
|
},
|
|
|
|
|
2008-11-20 01:53:55 +03:00
|
|
|
// Selectively enable/disable the button for writing a message depending on
|
2008-11-04 23:24:08 +03:00
|
|
|
// whether or not the user has an account that supports writing.
|
|
|
|
_updateWriteButton: function() {
|
2009-11-12 01:38:07 +03:00
|
|
|
this._writeButton.disabled = (SnowlService.targetsByID.length == 0);
|
2008-11-04 23:24:08 +03:00
|
|
|
},
|
|
|
|
|
2008-08-20 05:08:37 +04:00
|
|
|
|
|
|
|
//**************************************************************************//
|
2008-08-29 00:49:58 +04:00
|
|
|
// Event & Notification Handlers
|
|
|
|
|
2008-08-22 01:01:22 +04:00
|
|
|
/**
|
|
|
|
* Resize the content in the middle column based on the width of the viewport.
|
|
|
|
* FIXME: file a bug on the problem that necessitates this hack.
|
|
|
|
*/
|
|
|
|
onResize: function() {
|
2008-12-09 06:37:48 +03:00
|
|
|
const LEFT_COLUMN_WIDTH = 24 + 4; // 24px width + 4px right margin
|
|
|
|
const RIGHT_COLUMN_WIDTH = 16 + 2; // 16px width + 2px left margin
|
|
|
|
|
|
|
|
// Calculate the width of the middle column and set it (along with some
|
|
|
|
// of its contents to that width). See the comments in stream.css
|
|
|
|
// for more info on why we set each of these rules.
|
|
|
|
|
2008-08-22 01:01:22 +04:00
|
|
|
// We anticipate that there will be a scrollbar, so we include it
|
2008-12-09 06:37:48 +03:00
|
|
|
// in the calculation. Perhaps we should instead wait to include it
|
|
|
|
// until the content actually overflows.
|
|
|
|
|
|
|
|
// window.innerWidth == document.documentElement.boxObject.width == document.documentElement.clientWidth,
|
|
|
|
// and I know of no reason to prefer one over the other, except that
|
|
|
|
// clientWidth only works in Firefox 3.1+, and we support Firefox 3.0,
|
|
|
|
// so one of the others is better.
|
|
|
|
|
|
|
|
let width = window.innerWidth - this.scrollbarWidth - LEFT_COLUMN_WIDTH - RIGHT_COLUMN_WIDTH;
|
2008-12-24 02:03:51 +03:00
|
|
|
this._updateRule(0, ".body { min-width: " + width + "px; max-width: " + width + "px }");
|
|
|
|
this._updateRule(1, ".body > div { min-width: " + width + "px; max-width: " + width + "px }");
|
|
|
|
this._updateRule(2, ".centerColumn { min-width: " + width + "px; max-width: " + width + "px }");
|
2008-08-22 01:01:22 +04:00
|
|
|
},
|
|
|
|
|
2008-12-29 16:56:13 +03:00
|
|
|
onMessageAdded: function(message) {
|
stop using a sandbox to do DOM manipulations, as it turns out to be unnecessary; this is the result of much digging about the FeedWriter.js code and history, including in particular bug 360529, which is where a lot of the sandbox stuff happened; FeedWriter.js is modifying an existing content document, so it has to be very careful how it does so; we're building a new document, though, in which we explicitly parse feed content with JavaScript disabled, so we aren't subject to the same issues that plagued the feed preview page, necessitating the sandbox approach they take; however, we leave in the code that checks the codebase principals for each source when setting a URI attribute, since we still have to make sure each URI can be loaded by the source that provided it (and in particular that it isn't a javascript: or data: URL that might run code with unwarranted privileges in our chrome environment) before inserting it into the document
2008-12-29 09:58:08 +03:00
|
|
|
let messages = this._document.getElementById("contentBox");
|
|
|
|
let messageBox = this._buildMessageView(message);
|
|
|
|
messages.insertBefore(messageBox, messages.firstChild);
|
2008-08-29 00:49:58 +04:00
|
|
|
},
|
|
|
|
|
2008-12-29 16:56:13 +03:00
|
|
|
onSourcesChanged: function() {
|
2008-11-04 23:24:08 +03:00
|
|
|
this._updateWriteButton();
|
2008-12-30 03:09:55 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
onSourceRemoved: function() {
|
|
|
|
// We don't currently have a way to remove just the messages
|
|
|
|
// from the removed source, so rebuild the entire view.
|
2008-11-04 23:11:07 +03:00
|
|
|
this._rebuildView();
|
|
|
|
},
|
|
|
|
|
2009-11-12 05:03:07 +03:00
|
|
|
onMessagesCompleted: function(aSourceId) {
|
|
|
|
// Enable refresh button.
|
|
|
|
if (SnowlService.refreshingCount == 0)
|
|
|
|
this._refreshButton.removeAttribute("disabled");
|
|
|
|
// Disable refresh button.
|
|
|
|
if (aSourceId == "refresh")
|
|
|
|
this._refreshButton.setAttribute("disabled", true);
|
|
|
|
},
|
|
|
|
|
2008-09-27 05:37:39 +04:00
|
|
|
onToggleGroup: function(event) {
|
|
|
|
event.target.nextSibling.style.display = event.target.checked ? "block" : "none";
|
|
|
|
},
|
|
|
|
|
2008-12-12 01:30:09 +03:00
|
|
|
onRefresh: function() {
|
|
|
|
SnowlService.refreshAllSources();
|
|
|
|
},
|
|
|
|
|
2008-11-20 01:53:55 +03:00
|
|
|
onToggleWrite: function(event) {
|
2008-12-03 12:00:53 +03:00
|
|
|
this._writeForm.hidden = !event.target.checked;
|
2008-11-04 23:24:08 +03:00
|
|
|
},
|
|
|
|
|
2008-08-20 05:08:37 +04:00
|
|
|
|
|
|
|
//**************************************************************************//
|
|
|
|
// Content Generation
|
|
|
|
|
2009-06-06 10:02:12 +04:00
|
|
|
_rebuildView: function() {
|
2008-08-20 05:08:37 +04:00
|
|
|
let begin = new Date();
|
|
|
|
|
2008-09-27 05:37:39 +04:00
|
|
|
let contentBox = this._document.getElementById("contentBox");
|
|
|
|
while (contentBox.hasChildNodes())
|
|
|
|
contentBox.removeChild(contentBox.lastChild);
|
|
|
|
|
2009-08-25 04:44:30 +04:00
|
|
|
for each (let message in this._collection) {
|
2008-09-02 06:01:56 +04:00
|
|
|
let messageBox = this._buildMessageView(message);
|
stop using a sandbox to do DOM manipulations, as it turns out to be unnecessary; this is the result of much digging about the FeedWriter.js code and history, including in particular bug 360529, which is where a lot of the sandbox stuff happened; FeedWriter.js is modifying an existing content document, so it has to be very careful how it does so; we're building a new document, though, in which we explicitly parse feed content with JavaScript disabled, so we aren't subject to the same issues that plagued the feed preview page, necessitating the sandbox approach they take; however, we leave in the code that checks the codebase principals for each source when setting a URI attribute, since we still have to make sure each URI can be loaded by the source that provided it (and in particular that it isn't a javascript: or data: URL that might run code with unwarranted privileges in our chrome environment) before inserting it into the document
2008-12-29 09:58:08 +03:00
|
|
|
contentBox.appendChild(messageBox);
|
2008-08-20 05:08:37 +04:00
|
|
|
|
2008-12-19 01:30:00 +03:00
|
|
|
// Sleep a bit after every message so we don't hork the UI thread and users
|
2008-08-20 05:08:37 +04:00
|
|
|
// can immediately start reading messages while we finish writing them.
|
2009-06-06 10:02:12 +04:00
|
|
|
Sync.sleep(0);
|
2008-08-20 05:08:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
this._log.info("time spent building view: " + (new Date() - begin) + "ms\n");
|
2008-08-22 01:01:22 +04:00
|
|
|
|
|
|
|
//let serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].
|
|
|
|
// createInstance(Ci.nsIDOMSerializer);
|
|
|
|
//this._log.info(serializer.serializeToString(document.getElementById("contentBox")));
|
2009-06-06 10:02:12 +04:00
|
|
|
},
|
2008-09-02 06:01:56 +04:00
|
|
|
|
|
|
|
_buildMessageView: function(message) {
|
|
|
|
let messageBox = this._document.createElementNS(XUL_NS, "hbox");
|
|
|
|
messageBox.className = "message";
|
|
|
|
|
|
|
|
// left column
|
|
|
|
let leftColumn = this._document.createElementNS(XUL_NS, "vbox");
|
|
|
|
leftColumn.className = "leftColumn";
|
|
|
|
let icon = document.createElementNS(XUL_NS, "image");
|
|
|
|
icon.className = "icon";
|
2009-06-06 10:02:12 +04:00
|
|
|
if (message.author && message.author.person.iconURL)
|
|
|
|
icon.setAttribute("src", message.author.person.iconURL);
|
2008-12-29 13:31:56 +03:00
|
|
|
else if (message.source.faviconURI)
|
|
|
|
icon.setAttribute("src", message.source.faviconURI.spec)
|
|
|
|
else
|
|
|
|
icon.setAttribute("src", "chrome://snowl/skin/livemarkItem-16.png");
|
|
|
|
|
2008-09-02 06:01:56 +04:00
|
|
|
leftColumn.appendChild(icon);
|
|
|
|
messageBox.appendChild(leftColumn);
|
|
|
|
|
|
|
|
// center column
|
|
|
|
let centerColumn = this._document.createElementNS(XUL_NS, "vbox");
|
|
|
|
centerColumn.className = "centerColumn";
|
|
|
|
messageBox.appendChild(centerColumn);
|
|
|
|
|
|
|
|
// Author or Source
|
2009-06-06 10:02:12 +04:00
|
|
|
if (message.author || message.source) {
|
2008-09-02 06:01:56 +04:00
|
|
|
let desc = this._document.createElementNS(XUL_NS, "description");
|
2009-06-06 10:02:12 +04:00
|
|
|
let value = message.author && message.author.person.name ?
|
|
|
|
message.author.person.name :
|
|
|
|
message.source.name;
|
2008-09-02 06:01:56 +04:00
|
|
|
desc.className = "author";
|
|
|
|
desc.setAttribute("crop", "end");
|
2009-06-06 10:02:12 +04:00
|
|
|
desc.setAttribute("value", value);
|
2008-09-02 06:01:56 +04:00
|
|
|
centerColumn.appendChild(desc);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Timestamp
|
|
|
|
// Commented out because the timestamp isn't that useful when we order
|
|
|
|
// by time received. Instead, we're going to group by time period
|
|
|
|
// received (this morning, yesterday, last week, etc.) to give users
|
|
|
|
// useful chronographic info.
|
2008-11-02 20:20:12 +03:00
|
|
|
//let lastUpdated = SnowlDateUtils._formatDate(message.timestamp);
|
2008-09-02 06:01:56 +04:00
|
|
|
//if (lastUpdated) {
|
|
|
|
// let timestamp = this._document.createElementNS(XUL_NS, "description");
|
|
|
|
// timestamp.className = "timestamp";
|
|
|
|
// timestamp.setAttribute("crop", "end");
|
|
|
|
// timestamp.setAttribute("value", lastUpdated);
|
|
|
|
// centerColumn.appendChild(timestamp);
|
|
|
|
//}
|
|
|
|
|
2008-11-26 11:41:40 +03:00
|
|
|
// Content (subject or excerpt)
|
2008-09-02 06:01:56 +04:00
|
|
|
let body = this._document.createElementNS(XUL_NS, "description");
|
|
|
|
body.className = "body";
|
|
|
|
let div = this._document.createElementNS(HTML_NS, "div");
|
2008-11-26 11:41:40 +03:00
|
|
|
|
|
|
|
let content = message.subject || message.excerpt;
|
2008-09-02 06:01:56 +04:00
|
|
|
|
|
|
|
if (message.link) {
|
|
|
|
let a = this._document.createElementNS(HTML_NS, "a");
|
2009-06-13 21:00:05 +04:00
|
|
|
SnowlUtils.safelySetURIAttribute(a,
|
|
|
|
"href",
|
|
|
|
message.link.spec,
|
|
|
|
message.source.principal);
|
2008-09-02 06:01:56 +04:00
|
|
|
body.className += " text-link";
|
2008-11-26 11:41:40 +03:00
|
|
|
a.appendChild(this._document.createTextNode(content));
|
2008-09-02 06:01:56 +04:00
|
|
|
div.appendChild(a);
|
|
|
|
}
|
2009-06-09 14:11:42 +04:00
|
|
|
else if (content) {
|
stop using a sandbox to do DOM manipulations, as it turns out to be unnecessary; this is the result of much digging about the FeedWriter.js code and history, including in particular bug 360529, which is where a lot of the sandbox stuff happened; FeedWriter.js is modifying an existing content document, so it has to be very careful how it does so; we're building a new document, though, in which we explicitly parse feed content with JavaScript disabled, so we aren't subject to the same issues that plagued the feed preview page, necessitating the sandbox approach they take; however, we leave in the code that checks the codebase principals for each source when setting a URI attribute, since we still have to make sure each URI can be loaded by the source that provided it (and in particular that it isn't a javascript: or data: URL that might run code with unwarranted privileges in our chrome environment) before inserting it into the document
2008-12-29 09:58:08 +03:00
|
|
|
SnowlUtils.linkifyText(content, div, message.source.principal);
|
2008-09-02 06:01:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
body.appendChild(div);
|
|
|
|
centerColumn.appendChild(body);
|
|
|
|
|
|
|
|
// Source
|
|
|
|
//let source = this._document.createElementNS(HTML_NS, "a");
|
|
|
|
//source.className = "source";
|
|
|
|
//let sourceIcon = document.createElementNS(HTML_NS, "img");
|
|
|
|
//let sourceFaviconURI = message.source.humanURI || URI.get("urn:use-default-icon");
|
|
|
|
//sourceIcon.src = this._faviconSvc.getFaviconImageForPage(sourceFaviconURI).spec;
|
|
|
|
//source.appendChild(sourceIcon);
|
|
|
|
//source.appendChild(this._document.createTextNode(message.source.name));
|
|
|
|
//if (message.source.humanURI)
|
stop using a sandbox to do DOM manipulations, as it turns out to be unnecessary; this is the result of much digging about the FeedWriter.js code and history, including in particular bug 360529, which is where a lot of the sandbox stuff happened; FeedWriter.js is modifying an existing content document, so it has to be very careful how it does so; we're building a new document, though, in which we explicitly parse feed content with JavaScript disabled, so we aren't subject to the same issues that plagued the feed preview page, necessitating the sandbox approach they take; however, we leave in the code that checks the codebase principals for each source when setting a URI attribute, since we still have to make sure each URI can be loaded by the source that provided it (and in particular that it isn't a javascript: or data: URL that might run code with unwarranted privileges in our chrome environment) before inserting it into the document
2008-12-29 09:58:08 +03:00
|
|
|
// SnowlUtils.safelySetURIAttribute(source, "href", message.source.humanURI.spec, message.source.principal);
|
2008-09-02 06:01:56 +04:00
|
|
|
//centerColumn.appendChild(source);
|
|
|
|
|
|
|
|
// right column
|
|
|
|
let rightColumn = this._document.createElementNS(XUL_NS, "vbox");
|
|
|
|
rightColumn.className = "rightColumn";
|
|
|
|
messageBox.appendChild(rightColumn);
|
|
|
|
|
|
|
|
return messageBox;
|
|
|
|
}
|
2008-08-20 05:08:37 +04:00
|
|
|
|
|
|
|
};
|