зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
27e45479f5
Коммит
c2d6dd5251
|
@ -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@
|
||||
|
|
13
configure.in
13
configure.in
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче