Initial support for microsummaries via a service and integration into the bookmarks UI.

bug=334471
r=brettw
a=ben for the branch
This commit is contained in:
myk%mozilla.org 2006-05-05 22:45:37 +00:00
Родитель f94d228c92
Коммит 19eac0bfdf
34 изменённых файлов: 2787 добавлений и 34 удалений

Просмотреть файл

@ -540,6 +540,46 @@
#endif
</toolbarbutton>
</rule>
<!-- A rule to match bookmarks with microsummary generated titles.
- We have to use the extended template syntax to specify the rule
- because the simplified syntax doesn't permit conditions that test
- for the mere presence of a property, and microsummarized bookmarks
- are identified by the mere presence of the GeneratedTitle property.
-->
<rule>
<conditions>
<content uri="?start" tag="hbox"/>
<member container="?start" child="?bookmark"/>
<triple subject="?bookmark"
predicate="http://home.netscape.com/NC-rdf#GeneratedTitle"
object="?GeneratedTitle"/>
</conditions>
<bindings>
<binding subject="?bookmark"
predicate="http://home.netscape.com/WEB-rdf#status"
object="?status"/>
<binding subject="?bookmark"
predicate="http://home.netscape.com/NC-rdf#Bookmark"
object="?xBookmark"/>
<binding subject="?bookmark"
predicate="http://home.netscape.com/NC-rdf#Icon"
object="?Icon"/>
<binding subject="?bookmark"
predicate="http://home.netscape.com/NC-rdf#URL"
object="?URL"/>
</bindings>
<action>
<toolbarbutton class="bookmark-item-microsummarized bookmark-item"
uri="?bookmark"
editable="true"
status="?status"
rdf:type="?xBookmark"
image="?Icon"
statustext="?URL"
tooltip="btTooltip"
label="?GeneratedTitle"/>
</action>
</rule>
<rule parent="hbox">
<toolbarbutton class="bookmark-item" uri="rdf:*" editable="true"
status="rdf:http://home.netscape.com/WEB-rdf#status"
@ -581,6 +621,42 @@
</menu>
</menupopup>
</rule>
<!-- A rule to match bookmarks with microsummary generated titles.
- We have to use the extended template syntax to specify the rule
- because the simplified syntax doesn't permit conditions that test
- for the mere presence of a property, and microsummarized bookmarks
- are identified by the mere presence of the GeneratedTitle property.
-->
<rule>
<conditions>
<content uri="?start"/>
<member container="?start" child="?bookmark"/>
<triple subject="?bookmark"
predicate="http://home.netscape.com/NC-rdf#GeneratedTitle"
object="?GeneratedTitle"/>
</conditions>
<bindings>
<binding subject="?bookmark"
predicate="http://home.netscape.com/WEB-rdf#status"
object="?status"/>
<binding subject="?bookmark"
predicate="http://home.netscape.com/NC-rdf#Icon"
object="?Icon"/>
<binding subject="?bookmark"
predicate="http://home.netscape.com/NC-rdf#URL"
object="?URL"/>
</bindings>
<action>
<menupopup>
<menuitem class="menuitem-iconic bookmark-item"
uri="?bookmark"
label="?GeneratedTitle"
image="?Icon"
status="?status"
statustext="?URL"/>
</menupopup>
</action>
</rule>
<rule>
<menupopup>
<menuitem class="menuitem-iconic bookmark-item" uri="rdf:*"

Просмотреть файл

@ -57,6 +57,7 @@ EXTRA_PP_COMPONENTS = \
DIRS = \
dirprovider \
microsummaries \
migration \
preferences \
search \

Просмотреть файл

@ -96,6 +96,7 @@ var gSuggestedKeyword;
var gRequiredFields = [];
var gPostData;
var gArg = window.arguments[0];
var gResource;
# on windows, sizeToContent is buggy (see bug 227951), we''ll use resizeTo
# instead and cache the bookmarks tree view size.
@ -170,6 +171,9 @@ function Startup()
// Bookmarks toolbar folder.
var btfMenuItem = document.getElementById("btfMenuItem");
btfMenuItem.id = BMSVC.getBookmarksToolbarFolder().Value;
if (MicrosummaryPicker.enabled)
MicrosummaryPicker.init();
}
function initTitle()
@ -196,35 +200,38 @@ function onOK()
{
RDFC.Init(BMDS, gSelectedFolder);
var url, rSource;
var url;
var livemarkFeed = gArg.feedURL;
if (gArg.bBookmarkAllTabs) {
rSource = BMDS.createFolder(gName.value);
gResource = BMDS.createFolder(gName.value);
const groups = gArg.objGroup;
for (var i = 0; i < groups.length; ++i) {
url = getNormalizedURL(groups[i].url);
BMDS.createBookmarkInContainer(groups[i].name, url, gKeyword.value,
groups[i].description, groups[i].charset,
gPostData, rSource, -1);
gPostData, gResource, -1);
}
} else if (livemarkFeed != null) {
url = getNormalizedURL(gArg.url);
rSource = BMDS.createLivemark(gName.value, url, livemarkFeed,
gArg.description);
gResource = BMDS.createLivemark(gName.value, url, livemarkFeed,
gArg.description);
} else {
url = getNormalizedURL(gArg.url);
rSource = BMDS.createBookmark(gName.value, url, gKeyword.value,
gArg.description, gArg.charset,
gPostData);
gResource = BMDS.createBookmark(gName.value, url, gKeyword.value,
gArg.description, gArg.charset,
gPostData);
}
var selection = BookmarksUtils.getSelectionFromResource(rSource);
var selection = BookmarksUtils.getSelectionFromResource(gResource);
var target = BookmarksUtils.getTargetFromFolder(gSelectedFolder);
BookmarksUtils.insertAndCheckSelection("newbookmark", selection, target);
if (gArg.bWebPanel && rSource) {
if (MicrosummaryPicker.enabled)
MicrosummaryPicker.commit();
if (gArg.bWebPanel && gResource) {
// Assert that we're a web panel.
BMDS.Assert(rSource, RDF.GetResource(gNC_NS+"WebPanel"),
BMDS.Assert(gResource, RDF.GetResource(gNC_NS+"WebPanel"),
RDF.GetLiteral("true"), true);
}

Просмотреть файл

@ -69,6 +69,7 @@
<script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/x-javascript" src="chrome://browser/content/bookmarks/bookmarks.js"/>
<script type="application/x-javascript" src="chrome://browser/content/bookmarks/microsummaryPicker.js"/>
<script type="application/x-javascript" src="chrome://browser/content/bookmarks/addBookmark2.js"/>
<stringbundle id="bookmarksBundle"
@ -91,6 +92,15 @@
<label value="&keyword.label;" accesskey="&keyword.accesskey;" control="keyword"/>
<textbox id="keyword" oninput="onFieldInput();"/>
</row>
<row id="microsummaryRow">
<label value="&microsummary.label;" accesskey="&microsummary.accesskey;"
control="microsummaryMenuList"/>
<menulist id="microsummaryMenuList">
<menupopup id="microsummaryMenuPopup">
<menuitem label="&microsummary.none.label;" selected="true"/>
</menupopup>
</menulist>
</row>
<row align="center">
<label id="createinlabel" value="&createin.label;" accesskey="&createin.accesskey;" control="select-menu"/>
<menulist id="select-menu" class="folder-icon"

Просмотреть файл

@ -66,7 +66,8 @@ function Init()
window.arguments[1].ok = false;
// This is the set of fields that are visible in the window.
gFields = ["name", "url", "shortcut", "description", "webpanel", "feedurl"];
gFields = ["name", "url", "shortcut", "description", "webpanel", "feedurl",
"microsummaryMenuList"];
// ...and this is a parallel array that contains the RDF properties
// that they are associated with.
@ -75,7 +76,8 @@ function Init()
RDF.GetResource(gNC_NS+"ShortcutURL"),
RDF.GetResource(gNC_NS+"Description"),
RDF.GetResource(gNC_NS+"WebPanel"),
RDF.GetResource(gNC_NS+"FeedURL")];
RDF.GetResource(gNC_NS+"FeedURL"),
RDF.GetResource(gNC_NS+"GeneratedTitle")];
var x;
// Initialize the properties panel by copying the values from the
@ -90,6 +92,11 @@ function Init()
if (gFields[i] == "webpanel")
field.checked = (value != undefined);
else if (gFields[i] == "microsummaryMenuList") {
if (MicrosummaryPicker.enabled)
MicrosummaryPicker.init();
continue;
}
else if (value) //make sure were aren't stuffing null into any fields
field.value = value;
}
@ -150,6 +157,14 @@ function Commit()
if (! field)
continue;
if (gFields[i] == "microsummaryMenuList") {
if (MicrosummaryPicker.enabled) {
changed |= MicrosummaryPicker.commit();
MicrosummaryPicker.destroy();
}
continue;
}
// Get the new value as a literal, using 'null' if the value is empty.
var newValue = field.value;
if (gFields[i] == "webpanel")
@ -193,6 +208,12 @@ function Commit()
return true;
}
function Cancel()
{
MicrosummaryPicker.destroy();
return true;
}
function updateAttribute(aProperty, aOldValue, aNewValue)
{
if ((aOldValue || aNewValue) && aOldValue != aNewValue) {

Просмотреть файл

@ -47,10 +47,12 @@
<dialog id="bmPropsWindow" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&bookmarks.windowtitle.label;"
onload="Init()" style="width: 30em;"
ondialogaccept="return Commit();">
ondialogaccept="return Commit();"
ondialogcancel="return Cancel();">
<script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/x-javascript" src="chrome://browser/content/bookmarks/bookmarks.js"/>
<script type="application/x-javascript" src="chrome://browser/content/bookmarks/microsummaryPicker.js"/>
<script type="application/x-javascript" src="chrome://browser/content/bookmarks/bookmarksProperties.js"/>
<vbox id="description-box" hidden="true">
@ -85,6 +87,14 @@
<label value="&bookmarks.shortcut.label;" control="shortcut"/>
<textbox id="shortcut" />
</row>
<row id="microsummaryRow">
<label value="&bookmarks.micsum.label;" control="microsummaryMenuList"/>
<menulist id="microsummaryMenuList">
<menupopup id="microsummaryMenuPopup">
<menuitem label="&bookmarks.micsum.none.label;" selected="true"/>
</menupopup>
</menulist>
</row>
<row id="descriptionrow">
<label value="&bookmarks.description.label;" control="description"/>
<textbox multiline="true" wrap="virtual" id="description" flex="1"/>

Просмотреть файл

@ -0,0 +1,240 @@
//* -*- Mode: C++; tab-width: 8; 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 Microsummarizer.
*
* The Initial Developer of the Original Code is Mozilla.
* Portions created by the Initial Developer are Copyright (C) 2006
* 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 ***** */
// XXX Synchronize these values with the VARIANT constants in Places code?
const ADD_BOOKMARK_MODE = 0;
const EDIT_BOOKMARK_MODE = 1;
const Cc = Components.classes;
const Ci = Components.interfaces;
var MicrosummaryPicker = {
// The microsummary service.
__mss: null,
get _mss() {
if (!this.__mss)
this.__mss = Cc["@mozilla.org/microsummary/service;1"].
getService(Ci.nsIMicrosummaryService);
return this.__mss;
},
// The IO service.
__ios: null,
get _ios() {
if (!this.__ios)
this.__ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
return this.__ios;
},
// The URI of the page being bookmarked.
get _pageURI() {
if (this._mode == ADD_BOOKMARK_MODE)
return this._ios.newURI(gArg.url, null, null);
else if (this._mode == EDIT_BOOKMARK_MODE) {
var uri = BMDS.GetTarget(gResource, gProperties[1], true);
if (uri) {
uri = uri.QueryInterface(Ci.nsIRDFLiteral).Value;
return this._ios.newURI(uri, null, null);
}
}
return null;
},
// The unique identifier for the bookmark. If we're adding a bookmark,
// this may not exist yet.
get _bookmarkID() {
if (this._mode == ADD_BOOKMARK_MODE && typeof gResource == "undefined")
return null;
return gResource;
},
_microsummaries: null,
get _mode() {
if ("gArg" in window)
return ADD_BOOKMARK_MODE;
else if ("gProperties" in window)
return EDIT_BOOKMARK_MODE;
return null;
},
/*
* Whether or not the microsummary picker is enabled for this bookmark.
* The picker is enabled for regular pages. It's disabled for livemarks,
* separators, folders, or when bookmarking multiple tabs.
*
* @returns boolean true if the picker is enabled; false otherwise
*
*/
get enabled() {
if (this._mode == ADD_BOOKMARK_MODE) {
// If we're adding a bookmark, we only have to worry about livemarks
// and bookmarking multiple tabs.
if ("feedURL" in gArg || gArg.bBookmarkAllTabs)
return false;
}
else if (this._mode == EDIT_BOOKMARK_MODE) {
// If we're modifying a bookmark, it could be a livemark, separator,
// folder, or regular page. The picker is only enabled for regular pages.
var isLivemark = BookmarksUtils.resolveType(gResource) == "Livemark";
var isSeparator = BookmarksUtils.resolveType(gResource) == "BookmarkSeparator";
var isContainer = RDFCU.IsContainer(BMDS, gResource);
if (isLivemark || isSeparator || isContainer)
return false;
}
else {
// We should never get to this point, since we're only being used
// in the Add Bookmark and Bookmark Properties dialogs, but if we're here
// for some reason, be conservative and assume the picker is disabled.
return false;
}
// We haven't found a reason to disable the picker, so say it's enabled.
return true;
},
init: function MSP_init() {
this._microsummaries = this._mss.getMicrosummaries(this._pageURI, this._bookmarkID);
this._microsummaries.addObserver(this._observer);
this.rebuild();
},
destroy: function MSP_destroy() {
this._microsummaries.removeObserver(this._observer);
},
rebuild: function MSP_rebuild() {
var microsummaryMenuList = document.getElementById("microsummaryMenuList");
var microsummaryMenuPopup = document.getElementById("microsummaryMenuPopup");
// Remove old items from the menu, except the first item, which represents
// "don't show a microsummary; show the page title instead".
while (microsummaryMenuPopup.childNodes.length > 1)
microsummaryMenuPopup.removeChild(microsummaryMenuPopup.lastChild);
var enumerator = this._microsummaries.Enumerate();
while (enumerator.hasMoreElements()) {
var microsummary = enumerator.getNext().QueryInterface(Ci.nsIMicrosummary);
var menuItem = document.createElement("menuitem");
// Store a reference to the microsummary in the menu item, so we know
// which microsummary this menu item represents when it's time to save
// changes to the datastore.
menuItem.microsummary = microsummary;
// Content may have to be generated asynchronously; we don't necessarily
// have it now. If we do, great; otherwise, fall back to the generator
// name, then the URI, and we trigger a microsummary content update.
// Once the update completes, the microsummary will notify our observer
// to rebuild the menu.
// XXX Instead of just showing the generator name or (heaven forbid)
// its URI when we don't have content, we should tell the user that we're
// loading the microsummary, perhaps with some throbbing to let her know
// it's in progress.
if (microsummary.content != null)
menuItem.setAttribute("label", microsummary.content);
else {
menuItem.setAttribute("label", microsummary.generator ? microsummary.generator.name
: microsummary.generatorURI.spec);
microsummary.update();
}
microsummaryMenuPopup.appendChild(menuItem);
// Select the item if this is the current microsummary for the bookmark.
if (this._bookmarkID && this._mss.isMicrosummary(this._bookmarkID, microsummary))
microsummaryMenuList.selectedItem = menuItem;
}
},
_observer: {
interfaces: [Ci.nsIMicrosummaryObserver, Ci.nsISupports],
QueryInterface: function (iid) {
//if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
if (!iid.equals(Ci.nsIMicrosummaryObserver) &&
!iid.equals(Ci.nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
onContentLoaded: function(microsummary) {
MicrosummaryPicker.rebuild();
},
onElementAppended: function(microsummary) {
MicrosummaryPicker.rebuild();
}
},
commit: function MSP_commit() {
var changed = false;
var menuList = document.getElementById("microsummaryMenuList");
// Something should always be selected in the microsummary menu,
// but if nothing is selected, then conservatively assume we should
// just display the bookmark title.
if (menuList.selectedIndex == -1)
menuList.selectedIndex = 0;
// This will set microsummary == undefined if the user selected
// the "don't display a microsummary" item.
var newMicrosummary = menuList.selectedItem.microsummary;
if (newMicrosummary == null && this._mss.hasMicrosummary(this._bookmarkID)) {
this._mss.removeMicrosummary(this._bookmarkID);
changed = true;
}
else if (newMicrosummary != null
&& !this._mss.isMicrosummary(this._bookmarkID, newMicrosummary)) {
this._mss.setMicrosummary(this._bookmarkID, newMicrosummary);
changed = true;
}
return changed;
}
};
function debug(str) {
dump(str + "\n");
}

Просмотреть файл

@ -51,3 +51,4 @@ browser.jar:
* content/browser/bookmarks/bookmarksManager.js (content/bookmarksManager.js)
* content/browser/bookmarks/bookmarksPanel.xul (content/bookmarksPanel.xul)
* content/browser/bookmarks/bookmarksPanel.js (content/bookmarksPanel.js)
* content/browser/bookmarks/microsummaryPicker.js (content/microsummaryPicker.js)

Просмотреть файл

@ -29,6 +29,7 @@
* Jan Varga <varga@nixcorp.com>
* Benjamin Smedberg <bsmedberg@covad.net>
* Vladimir Vukicevic <vladimir@pobox.com>
* 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
@ -118,6 +119,9 @@ nsIRDFResource *kNC_PostData;
nsIRDFResource *kNC_Livemark;
nsIRDFResource *kNC_LivemarkLock;
nsIRDFResource *kNC_LivemarkExpiration;
nsIRDFResource *kNC_MicsumGenURI;
nsIRDFResource *kNC_MicsumExpiration;
nsIRDFResource *kNC_GeneratedTitle;
nsIRDFResource *kRDF_type;
nsIRDFResource *kRDF_instanceOf;
nsIRDFResource *kRDF_nextVal;
@ -276,6 +280,12 @@ bm_AddRefGlobals()
&kNC_LivemarkLock);
gRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "LivemarkExpiration"),
&kNC_LivemarkExpiration);
gRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "MicsumGenURI"),
&kNC_MicsumGenURI);
gRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "MicsumExpiration"),
&kNC_MicsumExpiration);
gRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "GeneratedTitle"),
&kNC_GeneratedTitle);
gRDF->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
&kRDF_type);
gRDF->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
@ -393,6 +403,9 @@ bm_ReleaseGlobals()
NS_IF_RELEASE(kNC_Livemark);
NS_IF_RELEASE(kNC_LivemarkLock);
NS_IF_RELEASE(kNC_LivemarkExpiration);
NS_IF_RELEASE(kNC_MicsumGenURI);
NS_IF_RELEASE(kNC_MicsumExpiration);
NS_IF_RELEASE(kNC_GeneratedTitle);
NS_IF_RELEASE(kRDF_type);
NS_IF_RELEASE(kRDF_instanceOf);
NS_IF_RELEASE(kRDF_nextVal);
@ -626,6 +639,9 @@ static const char kLastModifiedEquals[] = "LAST_MODIFIED=\"";
static const char kLastCharsetEquals[] = "LAST_CHARSET=\"";
static const char kShortcutURLEquals[] = "SHORTCUTURL=\"";
static const char kFeedURLEquals[] = "FEEDURL=\"";
static const char kMicsumGenURIEquals[] = "MICSUM_GEN_URI=\"";
static const char kMicsumExpirationEquals[]= "MICSUM_EXPIRATION=\"";
static const char kGeneratedTitleEquals[] = "GENERATED_TITLE=\"";
static const char kIconEquals[] = "ICON=\"";
static const char kWebPanelEquals[] = "WEB_PANEL=\"";
static const char kPostDataEquals[] = "POST_DATA=\"";
@ -1130,7 +1146,10 @@ BookmarkParser::gBookmarkFieldTable[] =
{ kLastVisitEquals, WEB_NAMESPACE_URI "LastVisitDate", nsnull, BookmarkParser::ParseDate, nsnull },
{ kLastModifiedEquals, WEB_NAMESPACE_URI "LastModifiedDate", nsnull, BookmarkParser::ParseDate, nsnull },
{ kShortcutURLEquals, NC_NAMESPACE_URI "ShortcutURL", nsnull, BookmarkParser::ParseLiteral, nsnull },
{ kFeedURLEquals, NC_NAMESPACE_URI "FeedURL", nsnull, BookmarkParser::ParseLiteral, nsnull },
{ kFeedURLEquals, NC_NAMESPACE_URI "FeedURL", nsnull, BookmarkParser::ParseLiteral, nsnull },
{ kMicsumGenURIEquals, NC_NAMESPACE_URI "MicsumGenURI", nsnull, BookmarkParser::ParseLiteral, nsnull },
{ kMicsumExpirationEquals,NC_NAMESPACE_URI "MicsumExpiration", nsnull, BookmarkParser::ParseLiteral, nsnull },
{ kGeneratedTitleEquals, NC_NAMESPACE_URI "GeneratedTitle", nsnull, BookmarkParser::ParseLiteral, nsnull },
{ kIconEquals, NC_NAMESPACE_URI "Icon", nsnull, BookmarkParser::ParseLiteral, nsnull },
{ kWebPanelEquals, NC_NAMESPACE_URI "WebPanel", nsnull, BookmarkParser::ParseLiteral, nsnull },
{ kPostDataEquals, NC_NAMESPACE_URI "PostData", nsnull, BookmarkParser::ParseLiteral, nsnull },
@ -5011,6 +5030,15 @@ nsBookmarksService::WriteBookmarksContainer(nsIRDFDataSource *ds,
rv |= WriteBookmarkProperties(ds, strm, child, kNC_FeedURL, kFeedURLEquals, PR_FALSE);
}
// output microsummary generator URI
rv |= WriteBookmarkProperties(ds, strm, child, kNC_MicsumGenURI, kMicsumGenURIEquals, PR_FALSE);
// output microsummary expiration
rv |= WriteBookmarkProperties(ds, strm, child, kNC_MicsumExpiration, kMicsumExpirationEquals, PR_FALSE);
// output generated title
rv |= WriteBookmarkProperties(ds, strm, child, kNC_GeneratedTitle, kGeneratedTitleEquals, PR_FALSE);
// output ID and NAME
rv |= WriteBookmarkIdAndName(ds, strm, child);
@ -5288,6 +5316,9 @@ nsBookmarksService::CanAccept(nsIRDFResource* aSource,
(aProperty == kNC_Livemark) ||
(aProperty == kNC_LivemarkLock) ||
(aProperty == kNC_LivemarkExpiration) ||
(aProperty == kNC_MicsumGenURI) ||
(aProperty == kNC_MicsumExpiration) ||
(aProperty == kNC_GeneratedTitle) ||
(aProperty == kWEB_LastModifiedDate) ||
(aProperty == kWEB_LastVisitDate) ||
(aProperty == kNC_BookmarkAddDate) ||

Просмотреть файл

@ -0,0 +1,46 @@
# ***** 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 Microsummarizer.
#
# The Initial Developer of the Original Code is Mozilla.
# Portions created by the Initial Developer are Copyright (C) 2006
# 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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,49 @@
# ***** 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 Microsummarizer.
#
# The Initial Developer of the Original Code is Mozilla.
# Portions created by the Initial Developer are Copyright (C) 2006
# 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = microsummaries
XPIDL_MODULE = microsummaries
XPIDLSRCS = nsIMicrosummaryService.idl
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,253 @@
#include "nsISupports.idl"
interface nsIDOMNode;
interface nsIURI;
interface nsISimpleEnumerator;
interface nsIMicrosummary;
[scriptable, uuid(cb284a83-1ca5-4000-9841-ce345ce84915)]
interface nsIMicrosummaryObserver : nsISupports
{
/**
* Called when an observed microsummary updates its content.
* Since an observer might watch multiple microsummaries at the same time,
* the microsummary whose content has been updated gets passed
* to this handler.
* XXX Should this be onContentUpdated?
*
* @param microsummary
* the microsummary whose content has just been updated
*
*/
void onContentLoaded(in nsIMicrosummary microsummary);
/**
* Called when an element is appended to a microsummary set.
* XXX Should this be in a separate nsICollectionObserver interface?
*
* @param microsummary
* the microsummary that has just been appended to the set
*
*/
void onElementAppended(in nsIMicrosummary microsummary);
};
[scriptable, uuid(ff3eba15-81de-4c24-bfcf-c8180dc3c00a)]
interface nsIMicrosummaryGenerator : nsISupports
{
// An arbitrary descriptive name for this microsummary generator.
readonly attribute AUTF8String name;
// The canonical location and unique identifier of the generator.
// It tells us where the generator comes from and where to go for updates.
// For generators referenced by web pages via <link> tags, this URI
// is the one specified by the tag. For generators installed by users,
// this URI is the remote location from which we installed the generator.
// For generators bundled with the browser, this URI is a reference
// to the latest version of this generator available on Mozilla Add-ons.
readonly attribute nsIURI uri;
// Whether or not this generator needs page content to generate
// a microsummary. Microsummaries generated by XSLT templates need page
// content, while those which represent the actual microsummary content
// do not.
readonly attribute boolean needsPageContent;
/**
* Generate a microsummary by processing the generator template
* against the page content. If a generator doesn't need content,
* pass null as the parameter to this method.
*
* XXX In the future, this should support returning rich text content,
* so perhaps we should make it return a DOM node now and have the caller
* convert that to text if it doesn't support rich content.
*
* @param pageContent
* the content of the page being summarized
* @returns the text result of processing the template
*
*/
AString generateMicrosummary(in nsIDOMNode aPageContent);
};
[scriptable, uuid(f9d1a73c-e147-46f3-ba61-4f0bd33f5d47)]
interface nsIMicrosummary : nsISupports
{
// the URI of the page being summarized
readonly attribute nsIURI pageURI;
// The URI of the generator that generates this microsummary.
readonly attribute nsIURI generatorURI;
// The generator that generates this microsummary.
// Since generators can be remote resources, this may not always be available.
attribute nsIMicrosummaryGenerator generator;
// The content of the microsummary.
// Since generators and pages can be remote resources, and we need them
// to generate the content, this may not always be available.
readonly attribute AString content;
/**
* Add a microsummary observer to this microsummary.
*
* @param observer
* the microsummary observer to add
*
*/
void addObserver(in nsIMicrosummaryObserver observer);
/**
* Remove a microsummary observer from this microsummary.
*
* @param observer
* the microsummary observer to remove
*
*/
void removeObserver(in nsIMicrosummaryObserver observer);
/**
* Update the microsummary, first loading its generator and page content
* as necessary. If you want know when a microsummary finishes updating,
* add an observer before calling this method.
*
*/
void update();
};
[scriptable, uuid(7111e88d-fecd-4b17-b7a9-1fa74e23153f)]
interface nsIMicrosummarySet : nsISupports
{
/**
* Add a microsummary observer to this microsummary set. Adding an observer
* to a set is the equivalent of adding it to each constituent microsummary.
*
* @param observer
* the microsummary observer to add
*
*/
void addObserver(in nsIMicrosummaryObserver observer);
/**
* Remove a microsummary observer from this microsummary.
*
* @param observer
* the microsummary observer to remove
*
*/
void removeObserver(in nsIMicrosummaryObserver observer);
/**
* Retrieve a enumerator of microsummaries in the set.
*
* @returns an enumerator of nsIMicrosummary objects
*
*/
nsISimpleEnumerator Enumerate();
};
[scriptable, uuid(c5e9c390-beb0-4eb4-90ab-529efc817632)]
interface nsIMicrosummaryService : nsISupports
{
/**
* Install the microsummary generator from the resource at the supplied URI.
* Callable by content via the addMicrosummaryGenerator() sidebar method.
*
* @param generatorURI
* the URI of the resource providing the generator
*
*/
void addGenerator(in nsIURI generatorURI);
/**
* Get the set of microsummaries available for a given page. The set
* might change after this method returns, since this method will trigger
* an asynchronous load of the page in question (if it isn't already loaded)
* to see if it references any page-specific microsummaries.
*
* If the caller passes a bookmark ID, and one of the microsummaries
* is the current one for the bookmark, this method will retrieve content
* from the datastore for that microsummary, which is useful when callers
* want to display a list of microsummaries for a page that isn't loaded,
* and they want to display the actual content of the selected microsummary
* immediately (rather than after the content is asynchronously loaded).
*
* @param pageURI
* the URI of the page for which to retrieve available microsummaries
*
* @param bookmarkID (optional)
* the ID of the bookmark for which this method is being called
*
* @returns an nsIMicrosummarySet of nsIMicrosummaries for the given page
*
*/
nsIMicrosummarySet getMicrosummaries(in nsIURI pageURI,
in nsISupports bookmarkID);
/**
* Get the current microsummary for the given bookmark.
*
* @param bookmarkID
* the bookmark for which to get the current microsummary
*
* @returns the current microsummary for the bookmark, or null
* if the bookmark does not have a current microsummary
*
*/
nsIMicrosummary getMicrosummary(in nsISupports bookmarkID);
/**
* Set the current microsummary for the given bookmark.
*
* @param bookmarkID
* the bookmark for which to set the current microsummary
*
* @param microsummary
* the microsummary to set as the current one
*
*/
void setMicrosummary(in nsISupports bookmarkID,
in nsIMicrosummary microsummary);
/**
* Remove the current microsummary for the given bookmark.
*
* @param bookmarkID
* the bookmark for which to remove the current microsummary
*
*/
void removeMicrosummary(in nsISupports bookmarkID);
/**
* Whether or not the given bookmark has a current microsummary.
*
* @param bookmarkID
* the bookmark for which to set the current microsummary
*
* @returns a boolean representing whether or not the given bookmark
* has a current microsummary
*
*/
boolean hasMicrosummary(in nsISupports bookmarkID);
/**
* Whether or not the given microsummary is the current microsummary
* for the given bookmark.
*
* @param bookmarkID
* the bookmark to check
*
* @param microsummary
* the microsummary to check
*
* @returns whether or not the microsummary is the current one
* for the bookmark
*
*/
boolean isMicrosummary(in nsISupports bookmarkID,
in nsIMicrosummary microsummary);
};

Просмотреть файл

@ -0,0 +1,51 @@
# ***** 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 Microsummarizer.
#
# The Initial Developer of the Original Code is Mozilla.
# Portions created by the Initial Developer are Copyright (C) 2006
# 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = microsummaries
EXTRA_COMPONENTS = nsMicrosummaryService.js
include $(topsrcdir)/config/rules.mk
nsMicrosummaryService.js: nsMicrosummaryService.js.in
$(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $^ > $@

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -102,8 +102,20 @@ var BookmarkPropertiesPanel = {
return this.__livemarks;
},
/**
* The Microsummary Service for displaying microsummaries.
*/
__mss: null,
get _mss() {
if (!this.__mss)
this.__mss = Cc["@mozilla.org/microsummary/service;1"].
getService(Ci.nsIMicrosummaryService);
return this.__mss;
},
_bookmarkURI: null,
_bookmarkTitle: "",
_microsummaries: null,
_dialogWindow: null,
_parentWindow: null,
_controller: null,
@ -173,7 +185,7 @@ var BookmarkPropertiesPanel = {
},
/**
* Returns true if the the shortcut field is visible in this
* Returns true if the shortcut field is visible in this
* variant of the dialog.
*/
_isShortcutVisible: function BPP__isShortcutVisible() {
@ -202,6 +214,22 @@ var BookmarkPropertiesPanel = {
}
},
/**
* Returns true if the microsummary field is visible in this variant
* of the dialog.
*/
_isMicrosummaryVisible: function BPP__isMicrosummaryVisible() {
switch(this._variant) {
case this.EDIT_FOLDER_VARIANT:
case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
case this.ADD_LIVEMARK_VARIANT:
case this.EDIT_LIVEMARK_VARIANT:
return false;
default:
return true;
}
},
/**
* Returns true if bookmark deletion is possible from the current
* variant of the dialog.
@ -501,6 +529,18 @@ var BookmarkPropertiesPanel = {
this._hide("shortcutRow");
}
if (this._isMicrosummaryVisible()) {
this._microsummaries = this._mss.getMicrosummaries(this._bookmarkURI,
this._bookmarkURI);
this._microsummaries.addObserver(this._microsummaryObserver);
this._rebuildMicrosummaryPicker();
}
else {
var microsummaryRow =
this._dialogWindow.document.getElementById("microsummaryRow");
microsummaryRow.setAttribute("hidden", "true");
}
if (this._isFolderEditable()) {
this._folderTree.selectFolders([this._bms.bookmarksRoot]);
}
@ -509,6 +549,71 @@ var BookmarkPropertiesPanel = {
}
},
_rebuildMicrosummaryPicker: function BPP__rebuildMicrosummaryPicker() {
var microsummaryMenuList = document.getElementById("microsummaryMenuList");
var microsummaryMenuPopup = document.getElementById("microsummaryMenuPopup");
// Remove old items from the menu, except the first item, which represents
// "don't show a microsummary; show the page title instead".
while (microsummaryMenuPopup.childNodes.length > 1)
microsummaryMenuPopup.removeChild(microsummaryMenuPopup.lastChild);
var enumerator = this._microsummaries.Enumerate();
while (enumerator.hasMoreElements()) {
var microsummary = enumerator.getNext().QueryInterface(Ci.nsIMicrosummary);
var menuItem = document.createElement("menuitem");
// Store a reference to the microsummary in the menu item, so we know
// which microsummary this menu item represents when it's time to save
// changes to the datastore.
menuItem.microsummary = microsummary;
// Content may have to be generated asynchronously; we don't necessarily
// have it now. If we do, great; otherwise, fall back to the generator
// name, then the URI, and we trigger a microsummary content update.
// Once the update completes, the microsummary will notify our observer
// to rebuild the menu.
// XXX Instead of just showing the generator name or (heaven forbid)
// its URI when we don't have content, we should tell the user that we're
// loading the microsummary, perhaps with some throbbing to let her know
// it's in progress.
if (microsummary.content != null)
menuItem.setAttribute("label", microsummary.content);
else {
menuItem.setAttribute("label", microsummary.generator ? microsummary.generator.name
: microsummary.generatorURI.spec);
microsummary.update();
}
microsummaryMenuPopup.appendChild(menuItem);
// Select the item if this is the current microsummary for the bookmark.
if (this._mss.isMicrosummary(this._bookmarkURI, microsummary))
microsummaryMenuList.selectedItem = menuItem;
}
},
_microsummaryObserver: {
interfaces: [Ci.nsIMicrosummaryObserver, Ci.nsISupports],
QueryInterface: function (iid) {
//if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
if (!iid.equals(Ci.nsIMicrosummaryObserver) &&
!iid.equals(Ci.nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
onContentLoaded: function(microsummary) {
BookmarkPropertiesPanel._rebuildMicrosummaryPicker();
},
onElementAppended: function(microsummary) {
BookmarkPropertiesPanel._rebuildMicrosummaryPicker();
}
},
/**
* Makes a URI from a spec.
* @param spec
@ -542,6 +647,8 @@ var BookmarkPropertiesPanel = {
* in the Bookmark Properties dialog.
*/
dialogDone: function BPP_dialogDone() {
if (this._isMicrosummaryVisible())
this._microsummaries.removeObserver(this._microsummaryObserver);
this._saveChanges();
this._hideBookmarkProperties();
},
@ -718,6 +825,33 @@ var BookmarkPropertiesPanel = {
this._controller.changeBookmarkURI(this._bookmarkURI, newURI);
}
if (this._isMicrosummaryVisible()) {
var menuList = document.getElementById("microsummaryMenuList");
// Something should always be selected in the microsummary menu,
// but if nothing is selected, then conservatively assume we should
// just display the bookmark title.
if (menuList.selectedIndex == -1)
menuList.selectedIndex = 0;
// This will set microsummary == undefined if the user selected
// the "don't display a microsummary" item.
var newMicrosummary = menuList.selectedItem.microsummary;
// Only add a microsummary update to the transaction if the microsummary
// has actually changed, i.e. the user selected no microsummary,
// but the bookmark previously had one, or the user selected a microsummary
// which is not the one the bookmark previously had.
if ((newMicrosummary == null &&
this._mss.hasMicrosummary(this._bookmarkURI)) ||
(newMicrosummary != null &&
!this._mss.isMicrosummary(this._bookmarkURI, newMicrosummary))) {
transactions.push(
new PlacesEditBookmarkMicrosummaryTransaction(this._bookmarkURI,
newMicrosummary));
}
}
// If we have any changes to perform, do them via the
// transaction manager in the PlacesController so they can be undone.
if (transactions.length > 0) {

Просмотреть файл

@ -79,6 +79,19 @@
</vbox>
<textbox id="editShortcutBox" value=""/>
</row>
<row id="microsummaryRow">
<vbox align="end">
<hbox align="center" flex="1">
<label value="&bookmark.property.microsummary;" align="middle"/>
</hbox>
</vbox>
<menulist id="microsummaryMenuList">
<menupopup id="microsummaryMenuPopup">
<menuitem label="&bookmark.property.microsummary.none;"
selected="true"/>
</menupopup>
</menulist>
</row>
<row id="folderRow" flex="1" style="min-height: 100px;">
<vbox align="end">
<hbox align="start" flex="1">

Просмотреть файл

@ -20,6 +20,7 @@
*
* Contributor(s):
* Ben Goodger <beng@google.com>
* 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
@ -2588,3 +2589,35 @@ PlacesEditLivemarkFeedURITransaction.prototype = {
this.livemarks.reloadLivemarkFolder(this._folderId);
}
};
/**
* Edit a bookmark's microsummary.
*/
function PlacesEditBookmarkMicrosummaryTransaction(uri, newMicrosummary) {
this._uri = uri;
this._newMicrosummary = newMicrosummary;
this._oldMicrosummary = null;
this.redoTransaction = this.doTransaction;
}
PlacesEditBookmarkMicrosummaryTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
mss: Cc["@mozilla.org/microsummary/service;1"].
getService(Ci.nsIMicrosummaryService),
doTransaction: function PEBMT_doTransaction() {
this._oldMicrosummary = this.mss.getMicrosummary(this._uri);
if (this._newMicrosummary)
this.mss.setMicrosummary(this._uri, this._newMicrosummary);
else
this.mss.removeMicrosummary(this._uri);
},
undoTransaction: function PEBMT_undoTransaction() {
if (this._oldMicrosummary)
this.mss.setMicrosummary(this._uri, this._oldMicrosummary);
else
this.mss.removeMicrosummary(this._uri);
}
};

Просмотреть файл

@ -22,6 +22,7 @@
# Contributor(s):
# Annie Sullivan <annie.sullivan@gmail.com>
# Ben Goodger <beng@google.com>
# 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
@ -163,7 +164,16 @@
<getter><![CDATA[
if (!this.__generatedTitles) {
this.__generatedTitles = {};
var pages = this._anno.getPagesWithAnnotation("bookmarks/generatedTitle", {});
// This try/catch block is a temporary workaround for bug 336194.
var pages;
try {
pages = this._anno.getPagesWithAnnotation("bookmarks/generatedTitle", {});
}
catch(e) {
pages = [];
}
// XXX It'd be faster to grab the annotations in a single query
// instead of querying separately for each one, but the annotation
// service provides no mechanism for doing so.
@ -453,12 +463,16 @@
this.doRebuild();
},
onItemAdded: function TB_O_onItemAdded(bookmark, folder, index) {
if (folder == this._self._bms.toolbarRoot)
if (folder == this._self._bms.toolbarRoot) {
this._self._currentURIs[bookmark.spec] = true;
this._numBatches ? this._batchedOperation = true : this.doRebuild();
}
},
onItemRemoved: function TB_O_onItemRemoved(bookmark, folder, index) {
if (folder == this._self._bms.toolbarRoot)
if (folder == this._self._bms.toolbarRoot) {
delete this._self._currentURIs[bookmark.spec];
this._numBatches ? this._batchedOperation = true : this.doRebuild();
}
},
onItemChanged: function TB_O_onItemChanged(bookmark, property, value) {
this._numBatches ? this._batchedOperation = true : this.doRebuild();
@ -818,9 +832,6 @@
if (!this._observers[annoName])
return false;
if (!this._self._currentURIs[uri.spec])
return false;
return true;
},

Просмотреть файл

@ -74,6 +74,7 @@ REQUIRES = xpcom \
nkcache \
widget \
url-classifier \
microsummaries \
$(NULL)
LOCAL_INCLUDES = -I$(srcdir)/../../build

Просмотреть файл

@ -537,22 +537,25 @@ function getSanitizedFile(aName) {
/**
* Removes all characters not in the "chars" string from aName.
*
* @returns a sanitized name to be used as a filename, or a random name if a
* sanitized name cannot be obtained (if aName contains no valid
* characters).
* @returns a sanitized name to be used as a filename, or a random name
* if a sanitized name cannot be obtained (if aName contains
* no valid characters).
*/
function sanitizeName(aName) {
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
var name = aName.toLowerCase()
.split("").filter(function (el) {
return chars.indexOf(el) != -1;
}).join("");
const chars = "-abcdefghijklmnopqrstuvwxyz0123456789";
var name = aName.toLowerCase();
name = name.replace(/ /g, "-");
name = name.split("").filter(function (el) {
return chars.indexOf(el) != -1;
}).join("");
if (!name) {
// Our input had no valid characters - use a random name
var cl = chars.length;
for (var i = 0; i < 8; ++i)
name += chars.charAt(Math.round(Math.random() * cl));
name += chars.charAt(Math.round(Math.random() * (chars.length - 1)));
}
return name;
}

Просмотреть файл

@ -24,6 +24,7 @@
* Robert John Churchill <rjc@netscape.com>
* David Hyatt <hyatt@mozilla.org>
* Christopher A. Aillon <christopher@aillon.com>
* 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
@ -154,9 +155,11 @@ function (engineURL, iconURL, suggestedTitle, suggestedCategory)
if (stringBundle) {
titleMessage = stringBundle.GetStringFromName("addEngineConfirmTitle");
dialogMessage = stringBundle.GetStringFromName("addEngineConfirmMessage");
// Replace # with newlines before replacing %url% with the URL
// so that we don't unintentionally hork a # in the URL itself.
dialogMessage = dialogMessage.replace(/#/g, "\n");
dialogMessage = dialogMessage.replace(/%title%/, suggestedTitle);
dialogMessage = dialogMessage.replace(/%url%/, engineURL);
dialogMessage = dialogMessage.replace(/#/g, "\n");
}
}
catch (e) {
@ -177,6 +180,44 @@ function (engineURL, iconURL, suggestedTitle, suggestedCategory)
searchService.addEngine(engineURL, typeText, iconURL);
}
nsSidebar.prototype.addMicrosummaryGenerator =
function (generatorURL)
{
debug("addMicrosummaryGenerator(" + generatorURL + ")");
var titleMessage, dialogMessage;
try {
var stringBundle = srGetStrBundle("chrome://browser/locale/sidebar/sidebar.properties");
if (stringBundle) {
titleMessage = stringBundle.GetStringFromName("addMicsumGenConfirmTitle");
dialogMessage = stringBundle.GetStringFromName("addMicsumGenConfirmMessage");
// Replace # with newlines before replacing %url% with the URL
// so that we don't unintentionally hork a # in the URL itself.
dialogMessage = dialogMessage.replace(/#/g, "\n");
dialogMessage = dialogMessage.replace(/%url%/, generatorURL);
}
}
catch (e) {
titleMessage = "Add Microsummary Generator";
dialogMessage = "Add the following microsummary generator?\n";
dialogMessage += "\nSource: " + generatorURL;
}
var rv = this.promptService.confirm(null, titleMessage, dialogMessage);
if (!rv)
return;
var ioService = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
var generatorURI = ioService.newURI(generatorURL, null, null);
var microsummaryService = Components.classes["@mozilla.org/microsummary/service;1"].
getService(Components.interfaces.nsIMicrosummaryService);
if (microsummaryService)
microsummaryService.addGenerator(generatorURI);
}
// property of nsIClassInfo
nsSidebar.prototype.flags = nsIClassInfo.DOM_OBJECT;

Просмотреть файл

@ -115,6 +115,7 @@ bin/components/layout_xul_tree.xpt
bin/components/layout_xul.xpt
bin/components/locale.xpt
bin/components/lwbrk.xpt
bin/components/microsummaries.xpt
bin/components/migration.xpt
bin/components/mimetype.xpt
bin/components/mozbrwsr.xpt
@ -183,6 +184,7 @@ bin/components/WebContentConverter.js
bin/components/nsBrowserContentHandler.js
bin/components/nsBrowserGlue.js
bin/components/nsSetDefaultBrowser.js
bin/components/nsMicrosummaryService.js
bin/components/nsSearchService.js
bin/components/jsconsole-clhandler.js
bin/components/nsCloseAllWindows.js

Просмотреть файл

@ -121,6 +121,7 @@ bin\components\layout_xul.xpt
bin\components\layout_xul_tree.xpt
bin\components\locale.xpt
bin\components\lwbrk.xpt
bin\components\microsummaries.xpt
bin\components\migration.xpt
bin\components\mimetype.xpt
bin\components\mozbrwsr.xpt
@ -204,6 +205,7 @@ bin\components\nsSidebar.js
bin\components\nsXmlRpcClient.js
bin\components\nsExtensionManager.js
bin\components\nsUpdateService.js
bin\components\nsMicrosummaryService.js
bin\components\nsPostUpdateWin.js
bin\components\pluginGlue.js
bin\components\extensions.xpt

Просмотреть файл

@ -142,6 +142,21 @@ else
$(SYSINSTALL) $(IFLAGS1) $(SEARCH_SHERLOCK_FILES) $(DESTDIR)$(mozappdir)/searchplugins
endif
MICROSUMMARY_GENERATORS = $(shell cat $(LOCALE_SRCDIR)/microsummary-generators/list.txt)
MICROSUMMARY_GENERATOR_PREFIX = $(addprefix $(LOCALE_SRCDIR)/microsummary-generators/,$(MICROSUMMARY_GENERATORS))
libs::
ifneq (,$(strip $(MICROSUMMARY_GENERATORS)))
$(addsuffix .xml,$(MICROSUMMARY_GENERATOR_PREFIX))
$(INSTALL) $^ $(FINAL_TARGET)/microsummary-generators
endif
install::
ifneq (,$(strip $(MICROSUMMARY_GENERATORS)))
$(addsuffix .xml,$(MICROSUMMARY_GENERATOR_PREFIX))
$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/microsummary-generators
endif
libs-%:
@$(MAKE) -C ../../toolkit/locales libs-$*
@$(MAKE) -C ../../extensions/reporter/locales libs AB_CD=$* XPI_NAME=locale-$*
@ -224,6 +239,7 @@ repackage-zip: $(ZIP_IN)
$(STAGEDIST)/chrome/en-US.manifest \
$(STAGEDIST)/defaults/pref/firefox-l10n.js
$(RM) -r $(STAGEDIST)/searchplugins \
$(RM) -r $(STAGEDIST)/microsummary-generators \
$(STAGEDIST)/defaults/profile \
$(STAGEDIST)/chrome/en-US
$(RM) -rf $(DIST)/xpi-stage/locale-$(AB_CD)

Просмотреть файл

@ -4,6 +4,9 @@
<!ENTITY name.accesskey "N">
<!ENTITY keyword.label "Keyword:">
<!ENTITY keyword.accesskey "K">
<!ENTITY microsummary.label "Summary:">
<!ENTITY microsummary.none.label "Don't Display a Summary">
<!ENTITY microsummary.accesskey "S">
<!ENTITY url.label "Location:">
<!ENTITY url.accesskey "L">
<!ENTITY button.createin.label "Create In &gt;&gt;">

Просмотреть файл

@ -23,6 +23,7 @@
# Stephen Lamm <slamm@netscape.com>
# Robert John Churchill <rjc@netscape.com>
# Ben Goodger <ben@netscape.com>
# 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
@ -46,5 +47,7 @@
<!ENTITY bookmarks.location.label "Location:">
<!ENTITY bookmarks.feedurl.label "Feed Location:">
<!ENTITY bookmarks.shortcut.label "Keyword:">
<!ENTITY bookmarks.micsum.label "Summary:">
<!ENTITY bookmarks.micsum.none.label "Don't Display a Summary">
<!ENTITY bookmarks.description.label "Description:">
<!ENTITY bookmarks.webpanels.label "Load this bookmark in the sidebar">

Просмотреть файл

@ -6,6 +6,10 @@
"Name">
<!ENTITY bookmark.property.shortcut
"Shortcut">
<!ENTITY bookmark.property.microsummary
"Summary">
<!ENTITY bookmark.property.microsummary.none
"Don't Display a Summary">
<!ENTITY bookmark.property.folders
"Folders">
<!ENTITY bookmark.property.folder_list

Просмотреть файл

@ -1,2 +1,4 @@
addEngineConfirmTitle=Add Search Engine
addEngineConfirmMessage=Add the following search engine to the Search Bar?##Name: %title%#Source: %url%
addMicsumGenConfirmTitle=Add Microsummary Generator
addMicsumGenConfirmMessage=Add the following microsummary generator?##Source: %url%

Просмотреть файл

Просмотреть файл

@ -137,6 +137,10 @@ toolbarbutton.bookmark-item {
border: none !important;
}
toolbarbutton.bookmark-item-microsummarized {
max-width: 20em;
}
.bookmark-item > .toolbarbutton-icon {
margin: 0px;
display: none !important;

Просмотреть файл

@ -74,6 +74,10 @@ toolbarbutton.bookmark-item {
padding: 2px 3px;
}
toolbarbutton.bookmark-item-microsummarized {
max-width: 20em;
}
toolbarbutton.bookmark-item:hover:active,
toolbarbutton.bookmark-item[open="true"] {
padding-top: 3px;

Просмотреть файл

@ -53,6 +53,7 @@ interface nsISidebar : nsISupports
in string aCustomizeURL);
void addSearchEngine(in string engineURL, in string iconURL,
in wstring suggestedTitle, in wstring suggestedCategory);
void addMicrosummaryGenerator(in string generatorURL);
};
%{ C++

Просмотреть файл

@ -76,6 +76,7 @@
#define NS_APP_CHROME_DIR "AChrom"
#define NS_APP_PLUGINS_DIR "APlugns" // Deprecated - use NS_APP_PLUGINS_DIR_LIST
#define NS_APP_SEARCH_DIR "SrchPlugns"
#define NS_APP_MICROSUMMARY_DIR "MicsumGens"
#define NS_APP_CHROME_DIR_LIST "AChromDL"
#define NS_APP_PLUGINS_DIR_LIST "APluginsDL"
@ -102,6 +103,7 @@
#define NS_APP_USER_CHROME_DIR "UChrm"
#define NS_APP_USER_SEARCH_DIR "UsrSrchPlugns"
#define NS_APP_USER_MICROSUMMARY_DIR "UsrMicsumGens"
#define NS_APP_LOCALSTORE_50_FILE "LclSt"
#define NS_APP_HISTORY_50_FILE "UHist"

Просмотреть файл

@ -109,6 +109,7 @@
#define CHROME_DIR_NAME NS_LITERAL_CSTRING("Chrome")
#define PLUGINS_DIR_NAME NS_LITERAL_CSTRING("Plug-ins")
#define SEARCH_DIR_NAME NS_LITERAL_CSTRING("Search Plugins")
#define MICROSUMMARY_DIR_NAME NS_LITERAL_CSTRING("Microsummary Generators")
#else
#define DEFAULTS_DIR_NAME NS_LITERAL_CSTRING("defaults")
#define DEFAULTS_PREF_DIR_NAME NS_LITERAL_CSTRING("pref")
@ -117,6 +118,7 @@
#define CHROME_DIR_NAME NS_LITERAL_CSTRING("chrome")
#define PLUGINS_DIR_NAME NS_LITERAL_CSTRING("plugins")
#define SEARCH_DIR_NAME NS_LITERAL_CSTRING("searchplugins")
#define MICROSUMMARY_DIR_NAME NS_LITERAL_CSTRING("microsummary-generators")
#endif
//*****************************************************************************
@ -277,6 +279,18 @@ nsAppFileLocationProvider::GetFile(const char *prop, PRBool *persistent, nsIFile
if (NS_SUCCEEDED(rv))
rv = (*_retval)->AppendNative(SEARCH_DIR_NAME);
}
else if (nsCRT::strcmp(prop, NS_APP_MICROSUMMARY_DIR) == 0)
{
rv = CloneMozBinDirectory(getter_AddRefs(localFile));
if (NS_SUCCEEDED(rv))
rv = localFile->AppendRelativeNativePath(MICROSUMMARY_DIR_NAME);
}
else if (nsCRT::strcmp(prop, NS_APP_USER_MICROSUMMARY_DIR) == 0)
{
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, _retval);
if (NS_SUCCEEDED(rv))
rv = (*_retval)->AppendNative(MICROSUMMARY_DIR_NAME);
}
else if (nsCRT::strcmp(prop, NS_APP_INSTALL_CLEANUP_DIR) == 0)
{
// This is cloned so that embeddors will have a hook to override