333751 - land initial content converter patch for feed parsing, turned off. r=bsmedberg for configure bits, r=brettw for everything else... use --enable-feeds in .mozconfig to turn this on.

This commit is contained in:
beng%bengoodger.com 2006-04-27 00:24:12 +00:00
Родитель 27e45479f5
Коммит c2d6dd5251
24 изменённых файлов: 1787 добавлений и 139 удалений

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

@ -78,6 +78,9 @@ const BROWSER_ADD_BM_FEATURES = "centerscreen,chrome,dialog,resizable,modal";
const BROWSER_ADD_BM_FEATURES = "centerscreen,chrome,dialog,resizable,dependent";
#endif
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const TYPE_XUL = "application/vnd.mozilla.xul+xml";
var gBrowserGlue = Components.classes["@mozilla.org/browser/browserglue;1"]
.getService(nsCI.nsIBrowserGlue);
var gRDF = null;
@ -875,9 +878,6 @@ function prepareForStartup()
window.QueryInterface(nsCI.nsIDOMChromeWindow).browserDOMWindow =
new nsBrowserAccess();
window.browserContentListener =
new nsBrowserContentListener(window, gBrowser);
// set default character set if provided
if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) {
if (window.arguments[1].indexOf("charset=") != -1) {
@ -1145,7 +1145,6 @@ function BrowserShutdown()
.XULBrowserWindow = null;
window.QueryInterface(nsCI.nsIDOMChromeWindow).browserDOMWindow = null;
window.browserContentListener.close();
// Close the app core.
if (appCore)
appCore.close();
@ -3967,138 +3966,6 @@ function displaySecurityInfo()
BrowserPageInfo(null, "securityTab");
}
function nsBrowserContentListener(toplevelWindow, contentWindow)
{
// this one is not as easy as you would hope.
// need to convert toplevelWindow to an XPConnected object, instead
// of a DOM-based object, to be able to QI() it to nsIXULWindow
this.init(toplevelWindow, contentWindow);
}
/* implements nsIURIContentListener */
nsBrowserContentListener.prototype =
{
init: function(toplevelWindow, contentWindow)
{
const nsIWebBrowserChrome = Components.interfaces.nsIWebBrowserChrome;
this.toplevelWindow = toplevelWindow;
this.contentWindow = contentWindow;
// hook up the whole parent chain thing
var windowDocShell = this.convertWindowToDocShell(toplevelWindow);
if (windowDocShell) {
windowDocshell
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIURIContentListener)
.parentContentListener = this;
}
var registerWindow = false;
try {
var treeItem = contentWindow.docShell.QueryInterface(Components.interfaces.nsIDocShellTreeItem);
var treeOwner = treeItem.treeOwner;
var interfaceRequestor = treeOwner.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var webBrowserChrome = interfaceRequestor.getInterface(nsIWebBrowserChrome);
if (webBrowserChrome)
{
var chromeFlags = webBrowserChrome.chromeFlags;
var res = chromeFlags & nsIWebBrowserChrome.CHROME_ALL;
var res2 = chromeFlags & nsIWebBrowserChrome.CHROME_DEFAULT;
if ( res == nsIWebBrowserChrome.CHROME_ALL || res2 == nsIWebBrowserChrome.CHROME_DEFAULT)
{
registerWindow = true;
}
}
} catch (ex) {}
// register ourselves
if (registerWindow)
{
var uriLoader = Components.classes["@mozilla.org/uriloader;1"].getService(Components.interfaces.nsIURILoader);
uriLoader.registerContentListener(this);
}
},
close: function()
{
this.contentWindow = null;
var uriLoader = Components.classes["@mozilla.org/uriloader;1"].getService(Components.interfaces.nsIURILoader);
uriLoader.unRegisterContentListener(this);
},
QueryInterface: function(iid)
{
if (iid.equals(Components.interfaces.nsIURIContentListener) ||
iid.equals(Components.interfaces.nsISupportsWeakReference) ||
iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
onStartURIOpen: function(uri)
{
// ignore and don't abort
return false;
},
doContent: function(contentType, isContentPreferred, request, contentHandler)
{
// forward the doContent to our content area webshell
var docShell = this.contentWindow.docShell;
var contentListener;
try {
contentListener =
docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIURIContentListener);
} catch (ex) {
dump(ex);
}
if (!contentListener) return false;
return contentListener.doContent(contentType, isContentPreferred, request, contentHandler);
},
isPreferred: function(contentType, desiredContentType)
{
// seems like we should be getting this from helper apps or something
switch(contentType) {
case "text/html":
case "text/xul":
case "text/rdf":
case "text/xml":
case "text/css":
case "image/gif":
case "image/jpeg":
case "image/png":
case "text/plain":
case "application/http-index-format":
return true;
}
return false;
},
canHandleContent: function(contentType, isContentPreferred, desiredContentType)
{
var docShell = this.contentWindow.docShell;
var contentListener;
try {
contentListener =
docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIURIContentListener);
} catch (ex) {
dump(ex);
}
if (!contentListener) return false;
return contentListener.canHandleContent(contentType, isContentPreferred, desiredContentType);
},
convertWindowToDocShell: function(win) {
// don't know how to do this
return null;
},
loadCookie: null,
parentContentListener: null
}
// |forceOpen| is a bool that indicates that the sidebar should be forced open. In other words
// the toggle won't be allowed to close the sidebar.
function toggleSidebar(aCommandID, forceOpen) {

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

@ -70,6 +70,10 @@ else
DIRS += history bookmarks
endif
ifdef MOZ_FEEDS
DIRS += feeds
endif
DIRS += build
include $(topsrcdir)/config/rules.mk

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

@ -46,7 +46,7 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../migration/src \
-I$(srcdir)/../shell/src \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,version)
endif
@ -83,6 +83,11 @@ SHARED_LIBRARY_LIBS += \
$(NULL)
endif
ifdef MOZ_FEEDS
LOCAL_INCLUDES += -I$(srcdir)/../feeds/src
SHARED_LIBRARY_LIBS += ../feeds/src/$(LIB_PREFIX)feeds_s.$(LIB_SUFFIX)
endif
# Link to gkgfx for GNOME shell service
ifeq ($(MOZ_WIDGET_TOOLKIT), gtk2)
EXTRA_DSO_LIBS += gkgfx

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

@ -123,3 +123,9 @@
#define NS_MORKHISTORYIMPORTER_CONTRACTID \
"@mozilla.org/browser/history-importer;1"
#define NS_FEEDSNIFFER_CID \
{ 0x6893e69, 0x71d8, 0x4b23, { 0x81, 0xeb, 0x80, 0x31, 0x4d, 0xaf, 0x3e, 0x66 } }
#define NS_FEEDSNIFFER_CONTRACTID \
"@mozilla.org/browser/feeds/sniffer;1"

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

@ -77,6 +77,9 @@
#include "nsICabProfileMigrator.h"
#endif
#include "rdf.h"
#ifdef MOZ_FEEDS
#include "nsFeedSniffer.h"
#endif
/////////////////////////////////////////////////////////////////////////////
@ -118,6 +121,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacIEProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCaminoProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsICabProfileMigrator)
#endif
#ifdef MOZ_FEEDS
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
#endif
/////////////////////////////////////////////////////////////////////////////
static const nsModuleComponentInfo components[] =
@ -207,6 +214,14 @@ static const nsModuleComponentInfo components[] =
#endif
#ifdef MOZ_FEEDS
{ "Feed Sniffer",
NS_FEEDSNIFFER_CID,
NS_FEEDSNIFFER_CONTRACTID,
nsFeedSnifferConstructor,
nsFeedSniffer::Register },
#endif
{ "Profile Migrator",
NS_FIREFOX_PROFILEMIGRATOR_CID,
NS_PROFILEMIGRATOR_CONTRACTID,
@ -274,8 +289,6 @@ static const nsModuleComponentInfo components[] =
NS_SEAMONKEYPROFILEMIGRATOR_CID,
NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "seamonkey",
nsSeamonkeyProfileMigratorConstructor }
};
NS_IMPL_NSGETMODULE(nsBrowserCompsModule, components)

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

@ -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 the Feed Handling System
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <beng@google.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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
include $(topsrcdir)/config/rules.mk

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

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

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

@ -0,0 +1,3 @@
browser.jar:
* content/browser/feeds/feedhandler.xul (content/feedhandler.xul)
* content/browser/feeds/feedhandler.js (content/feedhandler.js)

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

@ -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 mozilla.org code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = browser-feeds
XPIDL_MODULE = browser-feeds
XPIDLSRCS = nsIFeedResultService.idl nsIWebContentConverterRegistrar.idl
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,77 @@
/* -*- 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 the Feed Result Service.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.com>
* Robert Sayre <sayrer@gmail.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 nsIURI;
interface nsIFeedResult;
/**
* nsIFeedResultService provides a globally-accessible object for retreiving
* the results of feed processing.
*/
[scriptable, uuid(76d751fa-ad21-4a21-bc0b-405abbaf3fa1)]
interface nsIFeedResultService : nsISupports
{
/**
* Registers a Feed Result object with a globally accessible service
* so that it can be accessed by a singleton method outside the usual
* flow of control in document loading.
*
* @param feedResult
* An object implementing nsIFeedResult representing the feed.
*/
void addFeedResult(in nsIFeedResult feedResult);
/**
* Gets a Feed Handler object registered using addFeedResult.
* @param uri
* The URI of the feed a handler is being requested for
*/
nsIFeedResult getFeedResult(in nsIURI uri);
/**
* Unregisters a Feed Handler object registered using addFeedResult.
* @param uri
* The feed URI the handler was registered under.
*/
void removeFeedResult(in nsIURI uri);
attribute boolean attached;
};

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

@ -0,0 +1,177 @@
/* -*- 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 the Web Content Converter Registrar.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.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 nsIRequest;
[scriptable, uuid(2bd97d63-e928-4d52-9fd4-34061349a9a6)]
interface nsIWebContentHandlerInfo : nsISupports
{
/**
* The content type handled by the handler
*/
readonly attribute AString contentType;
/**
* The uri of the handler, with an embedded %s where the URI of the loaded
* document will be encoded.
*/
readonly attribute AString uri;
/**
* A human readable title of the handler.
*/
readonly attribute AString name;
/**
* Gets the service URL Spec, with the loading document URI encoded in it.
* @param uri
* The URI of the document being loaded
* @returns The URI of the service with the loading document URI encoded in
* it.
*/
AString getHandlerURI(in AString uri);
/**
* Determines if this handler object is equivalent to another.
* @param other
* The other handler info object
* @returns true if the two objects are equivalent (same content type,
* same uri).
*/
boolean equals(in nsIWebContentHandlerInfo other);
};
[scriptable, uuid(632b16a8-5c6b-4dc5-a8db-01771af7a79d)]
interface nsIWebContentConverterRegistrar : nsISupports
{
/**
* Specifies the handler to be used to automatically handle all links of a
* certain content type from now on.
* @param contentType
* The content type to automatically load with the specified handler
* @param handler
* A web service handler. If this is null, no automatic action is
* performed and the user must choose.
* @throws NS_ERROR_NOT_AVAILABLE if the service refered to by |handler| is
* not already registered.
*/
void setAutoHandler(in AString contentType, in nsIWebContentHandlerInfo handler);
/**
* Gets the auto handler specified for a particular content type
* @param contentType
* The content type to look up an auto handler for.
* @returns The web service handler that will automatically handle all
* documents of the specified type. null if there is no automatic
* handler. (Handlers may be registered, just none of them specified
* as "automatic").
*/
nsIWebContentHandlerInfo getAutoHandler(in AString contentType);
/**
* Gets the URI Spec for the "handler" of a particular type, with the
* specified uri embedded.
* @param uri
* The uri to be embedded in the handler URI
* @param contentType
* The content type of the document at |uri|
* @returns A uri of the handler for the |contentType|, with the |
*/
AString getHandlerURI(in AString uri, in AString contentType);
/**
* Loads the preferred handler when content of a registered type is about
* to be loaded.
* @param request
* The nsIRequest for the load of the content
*/
void loadPreferredHandler(in nsIRequest request);
/**
* Removes a registered protocol handler
* @param protocol
* The protocol scheme to remove a service handler for
* @param uri
* The uri of the service handler to remove
*/
void removeProtocolHandler(in AString protocol, in AString uri);
/**
* Removes a registered content handler
* @param contentType
* The content type to remove a service handler for
* @param uri
* The uri of the service handler to remove
*/
void removeContentHandler(in AString contentType, in AString uri);
/**
* Registers a protocol handler for a web service
* @param protocol
* The protocol scheme to register a service handler for
* @param uri
* The uri of the service handler to register
* @param title
* The human readable title of the service
*/
void registerProtocolHandler(in AString scheme, in AString uri,
in AString title);
/**
* Registers a content handler for a web service
* @param contentType
* The content type to register a service handler for
* @param uri
* The uri of the service handler to register
* @param title
* The human readable title of the service
*/
void registerContentHandler(in AString contentType, in AString uri,
in AString title);
/**
* Gets the list of content handlers for a particular type.
* @param contentType
* The content type to get handlers for
* @returns An array of nsIWebContentHandlerInfo objects
*/
void getContentHandlers(in AString contentType, out unsigned long count,
[retval,array,size_is(count)] out nsIWebContentHandlerInfo handlers);
};

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

@ -0,0 +1,427 @@
/* -*- 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 the Feed Stream Converter.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.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 ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
function LOG(str) {
dump("*** " + str + "\n");
}
const FC_CLASSID = Components.ID("{229fa115-9412-4d32-baf3-2fc407f76fb1}");
const FC_CLASSNAME = "Feed Stream Converter";
const FS_CLASSID = Components.ID("{2376201c-bbc6-472f-9b62-7548040a61c6}");
const FS_CLASSNAME = "Feed Result Service";
const FS_CONTRACTID = "@mozilla.org/browser/feeds/result-service;1";
const FPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=feed";
const FPH_CLASSID = Components.ID("{4f91ef2e-57ba-472e-ab7a-b4999e42d6c0}");
const FPH_CLASSNAME = "Feed Protocol Handler";
const PCPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=pcast";
const PCPH_CLASSID = Components.ID("{1c31ed79-accd-4b94-b517-06e0c81999d5}");
const PCPH_CLASSNAME = "Podcast Protocol Handler";
const FHS_CONTRACTID = "@mozilla.org/browser/feeds/handler-service;1";
const FHS_CLASSID = Components.ID("{792a7e82-06a0-437c-af63-b2d12e808acc}");
const FHS_CLASSNAME = "Feed Handler Service";
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const TYPE_ANY = "*/*";
const FEEDHANDLER_URI = "chrome://browser/content/feeds/feedhandler.xul";
function FeedConverter() {
}
FeedConverter.prototype = {
/**
* This is the downloaded text data for the feed.
*/
_data: null,
/**
* This is the object listening to the conversion, which is ultimately the
* docshell for the load.
*/
_listener: null,
/**
* See nsIStreamConverter.idl
*/
canConvert: function FC_canConvert(sourceType, destinationType) {
// We only support one conversion.
return destinationType == TYPE_ANY && sourceType == TYPE_MAYBE_FEED;
},
/**
* See nsIStreamConverter.idl
*/
convert: function FC_convert(sourceStream, sourceType, destinationType,
context) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
/**
* See nsIStreamConverter.idl
*/
asyncConvertData: function FC_asyncConvertData(sourceType, destinationType,
listener, context) {
this._listener = listener;
},
/**
* See nsIFeedResultListener.idl
*/
handleResult: function FC_handleResult(result) {
// Feeds come in various content types, which our feed sniffer coerces to
// the maybe.feed type. However, feeds are used as a transport for
// different data types, e.g. news/blogs (traditional feed), video/audio
// (podcasts) and photos (photocasts, photostreams). Each of these is
// different in that there's a different class of application suitable for
// handling feeds of that type, but without a content-type differentiation
// it is difficult for us to disambiguate.
//
// The other problem is that if the user specifies an auto-action handler
// for one feed application, the fact that the content type is shared means
// that all other applications will auto-load with that handler too,
// regardless of the content-type.
//
// This means that content-type alone is not enough to determine whether
// or not a feed should be auto-handled. This means that for feeds we need
// to always use this stream converter, even when an auto-action is
// specified, not the basic one provided by WebContentConverter. This
// converter needs to consume all of the data and parse it, and based on
// that determination make a judgement about type.
//
// Since there are no content types for this content, and I'm not going to
// invent any, the upshot is that while a user can set an auto-handler for
// generic feed content, the system will prevent them from setting an auto-
// handler for other stream types. In those cases, the user will always see
// the preview page and have to select a handler. We can guess and show
// a client handler, but will not be able to show web handlers for those
// types.
//
// If this is just a feed, not some kind of specialized application, then
// auto-handlers can be set and we should obey them.
var wccr =
Cc["@mozilla.org/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterRegistrar);
var feed = result.doc.QueryInterface(Ci.nsIFeed);
if (feed.type == Ci.nsIFeed.TYPE_FEED &&
wccr.getAutoHandler(TYPE_MAYBE_FEED)) {
wccr.loadPreferredHandler(this._request);
return;
}
// If there was no automatic handler, or this was a podcast, photostream or
// some other kind of application, we must always show the preview page...
// Store the result in the result service so that the display page can
// access it.
var feedService =
Cc["@mozilla.org/browser/feeds/result-service;1"].
getService(Ci.nsIFeedResultService);
feedService.addFeedResult(result);
// Now load the actual XUL document.
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var chromeURI = ios.newURI(FEEDHANDLER_URI, null, null);
var chromeChannel = ios.newChannelFromURI(chromeURI, null);
chromeChannel.originalURI = result.uri;
chromeChannel.asyncOpen(this._listener, null);
},
/**
* See nsIStreamListener.idl
*/
onDataAvailable: function FC_onDataAvailable(request, context, inputStream,
sourceOffset, count) {
// We are responsible for collecting all the data and retaining it.
var sis =
Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
sis.init(inputStream);
this._data += sis.read(sis.available());
},
/**
* See nsIRequestObserver.idl
*/
onStartRequest: function FC_onStartRequest(request, context) {
// Initialize the buffer
this._data = "";
},
/**
* See nsIRequestObserver.idl
*/
onStopRequest: function FC_onStopReqeust(request, context, status) {
var channel = request.QueryInterface(Ci.nsIChannel);
this._request = request;
// Parse the feed data we have buffered
var feedProcessor =
Cc["@mozilla.org/feed-processor;1"].
createInstance(Ci.nsIFeedProcessor);
feedProcessor.listener = this;
feedProcessor.parseFromString(this._data, channel.URI);
},
/**
* See nsISupports.idl
*/
QueryInterface: function FC_QueryInterface(iid) {
if (iid.equals(Ci.nsIFeedResultListener) ||
iid.equals(Ci.nsIStreamConverter) ||
iid.equals(Ci.nsIStreamListener) ||
iid.equals(Ci.nsIRequestObserver)||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
};
var FeedConverterFactory = {
createInstance: function FS_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return new FeedConverter().QueryInterface(iid);
},
QueryInterface: function FS_QueryInterface(iid) {
if (iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
};
/**
* Keeps parsed FeedResults around for use elsewhere in the UI after the stream
* converter completes.
*/
var FeedResultService = {
/**
* A URI spec -> nsIFeedResult hash
*/
_results: { },
/**
* See nsIFeedService.idl
*/
addFeedResult: function FRS_addFeedResult(feedResult) {
NS_ASSERT(feedResult.uri != null, "null URI!");
NS_ASSERT(feedResult.uri != null, "null feedResult!");
this._results[feedResult.uri.spec] = feedResult;
},
/**
* See nsIFeedService.idl
*/
getFeedResult: function RFS_getFeedResult(uri) {
NS_ASSERT(uri != null, "null URI!");
return this._results[uri.spec];
},
/**
* See nsIFeedService.idl
*/
removeFeedResult: function FRS_removeFeedResult(uri) {
NS_ASSERT(uri != null, "null URI!");
if (uri.spec in this._results)
delete this._results[uri.spec];
},
createInstance: function FRS_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return this.QueryInterface(iid);
},
QueryInterface: function FRS_QueryInterface(iid) {
if (iid.equals(Ci.nsIFeedResultService) ||
iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
};
/**
* A protocol handler that converts the URIs of Apple's various bogo protocol
* schemes into http, as they should be. Mostly, this object just forwards
* things through to the HTTP protocol handler.
*/
function FeedProtocolHandler(scheme) {
this._scheme = scheme;
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
this._http = ios.getProtocolHandler("http");
}
FeedProtocolHandler.prototype = {
_scheme: "",
get scheme() {
return this._scheme;
},
get protocolFlags() {
return this._http.protocolFlags;
},
get defaultPort() {
return this._http.defaultPort;
},
allowPort: function FPH_allowPort(port, scheme) {
return this._http.allowPort(port, scheme);
},
newURI: function FPH_newURI(spec, originalCharset, baseURI) {
var uri =
Cc["@mozilla.org/network/standard-url;1"].
createInstance(Ci.nsIStandardURL);
uri.init(Ci.nsIStandardURL.URLTYPE_STANDARD, 80, spec, originalCharset,
baseURI);
return uri;
},
newChannel: function FPH_newChannel(uri) {
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
// Force http, since this is what feed:// maps to in Safari.
uri.scheme = "http";
var channel = ios.newChannelFromURI(uri, null);
channel.originalURI = uri;
return channel;
},
QueryInterface: function FPH_QueryInterface(iid) {
if (iid.equals(Ci.nsIProtocolHandler) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
/**
* An object implementing nsIFactory that can construct other objects upon
* createInstance, passing a set of parameters to that object's constructor.
*/
function GenericComponentFactory(ctor, params) {
this._ctor = ctor;
this._params = params;
}
GenericComponentFactory.prototype = {
_ctor: null,
_params: null,
createInstance: function GCF_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return (new this._ctor(this._params)).QueryInterface(iid);
},
QueryInterface: function GCF_QueryInterface(iid) {
if (iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
var Module = {
QueryInterface: function M_QueryInterface(iid) {
if (iid.equals(Ci.nsIModule) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
getClassObject: function M_getClassObject(cm, cid, iid) {
if (!iid.equals(Ci.nsIFactory))
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
if (cid.equals(FS_CLASSID))
return FeedResultService;
if (cid.equals(FPH_CLASSID))
return new GenericComponentFactory(FeedProtocolHandler, "feed");
if (cid.equals(PCPH_CLASSID))
return new GenericComponentFactory(FeedProtocolHandler, "pcast");
if (cid.equals(FC_CLASSID))
return new GenericComponentFactory(FeedConverter);
throw Cr.NS_ERROR_NO_INTERFACE;
},
registerSelf: function M_registerSelf(cm, file, location, type) {
var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
cr.registerFactoryLocation(FS_CLASSID, FS_CLASSNAME, FS_CONTRACTID,
file, location, type);
cr.registerFactoryLocation(FPH_CLASSID, FPH_CLASSNAME, FPH_CONTRACTID,
file, location, type);
cr.registerFactoryLocation(PCPH_CLASSID, PCPH_CLASSNAME, PCPH_CONTRACTID,
file, location, type);
// The feed converter is always attached, since parsing must be done to
// determine whether or not auto-handling can occur.
const converterPrefix = "@mozilla.org/streamconv;1?from=";
var converterContractID =
converterPrefix + TYPE_MAYBE_FEED + "&to=" + TYPE_ANY;
cr.registerFactoryLocation(FC_CLASSID, FC_CLASSNAME, converterContractID,
file, location, type);
},
unregisterSelf: function M_unregisterSelf(cm, location, type) {
var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
cr.unregisterFactoryLocation(FPH_CLASSID, location);
cr.unregisterFactoryLocation(PCPH_CLASSID, location);
},
canUnload: function M_canUnload(cm) {
return true;
}
};
function NSGetModule(cm, file) {
return Module;
}
#include ../../../../toolkit/content/debug.js

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

@ -0,0 +1,62 @@
# ***** 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 Feed Handling System
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <beng@google.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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = feeds
LIBRARY_NAME = feeds_s
EXTRA_PP_COMPONENTS = \
FeedConverter.js \
WebContentConverter.js \
$(NULL)
REQUIRES = xpcom string necko
CPPSRCS = nsFeedSniffer.cpp
LOCAL_INCLUDES = -I$(srcdir)/../../build
FORCE_STATIC_LIB = 1
MOZILLA_INTERNAL_API = 1
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,576 @@
/* -*- 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 the Web Content Converter System.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.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 ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
function LOG(str) {
dump("*** " + str + "\n");
}
const WCCR_CONTRACTID = "@mozilla.org/web-content-handler-registrar;1";
const WCCR_CLASSID = Components.ID("{792a7e82-06a0-437c-af63-b2d12e808acc}");
const WCCR_CLASSNAME = "Web Content Handler Registrar";
const WCC_CLASSID = Components.ID("{db7ebf28-cc40-415f-8a51-1b111851df1e}");
const WCC_CLASSNAME = "Web Service Handler";
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const TYPE_ANY = "*/*";
const PREF_CONTENTHANDLERS_AUTO = "browser.contentHandlers.auto.";
const PREF_CONTENTHANDLERS_BRANCH = "browser.contentHandlers.types.";
function WebContentConverter() {
}
WebContentConverter.prototype = {
convert: function WCC_convert() { },
asyncConvertData: function WCC_asyncConvertData() { },
onDataAvailable: function WCC_onDataAvailable() { },
onStopRequest: function WCC_onStopRequest() { },
onStartRequest: function WCC_onStartRequest(request, context) {
var wccr =
Cc["@mozilla.org/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterRegistrar);
wccr.loadPreferredHandler(request);
},
QueryInterface: function WCC_QueryInterface(iid) {
if (iid.equals(Ci.nsIStreamConverter) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
var WebContentConverterFactory = {
createInstance: function WCCF_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return new WebContentConverter().QueryInterface(iid);
},
QueryInterface: function WCC_QueryInterface(iid) {
if (iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
function ServiceInfo(contentType, uri, name) {
this._contentType = contentType;
this._uri = uri;
this._name = name;
}
ServiceInfo.prototype = {
/**
* See nsIWebContentHandlerInfo
*/
get contentType() {
return this._contentType;
},
/**
* See nsIWebContentHandlerInfo
*/
get uri() {
return this._uri;
},
/**
* See nsIWebContentHandlerInfo
*/
get name() {
return this._name;
},
/**
* See nsIWebContentHandlerInfo
*/
getHandlerURI: function SI_getHandlerURI(uri) {
return this._uri.replace(/%s/gi, encodeURIComponent(uri));
},
/**
* See nsIWebContentHandlerInfo
*/
equals: function SI_equals(other) {
return this.contentType == other.contentType &&
this.uri == other.uri;
},
QueryInterface: function SI_QueryInterface(iid) {
if (iid.equals(Ci.nsIWebContentHandlerInfo) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
var WebContentConverterRegistrar = {
_contentTypes: { },
_protocols: { },
/**
* Track auto handlers for various content types using a content-type to
* handler map.
*/
_autoHandleContentTypes: { },
/**
* See nsIWebContentConverterRegistrar
*/
getAutoHandler:
function WCCR_getAutoHandler(contentType) {
contentType = this._resolveContentType(contentType);
if (contentType in this._autoHandleContentTypes)
return this._autoHandleContentTypes[contentType];
return null;
},
/**
* See nsIWebContentConverterRegistrar
*/
setAutoHandler:
function WCCR_setAutoHandler(contentType, handler) {
if (handler && !this._typeIsRegistered(contentType, handler.uri))
throw Cr.NS_ERROR_NOT_AVAILABLE;
contentType = this._resolveContentType(contentType);
this._setAutoHandler(contentType, handler);
var ps =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
var autoBranch = ps.getBranch(PREF_CONTENTHANDLERS_AUTO);
if (handler)
autoBranch.setCharPref(contentType, handler.uri);
else if (autoBranch.prefHasUserValue(contentType))
autoBranch.clearUserPref(contentType);
ps.savePrefFile(null);
},
/**
* Update the internal data structure (not persistent)
*/
_setAutoHandler:
function WCCR__setAutoHandler(contentType, handler) {
if (handler)
this._autoHandleContentTypes[contentType] = handler;
else if (contentType in this._autoHandleContentTypes)
delete this._autoHandleContentTypes[contentType];
},
/**
* See nsIWebContentConverterRegistrar
*/
loadPreferredHandler:
function WCCR_loadPreferredHandler(request) {
var channel = request.QueryInterface(Ci.nsIChannel);
var contentType = this._resolveContentType(channel.contentType);
var handler = this.getAutoHandler(contentType);
if (handler) {
request.cancel(Cr.NS_ERROR_FAILURE);
var webNavigation =
channel.notificationCallbacks.getInterface(Ci.nsIWebNavigation);
webNavigation.loadURI(handler.getHandlerURI(channel.URI.spec),
Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
null, null, null);
}
},
/**
* See nsIWebContentConverterRegistrar
*/
removeProtocolHandler:
function WCCR_removeProtocolHandler(protocol, uri) {
function notURI(currentURI) {
return currentURI != uri;
}
if (protocol in this._protocols)
this._protocols[protocol] = this._protocols[protocol].filter(notURI);
},
/**
* See nsIWebContentConverterRegistrar
*/
removeContentHandler:
function WCCR_removeContentHandler(contentType, uri) {
function notURI(serviceInfo) {
return serviceInfo.uri != uri;
}
if (contentType in this._contentTypes) {
this._contentTypes[contentType] =
this._contentTypes[contentType].filter(notURI);
}
},
/**
*
*/
_mappings: {
"application/rss+xml": TYPE_MAYBE_FEED,
"application/atom+xml": TYPE_MAYBE_FEED,
},
/**
* These are types for which there is a separate content converter aside
* from our built in generic one. We should not automatically register
* a factory for creating a converter for these types.
*/
_blockedTypes: {
"application/vnd.mozilla.maybe.feed": true,
},
/**
* Determines the "internal" content type based on the _mappings.
* @param contentType
* @returns The resolved contentType value.
*/
_resolveContentType:
function WCCR__resolveContentType(contentType) {
if (contentType in this._mappings)
return this._mappings[contentType];
return contentType;
},
_confirmAdd: function WCCR__confirmAdd(title, uri) {
var ps =
Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
return ps.confirm(null, "Add Handler",
"Add web handler for " + title + " to " + uri + "?",
"Yes", "No", null, null);
},
// XXXben: These functions need to move to window.navigator
/**
* See nsIWebContentConverterRegistrar
*/
registerProtocolHandler:
function WCCR_registerProtocolHandler(protocol, uri, title) {
LOG("registerProtocolHandler(" + protocol + "," + uri + "," + title + ")");
if (this._confirmAdd(title, uri))
this._protocols[protocol] = uri;
},
/**
* See nsIWebContentConverterRegistrar
* This is the web front end into the registration system, so a prompt to
* confirm the registration is provided, and the result is saved to
* preferences.
*/
registerContentHandler:
function WCCR_registerContentHandler(contentType, uri, title) {
LOG("registerContentHandler(" + contentType + "," + uri + "," + title + ")");
if (!this._confirmAdd(title, uri))
return;
contentType = this._resolveContentType(contentType);
this._registerContentHandler(contentType, uri, title);
this._saveContentHandlerToPrefs(contentType, uri, title);
},
/**
* Save Web Content Handler metadata to persistent preferences.
* @param contentType
* The content Type being handled
* @param uri
* The uri of the web service
* @param title
* The human readable name of the web service
*
* This data is stored under:
*
* browser.contentHandlers.type0 = content/type
* browser.contentHandlers.uri0 = http://www.foo.com/q=%s
* browser.contentHandlers.title0 = Foo 2.0alphr
*/
_saveContentHandlerToPrefs:
function WCCR__saveContentHandlerToPrefs(contentType, uri, title) {
var ps =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
var typeBranch =
ps.getBranch(PREF_CONTENTHANDLERS_BRANCH);
var i = 0;
while (true) {
try {
typeBranch.getCharPref("type" + i);
++i;
}
catch (e) {
// No more handlers
break;
}
}
typeBranch.setCharPref("type" + i, contentType);
typeBranch.setCharPref("uri" + i, uri);
typeBranch.setCharPref("title" + i, title);
ps.savePrefFile(null);
},
/**
* Determines if there is a type with a particular uri registered for the
* specified content type already.
* @param contentType
* The content type that the uri handles
* @param uri
* The uri of the
*/
_typeIsRegistered: function WCCR__typeIsRegistered(contentType, uri) {
var services = this._contentTypes[contentType];
for (var i = 0; i < services.length; ++i) {
// This uri has already been registered
if (services[i].uri == uri)
return true;
}
return false;
},
/**
* Gets a stream converter contract id for the specified content type.
* @param contentType
* The source content type for the conversion.
* @returns A contract id to construct a converter to convert between the
* contentType and *\/*.
*/
_getConverterContractID: function WCCR__getConverterContractID(contentType) {
const template = "@mozilla.org/streamconv;1?from=%s&to=*/*";
return template.replace(/%s/, contentType);
},
/**
* Update the content type -> handler map. This mapping is not persisted, use
* registerContentHandler or _saveContentHandlerToPrefs for that purpose.
* @param contentType
* The content Type being handled
* @param uri
* The uri of the web service
* @param title
* The human readable name of the web service
*/
_registerContentHandler:
function WCCR__registerContentHandler(contentType, uri, title) {
if (!(contentType in this._contentTypes))
this._contentTypes[contentType] = [];
// Avoid adding duplicates
if (this._typeIsRegistered(contentType, uri))
return;
this._contentTypes[contentType].push(new ServiceInfo(contentType, uri, title));
if (!(contentType in this._blockedTypes)) {
var converterContractID = this._getConverterContractID(contentType);
var cr = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
cr.registerFactory(WCC_CLASSID, WCC_CLASSNAME, converterContractID,
WebContentConverterFactory);
}
},
/**
* See nsIWebContentConverterRegistrar
*/
getContentHandlers:
function WCCR_getContentHandlers(contentType, countRef) {
countRef.value = 0;
if (!(contentType in this._contentTypes))
return [];
var handlers = this._contentTypes[contentType];
countRef.value = handlers.length;
return handlers;
},
/**
* Load the auto handler, content handler and protocol tables from
* preferences.
*/
_init: function WCCR__init() {
var ps =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
try {
var autoBranch = ps.getBranch(PREF_CONTENTHANDLERS_AUTO);
var childPrefs = autoBranch.getChildList("", { });
for (var i = 0; i < childPrefs.length; ++i) {
var type = childPrefs[i];
if (autoBranch.getBoolPref(type))
this._autoHandleContentType(type, true);
}
}
catch (e) {
// No auto branch yet, that's fine
}
try {
var handlerBranch = ps.getBranch(PREF_CONTENTHANDLERS_BRANCH);
var i = 0;
while (true) {
try {
var type = handlerBranch.getCharPref("type" + i);
var uri = handlerBranch.getCharPref("uri" + i);
var title = handlerBranch.getCharPref("title" + i);
++i;
this._registerContentHandler(type, uri, title);
}
catch (e) {
break;
}
}
}
catch (e) {
// No content handlers yet, that's fine
}
},
/**
* See nsIObserver
*/
observe: function WCCR_observe(subject, topic, data) {
var os =
Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
switch (topic) {
case "app-startup":
os.addObserver(this, "profile-after-change", false);
break;
case "profile-after-change":
os.removeObserver(this, "profile-after-change");
this._init();
break;
}
},
/**
* See nsIFactory
*/
createInstance: function WCCR_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return this.QueryInterface(iid);
},
/**
* See nsIClassInfo
*/
getInterfaces: function WCCR_getInterfaces(countRef) {
countRef.value = 2;
return [Ci.nsIWebContentConverterRegistrar, Ci.nsIClassInfo];
},
getHelperForLanguage: function WCCR_getHelperForLanguage(language) {
return null;
},
contractID: WCCR_CONTRACTID,
classDescription: WCCR_CLASSNAME,
classID: WCCR_CLASSID,
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
flags: Ci.nsIClassInfo.DOM_OBJECT,
/**
* See nsISupports
*/
QueryInterface: function WCCR_QueryInterface(iid) {
if (iid.equals(Ci.nsIWebContentConverterRegistrar) ||
iid.equals(Ci.nsIObserver) ||
iid.equals(Ci.nsIClassInfo) ||
iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
};
var Module = {
QueryInterface: function M_QueryInterface(iid) {
if (iid.equals(Ci.nsIModule) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
getClassObject: function M_getClassObject(cm, cid, iid) {
if (!iid.equals(Ci.nsIFactory))
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
if (cid.equals(WCCR_CLASSID))
return WebContentConverterRegistrar;
throw Cr.NS_ERROR_NO_INTERFACE;
},
registerSelf: function M_registerSelf(cm, file, location, type) {
var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
cr.registerFactoryLocation(WCCR_CLASSID, WCCR_CLASSNAME, WCCR_CONTRACTID,
file, location, type);
var catman =
Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
const JS_GLOBAL_PROP = "JavaScript global property";
catman.addCategoryEntry(JS_GLOBAL_PROP, "goats", WCCR_CONTRACTID, true,
true);
catman.addCategoryEntry("app-startup", WCCR_CLASSNAME,
"service," + WCCR_CONTRACTID, true, true, null);
},
unregisterSelf: function M_unregisterSelf(cm, location, type) {
var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
cr.unregisterFactoryLocation(WCCR_CLASSID, location);
},
canUnload: function M_canUnload(cm) {
return true;
}
};
function NSGetModule(cm, file) {
return Module;
}
#include ../../../../toolkit/content/debug.js

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

@ -0,0 +1,251 @@
/* -*- 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 the Feed Content Sniffer.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.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 "nsFeedSniffer.h"
#include "prmem.h"
#include "nsNetCID.h"
#include "nsXPCOM.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsStringStream.h"
#include "nsBrowserCompsCID.h"
#include "nsICategoryManager.h"
#include "nsIServiceManager.h"
#include "nsIStreamConverterService.h"
#include "nsIStreamConverter.h"
#include "nsIStreamListener.h"
#include "nsIHttpChannel.h"
#define TYPE_ATOM "application/atom+xml"
#define TYPE_RSS "application/rss+xml"
#define TYPE_MAYBE_FEED "application/vnd.mozilla.maybe.feed"
#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
#define NS_RSS "http://purl.org/rss/1.0/"
#define MAX_BYTES 512
NS_IMPL_ISUPPORTS2(nsFeedSniffer, nsIContentSniffer, nsIStreamListener)
nsresult
nsFeedSniffer::ConvertEncodedData(nsIRequest* request,
const PRUint8* data,
PRUint32 length)
{
nsresult rv = NS_OK;
mDecodedData = "";
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
if (!httpChannel)
return NS_ERROR_NO_INTERFACE;
nsCAutoString contentEncoding;
httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
contentEncoding);
if (!contentEncoding.IsEmpty()) {
nsCOMPtr<nsIStreamConverterService> converterService(do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID));
if (converterService) {
ToLowerCase(contentEncoding);
nsCOMPtr<nsIStreamListener> converter;
rv = converterService->AsyncConvertData(contentEncoding.get(),
"uncompressed", this, nsnull,
getter_AddRefs(converter));
NS_ENSURE_SUCCESS(rv, rv);
converter->OnStartRequest(request, nsnull);
nsCOMPtr<nsIInputStream> rawStream;
rv = NS_NewByteInputStream(getter_AddRefs(rawStream),
(const char*)data, length);
NS_ENSURE_SUCCESS(rv, rv);
rv = converter->OnDataAvailable(request, nsnull, rawStream, 0, length);
NS_ENSURE_SUCCESS(rv, rv);
converter->OnStopRequest(request, nsnull, NS_OK);
}
}
return rv;
}
NS_IMETHODIMP
nsFeedSniffer::GetMIMETypeFromContent(nsIRequest* request,
const PRUint8* data,
PRUint32 length,
nsACString& sniffedType)
{
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
// We need to find out if this is a load of a view-source document. In this
// case we do not want to override the content type, since the source display
// does not need to be converted from feed format to XUL. More importantly,
// we don't want to change the content type from something
// nsContentDLF::CreateInstance knows about (e.g. application/xml, text/html
// etc) to something that only the application fe knows about (maybe.feed)
// thus deactivating syntax highlighting.
nsCOMPtr<nsIURI> originalURI;
channel->GetOriginalURI(getter_AddRefs(originalURI));
nsCAutoString scheme;
originalURI->GetScheme(scheme);
if (scheme.EqualsLiteral("view-source")) {
sniffedType.Truncate();
return NS_OK;
}
// Check the Content-Type to see if it is set correctly. If it is set to
// something specific that we think is a reliable indication of a feed, don't
// bother sniffing since we assume the site maintainer knows what they're
// doing.
nsCAutoString contentType;
channel->GetContentType(contentType);
if (contentType.EqualsLiteral(TYPE_RSS) ||
contentType.EqualsLiteral(TYPE_ATOM)) {
sniffedType.AssignLiteral(TYPE_MAYBE_FEED);
return NS_OK;
}
// Now we need to potentially decompress data served with
// Content-Encoding: gzip
nsresult rv = ConvertEncodedData(request, data, length);
if (NS_FAILED(rv))
return rv;
const char* testData =
mDecodedData.IsEmpty() ? (const char*)data : mDecodedData.get();
// We cap the number of bytes to scan at MAX_BYTES to prevent picking up
// false positives by accidentally reading document content, e.g. a "how to
// make a feed" page.
if (length > MAX_BYTES)
length = MAX_BYTES;
// Thus begins the actual sniffing.
nsDependentCSubstring dataString((const char*)testData,
(const char*)testData + length);
nsACString::const_iterator start_iter, end_iter;
PRBool isFeed = PR_FALSE;
// RSS 0.91/0.92/2.0
dataString.BeginReading(start_iter);
dataString.EndReading(end_iter);
isFeed = FindInReadable(NS_LITERAL_CSTRING("<rss"), start_iter, end_iter);
// Atom 1.0
if (!isFeed) {
dataString.BeginReading(start_iter);
dataString.EndReading(end_iter);
isFeed = FindInReadable(NS_LITERAL_CSTRING("<feed"), start_iter, end_iter);
}
// RSS 1.0
if (!isFeed) {
dataString.BeginReading(start_iter);
dataString.EndReading(end_iter);
if (FindInReadable(NS_LITERAL_CSTRING("<rdf:RDF"), start_iter, end_iter)) {
dataString.BeginReading(start_iter);
dataString.EndReading(end_iter);
if (FindInReadable(NS_LITERAL_CSTRING(NS_RDF), start_iter, end_iter)) {
dataString.BeginReading(start_iter);
dataString.EndReading(end_iter);
isFeed = FindInReadable(NS_LITERAL_CSTRING(NS_RSS), start_iter, end_iter);
}
}
}
// If we sniffed a feed, coerce our internal type
if (isFeed)
sniffedType.AssignLiteral(TYPE_MAYBE_FEED);
else
sniffedType.Truncate();
return NS_OK;
}
NS_IMETHODIMP
nsFeedSniffer::OnStartRequest(nsIRequest* request, nsISupports* context)
{
return NS_OK;
}
NS_IMETHODIMP
nsFeedSniffer::OnDataAvailable(nsIRequest* request, nsISupports* context,
nsIInputStream* stream, PRUint32 offset,
PRUint32 count)
{
char* decodedBytes = (char*)PR_Malloc(sizeof(char) * count);
PRUint32 read;
nsresult rv = stream->Read(decodedBytes, count, &read);
if (NS_SUCCEEDED(rv))
mDecodedData.Append(decodedBytes, read);
PR_Free(decodedBytes);
decodedBytes = nsnull;
return rv;
}
NS_IMETHODIMP
nsFeedSniffer::OnStopRequest(nsIRequest* request, nsISupports* context,
nsresult status)
{
return NS_OK;
}
NS_METHOD
nsFeedSniffer::Register(nsIComponentManager *compMgr, nsIFile *path,
const char *registryLocation,
const char *componentType,
const nsModuleComponentInfo *info)
{
nsresult rv;
nsCOMPtr<nsICategoryManager> catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
return catman->AddCategoryEntry(NS_CONTENT_SNIFFER_CATEGORY, "Feed Sniffer",
NS_FEEDSNIFFER_CONTRACTID, PR_TRUE, PR_TRUE,
nsnull);
}

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

@ -0,0 +1,63 @@
/* -*- 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 the Feed Content Sniffer.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.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 "nsIGenericFactory.h"
#include "nsIContentSniffer.h"
#include "nsIStreamListener.h"
#include "nsString.h"
class nsFeedSniffer : public nsIContentSniffer, nsIStreamListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTSNIFFER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
static NS_METHOD Register(nsIComponentManager* compMgr, nsIFile* path,
const char* registryLocation,
const char* componentType,
const nsModuleComponentInfo *info);
protected:
nsresult ConvertEncodedData(nsIRequest* request, const PRUint8* data,
PRUint32 length);
private:
nsCString mDecodedData;
};

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

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

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

@ -35,6 +35,10 @@
* locale/browser/bookmarks/addBookmark.dtd (%chrome/browser/bookmarks/addBookmark.dtd)
* locale/browser/bookmarks/bookmarks.properties (%chrome/browser/bookmarks/bookmarks.properties)
* locale/browser/bookmarks/bookmarksProperties.dtd (%chrome/browser/bookmarks/bookmarksProperties.dtd)
#endif
#ifdef MOZ_FEEDS
locale/browser/feeds/feedhandler.dtd (%chrome/browser/feeds/feedhandler.dtd)
locale/browser/feeds/feedhandler.properties (%chrome/browser/feeds/feedhandler.properties)
#endif
locale/browser/history/history.dtd (%chrome/browser/history/history.dtd)
locale/browser/migration/migration.dtd (%chrome/browser/migration/migration.dtd)

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

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

@ -20,6 +20,9 @@ classic.jar:
skin/classic/browser/Throbber-small.png
skin/classic/browser/Toolbar.png
skin/classic/browser/Toolbar-small.png
#ifdef MOZ_FEEDS
skin/classic/browser/feeds/feedhandler.css (feeds/feedhandler.css)
#endif
#ifdef MOZ_PLACES
skin/classic/browser/places/places.css (places/places.css)
skin/classic/browser/places/defaultFavicon.png (places/defaultFavicon.png)

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

@ -143,6 +143,7 @@ MOZ_XPFE_COMPONENTS = @MOZ_XPFE_COMPONENTS@
MOZ_IPCD = @MOZ_IPCD@
MOZ_PROFILESHARING = @MOZ_PROFILESHARING@
MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@
MOZ_FEEDS = @MOZ_FEEDS@
MOZ_PLACES = @MOZ_PLACES@
MOZ_STORAGE = @MOZ_STORAGE@
MOZ_MORK = @MOZ_MORK@

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

@ -4308,6 +4308,7 @@ MOZ_CALENDAR=
MOZ_DBGRINFO_MODULES=
MOZ_ENABLE_CANVAS=1
MOZ_EXTENSIONS_ALL=" cookie wallet xml-rpc help p3p venkman inspector irc typeaheadfind spellcheck gnomevfs sroaming xmlterm datetime finger cview layout-debug tasks sql xforms permissions schema-validation reporter safe-browsing"
MOZ_FEEDS=
MOZ_IMG_DECODERS_DEFAULT="png gif jpeg bmp xbm icon"
MOZ_IMG_ENCODERS_DEFAULT="png jpeg"
MOZ_IPCD=
@ -5763,6 +5764,17 @@ if test -n "$MOZ_PLACES"; then
MOZ_MORKREADER=1
fi
dnl ========================================================
dnl = Enable feeds (new feed handling/processing - Firefox)
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(feeds,
[ --enable-feeds Enable in-page feed handling and processing (Firefox)],
MOZ_FEEDS=1,
MOZ_FEEDS= )
if test -n "$MOZ_FEEDS"; then
AC_DEFINE(MOZ_FEEDS)
fi
dnl ========================================================
dnl = Enable mozStorage
dnl = XXX need to implement --with-system-sqlite3 (see bug 263381)
@ -7330,6 +7342,7 @@ AC_SUBST(LDAP_LIBS)
AC_SUBST(LIBICONV)
AC_SUBST(MOZ_PLACES)
AC_SUBST(MOZ_STORAGE)
AC_SUBST(MOZ_FEEDS)
AC_SUBST(NS_PRINTING)
AC_SUBST(MOZ_JAVAXPCOM)