Bug 321219 - separate places backend into toolkit, removing old files which now live in toolkit/components/places, r=beng

This commit is contained in:
benjamin%smedbergs.us 2006-07-20 20:16:15 +00:00
Родитель 4322a32cc4
Коммит f5cace86f0
35 изменённых файлов: 0 добавлений и 26366 удалений

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

@ -1 +0,0 @@
Makefile

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

@ -1,58 +0,0 @@
#
# ***** 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 Places code.
#
# The Initial Developer of the Original Code is
# Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2005
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Brett Wilson <brettw@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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = places
XPIDL_MODULE = places
XPIDLSRCS = \
nsIAnnotationService.idl \
nsIFaviconService.idl \
nsINavHistoryService.idl \
nsINavBookmarksService.idl \
nsILivemarkService.idl \
nsIRemoteContainer.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -1,308 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** 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 Annotation code
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@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"
%{C++
#include "nsTArray.h"
#include "nsCOMArray.h"
#include "nsString.h"
%}
interface nsIURI;
interface nsIVariant;
[ptr] native CStringArray(nsTArray<nsCString>);
[ptr] native URIArray(nsCOMArray<nsIURI>);
[scriptable, uuid(d41c9510-2377-4728-b275-bdad6a0521f8)]
interface nsIAnnotationObserver : nsISupports
{
/**
* Called when an annotation value is set. It could be a new annotation,
* or it could be a new value for an existing annotation.
*/
void onAnnotationSet(in nsIURI aURI, in AUTF8String aName);
/**
* Called when an annotation is deleted. If aName is empty, then ALL
* annotations for the given URI have been deleted. This is not called when
* annotations are expired (normally happens when the app exits).
*/
void onAnnotationRemoved(in nsIURI aURI, in AUTF8String aName);
};
[scriptable, uuid(a857c97f-7705-4376-b374-bd8799f69d51)]
interface nsIAnnotationService : nsISupports
{
/**
* Valid values for aExpiration, which sets the expiration policy for your
* annotation. These times are measured since the last visit date of the
* page in question. This means that if you set an annotation with anything
* but session expiration, it will not expire so long as the user keeps
* visiting the page from time to time.
*/
/* EXPIRATION IS CURRENTLY UNIMPLEMENTED. This is here as a proposed
expiration policy. May be changed. Currently, use 0 for expiration.
*/
// For temporary stuff that can be discarded when the user exists
const PRInt32 EXPIRE_SESSION = 0;
// for short-lived temporary data that you still want to outlast a session
const PRInt32 EXPIRE_DAYS = 1;
// for general page settings, things the user is interested in seeing
// if they come back to this page some time in the future.
const PRInt32 EXPIRE_WEEKS = 2;
// Something that the user will be interested in seeing in their
// history like favicons. If they haven't visited a page in a couple
// of months, they probably aren't interested in much other annotation,
// the positions of things, or other stuff you create, so put that in
// the weeks policy.
const PRInt32 EXPIRE_MONTHS = 3;
// For small, user-entered data like notes that should never expire.
const PRInt32 EXPIRE_NEVER = 4;
/**
* Sets an annotation, overwriting any previous annotation with the same
* URL/name. IT IS YOUR JOB TO NAMESPACE YOUR ANNOTATION NAMES.
* Use the form "namespace/value", so your name would be like
* "bills_extension/page_state" or "history/thumbnail".
*
* Do not use characters that are not valid in URLs such as spaces, ":",
* commas, or most other symbols. You should stick to ASCII letters and
* numbers plus "_", "-", and "/".
*
* aExpiration is one of EXPIRE_* above. aFlags should be 0 for now, some
* flags will be defined in the future.
*
* NOTE: ALL ANNOTATIONS WILL GET DELETED WHEN THE PAGE IS REMOVED FROM
* HISTORY, regardless of expiration date. This means that if you create an
* annotation on a random unvisited URI, it will get deleted when the
* browser shuts down. Otherwise, things can exist in history as
* annotations but the user has no way of knowing it, potentially violating
* their privacy expectations about actions such as "Clear history." If
* there is an important annotation that the user wants to keep, you should
* make sure that URL is bookmarked. This will ensure the item is never
* completely deleted from the history database.
*
* The annotation "favicon" is special. favicons are stored in the favicon
* service, but are special cased in the protocol handler so they look like
* annotations. Do not set favicons using this service, it will not work.
*/
void setAnnotationString(in nsIURI aURI, in AUTF8String aName,
in AString aValue, in PRInt32 aFlags,
in PRInt32 aExpiration);
/**
* Sets an annotation just like setAnnotationString, but takes an Int32 as
* input.
*/
void setAnnotationInt32(in nsIURI aURI, in AUTF8String aName,
in PRInt32 aValue, in PRInt32 aFlags,
in PRInt32 aExpiration);
/**
* Sets an annotation just like setAnnotationString, but takes an Int64 as
* input.
*/
void setAnnotationInt64(in nsIURI aURI, in AUTF8String aName,
in PRInt64 aValue, in PRInt32 aFlags,
in PRInt32 aExpiration);
/**
* Sets an annotation just like setAnnotationString, but takes a double as
* input.
*/
void setAnnotationDouble(in nsIURI aURI, in AUTF8String aName,
in double aValue, in PRInt32 aFlags,
in PRInt32 aExpiration);
/*
* Sets an annotation just like setAnnotationString, but takes binary data
* as input. You MUST supply a valid MIME type.
*/
void setAnnotationBinary(in nsIURI aURI, in AUTF8String aName,
[const,array,size_is(aDataLen)] in octet aData,
in PRUint32 aDataLen, in AUTF8String aMimeType,
in PRInt32 aFlags, in PRInt32 aExpiration);
/**
* Retrieves the string value of a given annotation. Throws an error if the
* annotation does not exist. If the annotation was set as a different
* type than you are retrieving it as, the value will be converted as best
* as we can. You aren't always guaranteed a good conversion, however,
* and errors will not be thrown in this case. (For example, doubles will
* lose precision when stringified.)
*/
AString getAnnotationString(in nsIURI aURI, in AUTF8String aName);
/**
* Same as getAnnotationString but for ints. If the value doesn't look like
* an int, returns 0. (this is current sqlite behavior when asking for an
* int when there is not one, it will possibly change in the future if we
* start caching stuff).
*/
PRInt32 getAnnotationInt32(in nsIURI aURI, in AUTF8String aName);
/**
* Same as getAnnotationString for Int64s. If the value doesn't look like
* an int, returns 0. (this is current sqlite behavior when asking for an
* int when there is not one, it will possibly change in the future if we
* start caching stuff).
*/
PRInt64 getAnnotationInt64(in nsIURI aURI, in AUTF8String aName);
/**
* Same as getAnnotationString but returns a double-precision float. If the
* value doesn't look like an float, returns 0. (this is current sqlite
* behavior when asking for an number when there is not one, it will
* possibly change in the future if we start caching stuff).
*/
double getAnnotationDouble(in nsIURI aURI, in AUTF8String aName);
/**
* Same as getAnnotationString but for binary data. This also returns the
* MIME type.
*/
void getAnnotationBinary(in nsIURI aURI, in AUTF8String aName,
[array,size_is(aDataLen)] out octet aData,
out PRUint32 aDataLen,
out AUTF8String aMimeType);
/**
* Retrieves info about an existing annotation. aMimeType will be empty
* if the value was not binary data.
*
* aStorageType will be one of mozIStorageValueArray.VALUE_TYPE_* and
* indicates how the value is stored (if you want to determine whether
* the data is binary, etc.)
*
* example JS:
* var flags = {}, exp = {}, mimeType = {};
* annotator.getAnnotationInfo(myURI, "foo", flags, exp, mimeType);
* // now you can use 'exp.value' and 'flags.value'
*/
void getAnnotationInfo(in nsIURI aURI, in AUTF8String aName,
out PRInt32 aFlags, out PRInt32 aExpiration,
out AUTF8String aMimeType, out PRInt32 aStorageType);
/**
* Returns a list of all URIs having a given annotation.
*/
void getPagesWithAnnotation(in AUTF8String name,
out PRUint32 resultCount,
[retval, array, size_is(resultCount)] out nsIURI results);
/**
* COMArray version of getPagesWithAnnotation for easier memory
* management from C++ code;
*/
[noscript] void GetPagesWithAnnotationCOMArray(in AUTF8String aName,
in URIArray aResults);
/**
* Get the names of all annotations for this URI.
*
* example JS:
* var annotations = annotator.getPageAnnotations(myURI, {});
* You probably don't want to use this from C++, use
* GetPageAnnotationsTArray instead.
*/
void getPageAnnotationNames(in nsIURI aURI, out PRUint32 count,
[retval, array, size_is(count)] out nsIVariant result);
/**
* TArray version of getPageAnnotationNames for ease of use in C++ code.
*/
[noscript] void GetPageAnnotationNamesTArray(in nsIURI aURI, in CStringArray aResult);
/**
* Test for annotation existance.
*/
boolean hasAnnotation(in nsIURI aURI, in AUTF8String aName);
/**
* Removes a specific annotation. Succeeds even if the annotation is
* not found.
*/
void removeAnnotation(in nsIURI aURI, in AUTF8String aName);
/**
* Removes all annotations for the given page.
* We may want some other similar functions to get annotations with given
* flags (once we have flags defined).
*/
void removePageAnnotations(in nsIURI aURI);
/**
* Copies all annotations from the source to the destination URI. If the
* destination already has an annotation with the same name as one on the
* source, it will be overwritten if aOverwriteDest is set. Otherwise,
* the destination URIs will be preferred.
*
* All the source annotations will stay as-is. If you don't want them
* any more, use removePageAnnotations on that URI.
*/
void copyAnnotations(in nsIURI aSourceURI, in nsIURI aDestURI,
in boolean aOverwriteDest);
/**
* Adds an annotation observer. The annotation service will keep an owning
* reference to the observer object.
*/
void addObserver(in nsIAnnotationObserver aObserver);
/**
* Removes an annotaton observer previously registered by addObserver.
*/
void removeObserver(in nsIAnnotationObserver aObserver);
/**
* Returns a URI that can be used to access the given binary annotation.
* This function does NOT check that the annotation exists. Also, note that
* you can only load URIs for annotations that have have a valid MIME type
* set by setAnnotationBinary. No non-URI valid chars in name, especially
* colon, which will mess up parsing.
*/
nsIURI getAnnotationURI(in nsIURI aURI, in AUTF8String aName);
};

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

@ -1,261 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** 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 Places code
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@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;
[scriptable, uuid(b7fc8b9b-d85f-4d89-9b2a-0e67bd6e8d78)]
interface nsIFaviconService : nsISupports
{
/**
* Declares that a given page uses a favicon with the given URI.
*
* You needn't have specified any data at this point. An entry linking the
* favicon with the page will be create with no data. You can populate it
* later with SetFaviconData. However, any favicons not associated with a
* visited web page, a bookmark, or a "place:" URI will be expired when
* history cleanup is done * (typically at app shutdown, but also possibly
* if the user clears their * cache or history).
*
* This will send out history notifications if the new favicon has any data.
* This means that you should try to set data first if you have it, otherwise
* the page might not get a notification sent for it since data setting does
* not send notifications.
*
* @param aPage
* URI of the page whose favicon is being set.
* @param aFavicon
* URI of the favicon to associate with the page.
*/
void setFaviconUrlForPage(in nsIURI aPage, in nsIURI aFavicon);
/**
* Same as SetFaviconUrlForPage except that this also attempts to set the
* data by loading the favicon URI. An async request will be created for
* this URI and if the data is available, it will asynchronously get
* saved in the database without any further work from the caller.
*
* If the icon data already exists, we won't normally try to re-load the
* icon from the net (or more likely the cache). If the icon is in the
* failed favicon cache we won't do anything. Use forceReload to force
* a reload of the data. This will remove the favicon from the failed
* cache. If it then fails again, it will be re-added to the failed cache.
*
* SetFaviconUrlForPage and SetFaviconData will take any URL you provide
* and save it. This function is intended for automatic usage, and will
* only save favicons for "good" URLs, as defined by what gets added to
* history. For "bad" URLs, this function will succeed and do nothing.
* This function will also ignore favicons that are data URLs. Icons that
* fail to load will automatically be added to the failed favicon cache.
*
* This function will not save favicons for non-bookmarked URLs when
* history is disabled (expiration time is 0 days). The rest of the functions
* here will always store favicons even when history is disabled.
*
* @param aPage
* URI of the page whose favicon is being set.
* @param aFavicon
* URI of the favicon to associate with the page.
* @param aForceReload
* Unset is normal behavior, we will only try to reload the favicon
* if we don't have it or if it has expired from the cache. If set,
* it will always try to reload the favicon.
*/
void setAndLoadFaviconForPage(in nsIURI aPage, in nsIURI aFavicon,
in boolean aForceReload);
/**
* Stores the data of a given favicon. You must specify the MIME type
* unless you're clearing the data.
*
* You can set the data even if you haven't called SetFaviconUrlForPage
* yet. It will be stored but will not be associated with any page.
* However, any favicons not associated with a visited web page, bookmark,
* or "place:" URI will be expired when history cleanup is done. This might
* be done at any time on a timer, so you should not let the message loop
* run between calls or your icon may get deleted.
*
* It is best to set the favicon data, and then associate it with a page.
* This will make the notifications more efficient since the icon will
* already have data when the set favicon observer messages goes out.
*
* The expiration time is stored. This will be used if you call
* SetAndLoadFaviconForPage to see whether the data needs reloading.
*
* Do not use this function for chrome: icon URLs. You should reference the
* chrome image yourself. The GetFaviconLinkForIcon/Page will ignore any
* associated data if the favicon URI is "chrome:" and just return the same
* chrome URI.
*
* This function does NOT send out notifications that the data has changed.
* Potentially, many pages could be referencing the favicon and they could
* be visible in a history view or toolbar. But sending out those
* notifications is very intensive. Those pages will keep the old icon
* until they have been refreshed by other means.
*
* @param aFavicon
* URI of the favicon whose data is being set.
* @param aData
* Binary contents of the favicon to save
* @param aDataLength
* Length of binary data
* @param aMimeType
* MIME type of the data to store. This is important so that we know
* what to report when the favicon is used.
* @param aExpiration
* Time in microseconds since the epoch when this favicon expires.
* Until this time, we won't try to load it again.
*/
void setFaviconData(in nsIURI aFavicon,
[const,array,size_is(aDataLen)] in octet aData,
in unsigned long aDataLen, in AUTF8String aMimeType,
in PRTime aExpiration);
/**
* Retrieves the given favicon data. Throws if we don't have data.
*
* If there is no data but we have an entry for this favicon, aDataLen will
* be 0 and aData will be NULL.
*
* @param aFavicon
* URL of the favicon whose data is being read
* @param aData
* Output parameter where the binary favicon data will be placed.
* This will be null if we have this URL but have no data associated
* with it.
* @param aDataLen
* Output parameter where the size of the binary data will be placed.
* @param aMimeType
* Output parameter where the MIME type will be placed.
* @throws NS_ERROR_NOT_AVAILABLE
* Thrown when we have never heard of this favicon URL.
*/
void getFaviconData(in nsIURI aFavicon,
out AUTF8String aMimeType,
out unsigned long aDataLen,
[array,retval,size_is(aDataLen)] out octet aData);
/**
* Retrieves the URL of the favicon for the given page.
*
* @param aPage
* URI of the page whose favicon is desired
* @returns The URI of the favicon associated with that page. Returning a
* URI here does NOT mean that we have data for this favicon, only
* that we know what the favicon should be.
* @throws NS_ERROR_NOT_AVAILABLE
* When the page is not found or it has no favicon.
*/
nsIURI getFaviconForPage(in nsIURI aPage);
/**
* For a given page, this will give you a URI that, when displayed in chrome,
* will result in the given page's favicon. Unlike the other get functions,
* we needn't have heard of the page or its favicon: the default one will
* be returned in this case.
*
* @see getFaviconLinkForIcon
* This function only adds the extra level of indirection, looking up
* the favicon based on the page URI and using the default if not found.
*
* @param aPage
* URI of the page whose favicon is desired
* @returns A URI that will give you the icon image. This is NOT the URI of
* the icon as set on the page, but a URI that will give you the
* data out of the favicon service. For a normal page with a
* favicon we've stored, this will be an annotation URI which will
* then cause the corresponding favicon data to be loaded from this
* service. For pages where we don't have a favicon, this will be a
* chrome URI of the default icon for a web page.
*/
nsIURI getFaviconImageForPage(in nsIURI aPage);
/**
* For a given icon URI, this will return a URI that will result in the image.
* In most cases, this is an annotation URI. For chrome, this will do nothing
* and return the input URI. For NULL input, this will return the URI of
* the default favicon.
*
* @param aIcon
* The URL of an icon in the favicon service. Can be NULL.
* @returns A URI that will load the desired icon. This is NOT the URI of the
* icon as set on the page, but a URI that will give you the data
* out of the favicon service. For a normal page with a favicon
* we've stored, this will be an annotation URI which will then
* cause the corresponding favicon data to be loaded from this
* service. For pages where we don't have a favicon, this will be a
* chrome URI of the default icon for a web page. For chrome, the
* output will be the same as the input. For NULL input, this will
* be the URI of the default favicon.
*
* No validity checking is done. If you pass an icon URI that we've
* never seen, you'll get back a URI that references an invalid
* icon. The moz-anno protocol handler's special case for "favicon"
* annotations will detect most invalid icons and it will resolve to
* the default icon, although without caching. For invalid chrome
* URIs, you'll get a broken image.
*/
nsIURI getFaviconLinkForIcon(in nsIURI aIcon);
/**
* Adds a given favicon's URI to the failed favicon cache.
*
* The lifespan of the favicon cache is up to the caching system. This cache
* will also be written to if you use setAndLoadFaviconForPage and it
* encounters an error.
*
* @see isFailedFavicon
*/
void addFailedFavicon(in nsIURI aIcon);
/**
* Removes the given favicon from the failed favicon cache. If the icon is
* not in the cache, this function will silently succeed.
*/
void removeFailedFavicon(in nsIURI aIcon);
/**
* Checks to see if this favicon is in the failed favicon cache. Returns true
* if the favicon is in the failed cache, meaning you probably shouldn't try
* to load it. A false return value means that it's worth trying to load it.
* This allows you to avoid trying to load "foo.com/favicon.ico" for every
* page on a site that doesn't have a favicon.
*/
boolean isFailedFavicon(in nsIURI aIcon);
};

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

@ -1,146 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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 Places code
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Annie Sullivan <annie.sullivan@gmail.com>
* Joe Hughes <joe@retrovirus.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"
#include "nsIRemoteContainer.idl"
interface nsIURI;
[scriptable, uuid(1e66ec55-87fa-45c2-a912-dd44afb06922)]
interface nsILivemarkService : nsIRemoteContainer
{
/**
* Creates a new livemark
* @param folder The id of the parent folder
* @param name The name to show when displaying the livemark
* @param siteURI The URI of the site the livemark was created from
* @param feedURI The URI of the actual RSS feed
* @param index The index to insert at, or -1 to append
* @returns the ID of the folder for the livemark
*/
PRInt64 createLivemark(in PRInt64 folder,
in AString name,
in nsIURI siteURI,
in nsIURI feedURI,
in PRInt32 index);
/**
* Determines whether the folder with the given folder ID identifies
* a livemark container.
*
* @param folder A folder ID
*
* @returns true if the given folder is a livemark folder, or
* false otherwise
*
* @throws NS_ERROR_INVALID_ARG if the folder ID isn't known
*/
boolean isLivemark(in PRInt64 folder);
/**
* Gets the URI of the website associated with a livemark container.
*
* @param container The folder ID of a livemark container
*
* @returns nsIURI representing the URI of the website; if the livemark
* container doesn't have a valid site URI, null will be returned
*
* @throws NS_ERROR_INVALID_ARG if the folder ID isn't known or identifies
* a folder that isn't a livemark container
* @throws NS_ERROR_MALFORMED_URI if the site URI annotation has
* somehow been corrupted (and can't be turned into an nsIURI)
*/
nsIURI getSiteURI(in PRInt64 container);
/**
* Sets the URI of the website associated with a livemark container.
*
* @param container The folder ID of a livemark container
* @param siteURI nsIURI object representing the site URI, or null
* to clear the site URI for this livemark container
*
* @throws NS_ERROR_INVALID_ARG if the folder ID isn't known or identifies
* a folder that isn't a livemark container; also if the siteURI
* argument isn't a valid nsIURI object (or null)
*/
void setSiteURI(in PRInt64 container, in nsIURI siteURI);
/**
* Gets the URI of the syndication feed associated with a livemark container.
*
* @param container The folder ID of a livemark container
*
* @returns nsIURI representing the URI of the feed; if the livemark
* container doesn't have a valid feed URI, null will be returned
* of the nsIURI object returned will be the empty string.
*
* @throws NS_ERROR_INVALID_ARG if the folder ID isn't known or identifies
* a folder that isn't a livemark container
* @throws NS_ERROR_MALFORMED_URI if the site URI annotation has
* somehow been corrupted (and can't be turned into an nsIURI)
*/
nsIURI getFeedURI(in PRInt64 container);
/**
* Sets the URI of the feed associated with a livemark container.
*
* NOTE: The caller is responsible for reloading the livemark after
* changing its feed URI (since the contents are likely to be different
* given a different feed).
*
* @param container The folder ID of a livemark container
* @param feedURI nsIURI object representing the syndication feed URI
*
* @throws NS_ERROR_INVALID_ARG if the folder ID isn't known or identifies
* a folder that isn't a livemark container; also if the feedURI
* argument isn't a valid nsIURI object
*/
void setFeedURI(in PRInt64 container, in nsIURI feedURI);
/**
* Reloads all livemark subscriptions, whether or not they've expired.
*/
void reloadAllLivemarks();
/**
* Reloads the livemark with this folder ID, whether or not it's expired.
* @param folderID The ID of the folder to be reloaded
*/
void reloadLivemarkFolder(in PRInt64 folderID);
};

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

@ -1,507 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; 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 Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com> (original author)
* Joe Hughes <joe@retrovirus.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"
%{C++
#include "nsTArray.h"
#include "prtypes.h"
%}
interface nsIFile;
interface nsIURI;
interface nsITransaction;
[ptr] native PRInt64Array(nsTArray<PRInt64>);
/**
* Observer for bookmark changes.
*/
[scriptable, uuid(224f8162-4da8-45eb-8187-a8ba3a3db8e5)]
interface nsINavBookmarkObserver : nsISupports
{
/**
* Notify this observer that a batch transaction has started.
* Other notifications will be sent during the batch change,
* but the observer is guaranteed that onEndUpdateBatch() will be called
* at the completion of changes.
*/
void onBeginUpdateBatch();
/**
* Notify this observer that a batch transaction has ended.
*/
void onEndUpdateBatch();
/**
* Notify this observer that the bookmark was added. Called after the actual
* add took place. The rest of the bookmarks will be shifted down, but no
* additional notifications will be sent.
*
* @param bookmark The bookmark item that was added.
* @param folder The folder that the item was added to.
* @param index The item's index in the folder.
*/
void onItemAdded(in nsIURI bookmark, in PRInt64 folder, in PRInt32 index);
/**
* Notify this observer that the bookmark was removed. Called after the
* actual remove took place. The bookmarks following the index will be
* shifted up, but no additional notifications will be sent.
*
* @param bookmark The bookmark item will be removed.
* @param folder The folder that the item was removed from.
* @param index The bookmark's index in the folder.
*/
void onItemRemoved(in nsIURI bookmark, in PRInt64 folder, in PRInt32 index);
/**
* Notify this observer that a bookmark's information has changed. This
* will be called whenever any attributes like "title" are changed.
*
* @param bookmark The bookmark which changed.
* @param property The property which changed.
*
* property = "cleartime" (history was deleted, there is no last visit date):
* value = none
* property = "title": value = new title
* property = "favicon": value = new "moz-anno" URL of favicon image
*/
void onItemChanged(in nsIURI bookmark, in ACString property,
in AString value);
/**
* Notify that the item was visited. Normally in bookmarks we use the last
* visit date, and normally the time will be a new visit that will be more
* recent, but this is not guaranteed. You should check to see if it's
* actually more recent before using this new time.
*
* @see onItemChanged properth = "cleartime" for when all visit dates are
* deleted for the URI.
*/
void onItemVisited(in nsIURI bookmark, in PRInt64 aVisitID, in PRTime time);
/**
* Notify this observer that a bookmark has been replaced.
*
* @param folder The folder in which the bookmark was replaced
* @param item The item which was replaced
* @param newItem The new item which replaced item
*/
void onItemReplaced(in PRInt64 folder, in nsIURI item, in nsIURI newItem);
/**
* Notify this observer that a bookmark folder has been added.
* @param folder The id of the folder that was added.
* @param parent The id of the folder's parent.
* @param index The folder's index inside its parent.
*/
void onFolderAdded(in PRInt64 folder, in PRInt64 parent, in PRInt32 index);
/**
* Notify this observer that a bookmark folder has been removed.
* @param folder The id of the folder that was removed.
* @param parent The id of the folder's old parent.
* @param index The folder's old index in its parent.
*/
void onFolderRemoved(in PRInt64 folder, in PRInt64 parent, in PRInt32 index);
/**
* Notify this observer that a bookmark folder has been moved.
* @param folder The id of the folder that was moved.
* @param oldParent The id of the folder's old parent.
* @param oldIndex The folder's old index inside oldParent.
* @param newParent The id of the folder's new parent.
* @param newIndex The folder's index inside newParent.
*/
void onFolderMoved(in PRInt64 folder,
in PRInt64 oldParent, in PRInt32 oldIndex,
in PRInt64 newParent, in PRInt32 newIndex);
/**
* Notify this observer that a bookmark folder's information has changed.
* This will be called whenever any attributes like "title" are changed.
* @param folder The id of the folder that was changed.
* @param property The property that was changed.
*/
void onFolderChanged(in PRInt64 folder, in ACString property);
/**
* Notify this observer that a separator has been added.
* @param parent The id of the separator's parent.
* @param index The separator's index inside its parent.
*/
void onSeparatorAdded(in PRInt64 parent, in PRInt32 index);
/**
* Notify this observer that a separator has been removed.
* @param parent The id of the separator's parent.
* @param index The separator's old index in its parent.
*/
void onSeparatorRemoved(in PRInt64 parent, in PRInt32 index);
};
/**
* The BookmarksService interface provides methods for managing bookmarked
* history items. Bookmarks consist of a set of user-customizable
* folders. A URI in history can be contained in one or more such folders.
*/
[scriptable, uuid(860d786d-9bba-4011-a396-486a87af8f07)]
interface nsINavBookmarksService : nsISupports
{
/**
* The folder ID of the Places root.
*/
readonly attribute PRInt64 placesRoot;
/**
* The folder ID of the bookmarks root.
*/
readonly attribute PRInt64 bookmarksRoot;
/**
* The folder ID of the personal toolbar root.
*/
readonly attribute PRInt64 toolbarRoot;
/**
* The folder ID of the top-level folders that contain the tag "folders".
*
* NOTE: This isn't wired up yet, so don't try to use it for anything until
* bug 329961 is marked resolved.
*/
readonly attribute PRInt64 tagRoot;
/**
* Inserts a child item into the given folder. If this item already exists in
* the given folder, it will be moved to the new position.
* @param folder The id of the parent folder
* @param item The URI to insert
* @param index The index to insert at, or -1 to append
*/
void insertItem(in PRInt64 folder, in nsIURI item, in PRInt32 index);
/**
* Removes a child item from the given folder.
* @param folder The folder to remove the child from
* @param item The child item to remove
*/
void removeItem(in PRInt64 folder, in nsIURI child);
/**
* Replace an item with a different item.
* @param folder The folder which contains the item to replace
* @param item The item which should be replaced
* @param newItem The new item
*/
void replaceItem(in PRInt64 folder, in nsIURI item, in nsIURI newItem);
/**
* Creates a new child folder and inserts it under the given parent.
* @param parent The id of the parent folder
* @param name The name of the new folder
* @param index The index to insert at, or -1 to append
* @returns the ID of the newly-inserted folder
*/
PRInt64 createFolder(in PRInt64 parent, in AString name, in PRInt32 index);
/**
* Wrapper for container services. Creates a folder under the given
* parent and sets the container type.
* @param parent The id of the parent folder
* @param name The name of the new folder
* @param type The type of container to insert
* @param index The index to insert at, or -1 to append
* @returns the ID of the newly-inserted folder
*/
PRInt64 createContainer(in PRInt64 parent, in AString name,
in AString type, in PRInt32 index);
/**
* Removes a folder from the bookmarks tree.
* @param folder The id of the folder to remove.
*/
void removeFolder(in PRInt64 folder);
/**
* Gets an undo-able transaction for removing a folder from the bookmarks
* tree.
* @param folder The id of the folder to remove.
* @returns An object implementing nsITransaction that can be used to undo
* or redo the action.
*
* This method exists because complex delete->undo operations rely on
* recreated folders to have the same ID they had before they were deleted,
* so that any other items deleted in different transactions can be
* re-inserted correctly. This provides a safe encapsulation of this
* functionality without exposing the ability to recreate folders with
* specific IDs (potentially dangerous if abused by other code!) in the
* public API.
*/
nsITransaction getRemoveFolderTransaction(in PRInt64 folder);
/**
* Convenience function for container services. Removes
* all children of the given folder.
* @param folder The id of the folder to remove children from.
*/
void removeFolderChildren(in PRInt64 folder);
/**
* Moves a folder to a different container, preserving its contents.
* @param folder The folder to move
* @param newParent The id of the folder's new parent
* @param index The folder's index under newParent, or -1 to append
*/
void moveFolder(in PRInt64 folder, in PRInt64 newParent, in PRInt32 index);
/**
* Returns the ID of a child folder with the given name. This does not
* recurse, you have to give it an immediate sibling of the given folder.
* If the given subfolder doesn't exist, it will return 0.
* @param folder Parent folder whose children we will search
* @param subFolder Name of the folder to search for in folder
*/
PRInt64 getChildFolder(in PRInt64 folder, in AString subFolder);
/**
* Inserts a bookmark separator into the given folder at the given index.
* The separator can be removed using removeChildAt().
* @param folder Parent folder of the separator
* @param index The separator's index under folder, or -1 to append
*/
void insertSeparator(in PRInt64 folder, in PRInt32 index);
/**
* Removes any type of child (item, folder, or separator) at the given index.
* @param folder The folder to remove a child from
* @param index The index of the child to remove
*/
void removeChildAt(in PRInt64 folder, in PRInt32 index);
/**
* Set the history/bookmark title for a URI. The new title will be used
* anywhere the URI is shown in bookmarks or history.
* @param uri The URI whose name should be set
* @param title The new title for the URI
*/
void setItemTitle(in nsIURI uri, in AString title);
/**
* Get the history/bookmark title for the URI.
*
* If no item title is available (for instance, if the URI doesn't appear
* in the bookmarks or history), it will return a void string (null in JS).
*
* @param uri The URI whose title should be retrieved
* @returns The title for the URI.
*/
AString getItemTitle(in nsIURI uri);
/**
* Set the title for a bookmark folder.
* @param folder The folder whose title should be set
* @param title The new title for the folder
*/
void setFolderTitle(in PRInt64 folder, in AString title);
/**
* Get the title for a bookmark folder. Throws an invalid argument
* exception if it can't find a folder with the given ID.
*
* @param folder The folder whose title should be retrieved
* @returns The title for the folder
*/
AString getFolderTitle(in PRInt64 folder);
/**
* Get the place: url for a bookmark folder. You can use this value to
* get/set the icon for a folder or to associate other data with it using
* the annotation service. Its important that you use this function instead
* of just serializing the query/options for a given folder because you
* may have different options or query parameters. This function will give
* the canonical value.
* @param folder The folder whose URI should be retrieved
* @returns The URI for the folder
*/
nsIURI getFolderURI(in PRInt64 folder);
/**
* Checks whether a folder has read-only children. This property is
* defined by the nsIBookmarsContainer for the folder, if one exists.
* If this is set to true, UI should not allow the user to add, remove,
* or reorder children in this folder. The default for all folders is false.
*/
boolean getFolderReadonly(in PRInt64 folder);
/**
* Returns true if the given URI is in any bookmark folder. If you want the
* results to be redirect-aware, use getBookmarkedURIFor()
*/
boolean isBookmarked(in nsIURI uri);
/**
* Used to see if the given URI is bookmarked, or any page that redirected to
* it is bookmarked. For example, if I bookmark "mozilla.org" by manually
* typing it in, and follow the bookmark, I will get redirected to
* "www.mozilla.org". Logically, this new page is also bookmarked. This
* function, if given "www.mozilla.org", will return the URI of the bookmark,
* in this case "mozilla.org".
*
* If there is no bookmarked page found, it will return NULL.
*/
nsIURI getBookmarkedURIFor(in nsIURI uri);
/**
* "Changes" the URI of a bookmark. Since URIs are the unique
* identifiers of bookmarks in this system, what this really means is
* that all the metadata attached to oldURI will be copied onto newURI,
* and oldURI will be deleted from the bookmark system. If newURI
* is already bookmarked, the metadata from oldURI will overwrite
* the corresponding metadata on newURI. Any annotations on oldURI
* will be copied to newURI (a copy will remain on oldURI).
*/
void changeBookmarkURI(in nsIURI oldURI, in nsIURI newURI);
/**
* Returns the list of folder ids that contain the given URI.
*/
void getBookmarkFolders(in nsIURI uri, out PRUint32 count,
[array, retval, size_is(count)] out PRInt64 folders);
/**
* TArray version of getBookmarkFolders for ease of use in C++ code.
* Pass in a reference to a TArray; it will get cleared and filled with
* the resulting list of folder IDs.
*/
[noscript] void getBookmarkFoldersTArray(in nsIURI aURI,
in PRInt64Array aResult);
/**
* Returns the index of the given item in the given folder.
* Returns -1 if the item is not present in the folder.
*/
PRInt32 indexOfItem(in PRInt64 folder, in nsIURI uri);
/**
* Returns the index of the given subfolder in its parent.
* Returns -1 if the subfolder is not present in the parent folder.
*/
PRInt32 indexOfFolder(in PRInt64 parent, in PRInt64 folder);
/**
* Associates the given keyword with the given URI.
*
* Use an empty keyword to clear the keyword associated with the URI. Use an
* empty URI to clear the URI associated with that keyword. In both of these
* cases, succeeds but does nothing if the URL/keyword is not found.
*
* When setting a keyword (both URI and keyword are specified), the URI must
* be bookmarked for the keyword to be persistent.
*/
void setKeywordForURI(in nsIURI uri, in AString keyword);
/**
* Retrieves the keyword for the given URI. Will be void string
* (null in JS) if no such keyword is found.
*/
AString getKeywordForURI(in nsIURI uri);
/**
* Returns the URI associated with the given keyword. Empty if no such
* keyword is found.
*/
nsIURI getURIForKeyword(in AString keyword);
/**
* Adds a bookmark observer. If ownsWeak is false, the bookmark service will
* keep an owning reference to the observer. If ownsWeak is true, then
* aObserver must implement nsISupportsWeakReference, and the bookmark
* service will keep a weak reference to the observer.
*/
void addObserver(in nsINavBookmarkObserver observer, in boolean ownsWeak);
/**
* Removes a bookmark observer.
*/
void removeObserver(in nsINavBookmarkObserver observer);
/**
* Causes observers to be notified of a beginUpdateBatch when a lot of things
* are about to change. Calls can be nested, observers will only be
* notified when all batches begin/end.
*
* It is EXTREMELY IMPORTANT that you call EndUpdateBatch for each call to
* beginUpdateBatch. If you don't do this, certain parts of the UI will not
* get updated and any changes to bookmarks will not get written to disk.
* From C++ code inside the places component, use nsBookmarksUpdateBatcher
* defined in nsNavBookmarks.h to scope batches. For JS or from other
* components, just please be very careful to close the batch, especially
* when encountering an error and returning early.
*/
void beginUpdateBatch();
/**
* Causes observers to be notified of an endUpdateBatch when a batch is
* done changing. Should match beginUpdateBatch or bad things will happen.
*/
void endUpdateBatch();
/**
* Loads the given bookmarks.html file and merges it with the current
* bookmarks hierarchy.
*/
void importBookmarksHTML(in nsIURI url);
/**
* Loads the given bookmarks.html file and puts it in the given folder
*/
void importBookmarksHTMLToFolder(in nsIURI url, in PRInt64 folder);
/**
* Saves the current bookmarks hierarchy to a bookmarks.html file.
*/
void exportBookmarksHTML(in nsIFile file);
};

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

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

@ -1,147 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; 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 Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Annie Sullivan <annie.sullivan@gmail.com> (original author)
*
* 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 nsINavHistoryContainerResultNode;
interface nsINavHistoryQueryOptions;
/**
* The Remote Container interface provides a base class for services that want
* to provide containers for bookmarks. Some examples of possible services are
* the livemarks service and the filesystem.
*
* There are two primary modes of operation: container services might create
* actual bookmarks, or they might fill containers on the fly as needed. The
* livemarks service, for example, queries the feed from time to time and
* creates actual bookmarks in the folder corresponding to the feed. This way
* the items are persistent even if the user is offline, and can be searched.
* In this mode, the service just looks for moves and deletes to update the
* corresponding bookkeeping information. It can use the normal population
* method provided by the bookmark service and need not do any work for the
* onContainerOpen message.
*
* Such a bookmark-based container service might listen for onContainerOpening
* notifications messages to see whether
*
* Persistent bookmarks are not appropriate for more short-lived data, such as
* the filesystem interface. In this case, the service can fill result nodes
* directly into the container when it is being opened. It can use the property
* bag on every result node to store data associated with each item, such as
* full path on disk. It would create additional containers for each folder,
* resgistered to its service. These dynamic containers are not bookmark
* folders in contrast to the initial item.
*/
[scriptable, uuid(45bf2020-9683-498c-9638-f08130c4151d)]
interface nsIRemoteContainer : nsISupports
{
/**
* Called when the given container is about to be populated so that the
* service can populate the container if necessary.
*
* @param container The container node for the container being opened.
* If the node type is a bookmarks container, you can
* QI it to nsINavHistoryFolderResultNode and access the
* folder ID, etc. Note that all result nodes implement
* a property bag if you need to store state.
* @param options The options used to generate this query. Containers
* should follow these when possible, for example,
* whether to expand queries, etc. Implementations should
* use this when possible if adding query and folder nodes
* to the container. DO NOT MODIFY THIS VALUE.
*
* UNTESTED container API functions are commented out until they can be
* adequately tested.
*/
/*void onContainerOpening(in nsINavHistoryContainerResultNode container,
in nsINavHistoryQueryOptions options);*/
/**
* Called when the given container has just been hidden so that the service
* can do any necessary cleanup. This is NOT guaranteed to get called. In
* particular, if the query just goes away (like the user switched views on
* the places page) you will not get this call. This only happens when the
* container itself goes from the open state to the closed state. A serviced
* with large numbers of dynamically populated items might use this to do
* some cleanup so those items don't hang around
*
* @param container The container node of the container being closed. The
* service need not worry about removing any created nodes,
* they will be automatically removed when this call
* completes.
*
* UNTESTED container API functions are commented out until they can be
* adequately tested.
*/
/*void onContainerClosed(in nsINavHistoryContainerResultNode container);*/
/**
* Called when the given container is about to be deleted, so
* that the service can do any necessary cleanup.
* Called BEFORE the container is deleted, so that the service
* can still reference it.
* @param container The folderId of the bookmark folder
* representing the container to be deleted.
*/
void onContainerRemoving(in PRInt64 container);
/**
* Called when the given container has just been moved, in case
* the service needs to do any bookkeeping.
* Called AFTER the container has been moved, so the service can
* get the new URI.
* @param container The folderId of the bookmark folder
* representing the container to be moved.
* @param newFolder The folderId of the new parent folder
* for the container.
* @param newIndex The index the container will be inserted at,
* or -1 for append.
*/
void onContainerMoved(in PRInt64 container,
in PRInt64 newFolder, in PRInt32 newIndex);
/**
* Returns true if containers of this type should not expose UI for
* inserting, moving, or deleting children.
*/
readonly attribute boolean childrenReadOnly;
};

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

@ -1 +0,0 @@
Makefile

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

@ -1,107 +0,0 @@
#
# ***** 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 Places code
#
# The Initial Developer of the Original Code is
# Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2005
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Brett Wilson <brettw@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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = places
LIBRARY_NAME = places
LIBXUL_LIBRARY = 1
EXPORT_LIBRARY = 1
MODULE_NAME = nsPlacesModule
IS_COMPONENT = 1
REQUIRES = xpcom \
string \
history \
docshell \
rdf \
dom \
morkreader \
pref \
necko \
intl \
layout \
locale \
unicharutil \
autocomplete \
storage \
uconv \
htmlparser \
content \
txmgr \
caps \
xpconnect \
js \
nkcache \
widget \
url-classifier \
microsummaries \
$(NULL)
CPPSRCS = \
nsAnnoProtocolHandler.cpp \
nsAnnotationService.cpp \
nsBookmarksHTML.cpp \
nsFaviconService.cpp \
nsNavHistory.cpp \
nsNavHistoryAutoComplete.cpp \
nsNavHistoryExpire.cpp \
nsNavHistoryQuery.cpp \
nsNavHistoryResult.cpp \
nsNavBookmarks.cpp \
nsLivemarkService.cpp \
nsBookmarksFeedHandler.cpp \
nsMaybeWeakPtr.cpp \
nsMorkHistoryImporter.cpp \
nsPlacesModule.cpp \
$(NULL)
include $(topsrcdir)/config/rules.mk
EXTRA_DSO_LDOPTS = \
$(DEPTH)/db/morkreader/$(LIB_PREFIX)morkreader_s.$(LIB_SUFFIX) \
$(MOZ_UNICHARUTIL_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
LOCAL_INCLUDES += -I$(srcdir)/../../build

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

@ -1,245 +0,0 @@
//* -*- 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 Mozilla Annotation Service
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
/**
* Implementation of moz-anno: URLs for accessing annotation values. This just
* reads binary data from the annotation service.
*
* There is a special case for favicons. Annotation URLs with the name "favicon"
* will be sent to the favicon service. If the favicon service doesn't have the
* data, a stream containing the default favicon will be returned.
*/
#include "nsAnnoProtocolHandler.h"
#include "nsFaviconService.h"
#include "nsIChannel.h"
#include "nsIInputStreamChannel.h"
#include "nsILoadGroup.h"
#include "nsIStandardURL.h"
#include "nsIStringStream.h"
#include "nsISupportsUtils.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsStringStream.h"
NS_IMPL_ISUPPORTS1(nsAnnoProtocolHandler, nsIProtocolHandler)
// nsAnnoProtocolHandler::GetScheme
NS_IMETHODIMP
nsAnnoProtocolHandler::GetScheme(nsACString& aScheme)
{
aScheme.AssignLiteral("moz-anno");
return NS_OK;
}
// nsAnnoProtocolHandler::GetDefaultPort
//
// There is no default port for annotation URLs
NS_IMETHODIMP
nsAnnoProtocolHandler::GetDefaultPort(PRInt32 *aDefaultPort)
{
*aDefaultPort = -1;
return NS_OK;
}
// nsAnnoProtocolHandler::GetProtocolFlags
//
// No special protocol flags.
NS_IMETHODIMP
nsAnnoProtocolHandler::GetProtocolFlags(PRUint32 *aProtocolFlags)
{
*aProtocolFlags = (URI_NORELATIVE | URI_NOAUTH);
return NS_OK;
}
// nsAnnoProtocolHandler::NewURI
NS_IMETHODIMP
nsAnnoProtocolHandler::NewURI(const nsACString& aSpec,
const char *aOriginCharset,
nsIURI *aBaseURI, nsIURI **_retval)
{
nsCOMPtr <nsIURI> uri = do_CreateInstance(NS_SIMPLEURI_CONTRACTID);
if (!uri)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = uri->SetSpec(aSpec);
NS_ENSURE_SUCCESS(rv, rv);
*_retval = nsnull;
uri.swap(*_retval);
return NS_OK;
}
// nsAnnoProtocolHandler::NewChannel
//
NS_IMETHODIMP
nsAnnoProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
{
NS_ENSURE_ARG_POINTER(aURI);
nsresult rv;
nsCAutoString path;
rv = aURI->GetPath(path);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAnnotationService> annotationService = do_GetService(
"@mozilla.org/browser/annotation-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// annotation info
nsCOMPtr<nsIURI> annoURI;
nsCAutoString annoName;
rv = ParseAnnoURI(aURI, getter_AddRefs(annoURI), annoName);
NS_ENSURE_SUCCESS(rv, rv);
// get the data from the annotation service and hand it off to the stream
PRUint8* data;
PRUint32 dataLen;
nsCAutoString mimeType;
if (annoName.EqualsLiteral(FAVICON_ANNOTATION_NAME)) {
// special handling for favicons: ask favicon service
nsFaviconService* faviconService = nsFaviconService::GetFaviconService();
if (! faviconService) {
NS_WARNING("Favicon service is unavailable.");
return GetDefaultIcon(_retval);
}
rv = faviconService->GetFaviconData(annoURI, mimeType, &dataLen, &data);
if (NS_FAILED(rv))
return GetDefaultIcon(_retval);
// don't allow icons without MIME types
if (mimeType.IsEmpty()) {
NS_Free(data);
return GetDefaultIcon(_retval);
}
} else {
// normal handling for annotations
rv = annotationService->GetAnnotationBinary(annoURI, annoName, &data,
&dataLen, mimeType);
NS_ENSURE_SUCCESS(rv, rv);
// disallow annotations with no MIME types
if (mimeType.IsEmpty()) {
NS_Free(data);
return NS_ERROR_NOT_AVAILABLE;
}
}
nsCOMPtr<nsIStringInputStream> stream = do_CreateInstance(
NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
NS_Free(data);
return rv;
}
rv = stream->AdoptData((char*)data, dataLen);
if (NS_FAILED(rv)) {
NS_Free(data);
return rv;
}
nsCOMPtr<nsIChannel> channel;
rv = NS_NewInputStreamChannel(getter_AddRefs(channel), aURI, stream, mimeType);
NS_ENSURE_SUCCESS(rv, rv);
*_retval = channel;
NS_ADDREF(*_retval);
return NS_OK;
}
// nsAnnoProtocolHandler::AllowPort
//
// Don't override any bans on bad ports.
NS_IMETHODIMP
nsAnnoProtocolHandler::AllowPort(PRInt32 port, const char *scheme,
PRBool *_retval)
{
*_retval = PR_FALSE;
return NS_OK;
}
// nsAnnoProtocolHandler::ParseAnnoURI
//
// Splits an annotation URL into its URI and name parts
nsresult
nsAnnoProtocolHandler::ParseAnnoURI(nsIURI* aURI,
nsIURI** aResultURI, nsCString& aName)
{
nsresult rv;
nsCAutoString path;
rv = aURI->GetPath(path);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 firstColon = path.FindChar(':');
if (firstColon <= 0)
return NS_ERROR_MALFORMED_URI;
rv = NS_NewURI(aResultURI, Substring(path, firstColon + 1));
NS_ENSURE_SUCCESS(rv, rv);
aName = Substring(path, 0, firstColon);
return NS_OK;
}
// nsAnnoProtocolHandler::GetDefaultIcon
//
// This creates a channel for the default web page favicon.
nsresult
nsAnnoProtocolHandler::GetDefaultIcon(nsIChannel** aChannel)
{
nsresult rv;
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING(FAVICON_DEFAULT_URL));
NS_ENSURE_SUCCESS(rv, rv);
return NS_NewChannel(aChannel, uri);
}

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

@ -1,69 +0,0 @@
//* -*- 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 Mozilla Annotation Service
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
#ifndef nsAnnoProtocolHandler_h___
#define nsAnnoProtocolHandler_h___
#include "nsCOMPtr.h"
#include "nsIAnnotationService.h"
#include "nsIProtocolHandler.h"
#include "nsIURI.h"
#include "nsString.h"
#include "nsWeakReference.h"
// {e8b8bdb7-c96c-4d82-9c6f-2b3c585ec7ea}
#define NS_ANNOPROTOCOLHANDLER_CID \
{ 0xe8b8bdb7, 0xc96c, 0x4d82, { 0x9c, 0x6f, 0x2b, 0x3c, 0x58, 0x5e, 0xc7, 0xea } }
class nsAnnoProtocolHandler : public nsIProtocolHandler, public nsSupportsWeakReference
{
public:
nsAnnoProtocolHandler() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
private:
~nsAnnoProtocolHandler() {}
protected:
nsresult ParseAnnoURI(nsIURI* aURI, nsIURI** aResultURI, nsCString& aName);
nsresult GetDefaultIcon(nsIChannel** aChannel);
};
#endif /* nsAnnoProtocolHandler_h___ */

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

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

@ -1,124 +0,0 @@
//* -*- 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 Mozilla Annotation Service
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
#ifndef nsAnnotationService_h___
#define nsAnnotationService_h___
#include "nsIAnnotationService.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "mozIStorageService.h"
#include "mozIStorageConnection.h"
#include "nsServiceManagerUtils.h"
class nsAnnotationService : public nsIAnnotationService
{
public:
nsAnnotationService();
nsresult Init();
static nsresult InitTables(mozIStorageConnection* aDBConn);
/**
* Returns a cached pointer to the annotation service for consumers in the
* places directory.
*/
static nsAnnotationService* GetAnnotationService()
{
if (! gAnnotationService) {
// note that we actually have to set the service to a variable here
// because the work in do_GetService actually happens during assignment >:(
nsresult rv;
nsCOMPtr<nsIAnnotationService> serv(do_GetService("@mozilla.org/browser/annotation-service;1", &rv));
NS_ENSURE_SUCCESS(rv, nsnull);
// our constructor should have set the static variable. If it didn't,
// something is wrong.
NS_ASSERTION(gAnnotationService, "Annotation service creation failed");
}
// the service manager will keep the pointer to our service around, so
// this should always be valid even if nobody currently has a reference.
return gAnnotationService;
}
NS_DECL_ISUPPORTS
NS_DECL_NSIANNOTATIONSERVICE
private:
~nsAnnotationService();
protected:
nsCOMPtr<mozIStorageService> mDBService;
nsCOMPtr<mozIStorageConnection> mDBConn;
nsCOMPtr<mozIStorageStatement> mDBSetAnnotation;
nsCOMPtr<mozIStorageStatement> mDBGetAnnotation;
nsCOMPtr<mozIStorageStatement> mDBGetAnnotationNames;
nsCOMPtr<mozIStorageStatement> mDBGetAnnotationFromURI;
nsCOMPtr<mozIStorageStatement> mDBGetAnnotationNameID;
nsCOMPtr<mozIStorageStatement> mDBAddAnnotationName;
nsCOMPtr<mozIStorageStatement> mDBAddAnnotation;
nsCOMPtr<mozIStorageStatement> mDBRemoveAnnotation;
nsCOMArray<nsIAnnotationObserver> mObservers;
static nsAnnotationService* gAnnotationService;
static const int kAnnoIndex_ID;
static const int kAnnoIndex_Page;
static const int kAnnoIndex_Name;
static const int kAnnoIndex_MimeType;
static const int kAnnoIndex_Content;
static const int kAnnoIndex_Flags;
static const int kAnnoIndex_Expiration;
nsresult HasAnnotationInternal(PRInt64 aURLID, const nsACString& aName,
PRBool* hasAnnotation, PRInt64* annotationID);
nsresult StartGetAnnotationFromURI(nsIURI* aURI,
const nsACString& aName);
nsresult StartSetAnnotation(nsIURI* aURI,
const nsACString& aName,
PRInt32 aFlags, PRInt32 aExpiration,
mozIStorageStatement** aStatement);
void CallSetObservers(nsIURI* aURI, const nsACString& aName);
static nsresult MigrateFromAlpha1(mozIStorageConnection* aDBConn);
};
#endif /* nsAnnotationService_h___ */

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

@ -1,940 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Vladimir Vukicevic <vladimir@pobox.com>
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Annie Sullivan <annie.sullivan@gmail.com> (modified to work with places)
* Robert Sayre <sayrer@gmail.com>
* Masayuki Nakano <masayuki@d-toybox.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 ***** */
// THE ORIGINAL LOCATION OF THIS CODE IS
// /browser/components/bookmarks/src/nsBookmarksFeedHandler.cpp
#include "nsLivemarkService.h"
#include "nsArrayEnumerator.h"
#include "nsIArray.h"
#include "nsIDOMWindow.h"
#include "nsIObserverService.h"
#include "nsIRDFContainer.h"
#include "nsIRDFContainerUtils.h"
#include "nsIRDFService.h"
#include "nsIRDFXMLSerializer.h"
#include "nsIRDFXMLSource.h"
#include "nsIRDFXMLParser.h"
#include "nsRDFCID.h"
#include "nsISupportsPrimitives.h"
#include "rdf.h"
#include "nsUnicharUtils.h"
#include "nsInt64.h"
#include "nsStringStream.h"
#include "nsIScriptSecurityManager.h"
#include "nsIURL.h"
#include "nsIInputStream.h"
#include "nsNetUtil.h"
#include "nsICachingChannel.h"
#include "nsICacheVisitor.h"
#include "nsIDOMParser.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMNodeList.h"
#include "nsIDOM3Node.h"
#include "nsIDOMDocumentTraversal.h"
#include "nsIDOMTreeWalker.h"
#include "nsIDOMNodeFilter.h"
#include "nsIDOMDocumentFragment.h"
#include "nsIParser.h"
#include "nsParserCIID.h"
#include "nsIFragmentContentSink.h"
#include "nsIContentSink.h"
#include "nsIDocument.h"
#include "nsNavBookmarks.h"
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
static NS_DEFINE_CID(kRDFContainerCID, NS_RDFCONTAINER_CID);
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
////////////////////////////////////////////////////////////////////////
// nsLivemarkLoadListener
//
// An nsIStreamListener implementation that UpdateLivemarkChildren uses
// to aysnchronously fetch and update a livemark's child entries.
//
// This could potentially become a nested class within the livemarks service.
//
class nsLivemarkLoadListener : public nsIStreamListener
{
public:
nsLivemarkLoadListener(nsLivemarkService *aLivemarkService,
nsCOMPtr<nsIAnnotationService> aAnnotationService,
nsLivemarkService::LivemarkInfo * pLivemark)
: mLivemarkService(aLivemarkService), mAnnotationService(aAnnotationService),
mLivemark(pLivemark), mAborted(PR_FALSE)
{
NS_IF_ADDREF(mLivemarkService);
}
virtual ~nsLivemarkLoadListener() {
NS_IF_RELEASE(mLivemarkService);
}
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
void Abort () { mAborted = PR_TRUE; }
protected:
static NS_METHOD StreamReaderCallback(nsIInputStream *in,
void *closure,
const char *fromRawSegment,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount);
NS_METHOD TryParseAsRDF();
NS_METHOD TryParseAsSimpleRSS();
NS_METHOD SetResourceTTL(PRInt32 ttl);
// helpers
NS_METHOD HandleRDFItem (nsIRDFDataSource *aDS, nsIRDFResource *itemResource,
nsIRDFResource *aLinkResource, nsIRDFResource *aTitleResource);
NS_METHOD FindTextInChildNodes (nsIDOMNode *aNode, nsAString &aString);
NS_METHOD ParseHTMLFragment(nsAString &aFragString, nsIDocument* aTargetDocument, nsIDOMNode **outNode);
PRBool IsLinkValid(const PRUnichar *aURI);
nsLivemarkService *mLivemarkService;
nsCOMPtr<nsIAnnotationService> mAnnotationService;
nsRefPtr<nsLivemarkService::LivemarkInfo> mLivemark;
nsCOMPtr<nsIOutputStream> mCacheStream;
nsCOMPtr<nsIScriptSecurityManager> mSecMan;
PRBool mAborted;
nsCString mBody;
};
NS_IMPL_ISUPPORTS2(nsLivemarkLoadListener, nsIStreamListener, nsIRequestObserver)
NS_IMETHODIMP
nsLivemarkLoadListener::OnStartRequest(nsIRequest *aResult, nsISupports *ctxt)
{
if (mAborted)
return NS_ERROR_UNEXPECTED;
mBody.Truncate();
return NS_OK;
}
NS_METHOD
nsLivemarkLoadListener::StreamReaderCallback(nsIInputStream *aInputStream,
void *aClosure,
const char *aRawSegment,
PRUint32 aToOffset,
PRUint32 aCount,
PRUint32 *aWriteCount)
{
nsLivemarkLoadListener *rll = (nsLivemarkLoadListener *) aClosure;
rll->mBody.Append(aRawSegment, aCount);
*aWriteCount = aCount;
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkLoadListener::OnDataAvailable(nsIRequest *aRequest,
nsISupports *aContext,
nsIInputStream *aInputStream,
PRUint32 aSourceOffset,
PRUint32 aCount)
{
PRUint32 totalRead;
return aInputStream->ReadSegments(StreamReaderCallback, (void *)this, aCount, &totalRead);
}
NS_IMETHODIMP
nsLivemarkLoadListener::OnStopRequest(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aStatus)
{
nsresult rv;
if (mAborted) {
mLivemark->locked = PR_FALSE;
return NS_OK;
}
if (NS_FAILED(aStatus)) {
// Something went wrong; try to load again in 5 minutes.
SetResourceTTL (300);
mLivemark->locked = PR_FALSE;
return NS_OK;
}
// enclose all the changes (deletes and a bunch of adds) in a batch to
// avoid UI and DB updates
nsBookmarksUpdateBatcher bookmarksBatch;
// Clear out any child nodes of the livemark folder, since
// they're about to be replaced.
rv = mLivemarkService->DeleteLivemarkChildren(mLivemark->folderId);
if (NS_FAILED(rv)) {
mLivemark->locked = PR_FALSE;
return rv;
}
// Grab the security manager
mSecMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
// We need to parse the returned data here, stored in mBody. We
// try parsing as RDF first, then as Atom and the "simple" RSS
// (the userland 0.91/0.92/2.0 formats)
//
// Try parsing as RDF
rv = TryParseAsRDF();
// Try parsing as Atom/Simple RSS
if (!NS_SUCCEEDED(rv)) {
rv = TryParseAsSimpleRSS();
}
// If we weren't able to load with anything, attach a dummy bookmark
if (!NS_SUCCEEDED(rv)) {
rv = mLivemarkService->InsertLivemarkFailedItem(mLivemark->folderId);
}
// Set an expiration on the livemark, for reloading the data
PRInt32 ttl;
if (NS_FAILED(rv)) {
// if we failed, try again in 1 hour, to avoid trying
// to load a feed that doesn't parse over and over.
ttl = 3600;
} else {
// TODO -- read the pref for livemark reload time and set to max of
// the pref value and 1 minute.
ttl = 3600; // 1 hr default
// ensure that the ttl is at least equal to the cache expiry time, since
// otherwise a reload won't have much effect
nsCOMPtr<nsICachingChannel> channel = do_QueryInterface(aRequest);
if (channel) {
nsCOMPtr<nsISupports> cacheToken;
channel->GetCacheToken(getter_AddRefs(cacheToken));
if (cacheToken) {
nsCOMPtr<nsICacheEntryInfo> entryInfo = do_QueryInterface(cacheToken);
if (entryInfo) {
PRUint32 expiresTime;
if (NS_SUCCEEDED(entryInfo->GetExpirationTime(&expiresTime))) {
PRInt64 temp64, nowtime = PR_Now();
PRUint32 nowsec;
LL_I2L(temp64, PR_USEC_PER_SEC);
LL_DIV(temp64, nowtime, temp64);
LL_L2UI(nowsec, temp64);
if (nowsec >= expiresTime) {
expiresTime -= nowsec;
if (ttl < (PRInt32) expiresTime)
ttl = (PRInt32) expiresTime;
}
}
}
}
}
}
rv = SetResourceTTL(ttl);
if (NS_FAILED(rv)) {
NS_WARNING ("SetResourceTTL failed on Livemark");
}
mLivemark->locked = PR_FALSE;
return NS_OK;
}
/**
* SetResourceTTL: Set the next time we should attempt to reload this
* resource's feed
*/
nsresult
nsLivemarkLoadListener::SetResourceTTL (PRInt32 aTTL)
{
nsresult rv;
PRTime million, temp64, exptime = PR_Now();
LL_I2L (million, PR_USEC_PER_SEC);
LL_I2L (temp64, aTTL);
LL_MUL (temp64, temp64, million);
LL_ADD (exptime, exptime, temp64);
rv = mAnnotationService->SetAnnotationInt64(mLivemark->feedURI,
NS_LITERAL_CSTRING(LMANNO_EXPIRATION),
exptime, 0,
nsIAnnotationService::EXPIRE_NEVER);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
/**
* TryParseAsRDF: attempt to parse the read data in mBody as
* RSS 0.90/1.0 data. This is supposed to be RDF, so we use
* the RDF parser to do our work for us.
*/
nsresult
nsLivemarkLoadListener::TryParseAsRDF ()
{
nsresult rv;
nsCOMPtr<nsIRDFXMLParser> rdfparser(do_CreateInstance("@mozilla.org/rdf/xml-parser;1", &rv));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIRDFDataSource> ds(do_CreateInstance(kRDFInMemoryDataSourceCID, &rv));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStreamListener> listener;
rv = rdfparser->ParseAsync(ds, mLivemark->feedURI, getter_AddRefs(listener));
if (NS_FAILED(rv)) return rv;
if (!listener) return NS_ERROR_FAILURE;
nsCOMPtr<nsIInputStream> stream;
rv = NS_NewCStringInputStream(getter_AddRefs(stream), mBody);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIChannel> channel;
rv = NS_NewInputStreamChannel(getter_AddRefs(channel), mLivemark->feedURI,
stream, NS_LITERAL_CSTRING("text/xml"));
if (NS_FAILED(rv)) return rv;
listener->OnStartRequest(channel, nsnull);
listener->OnDataAvailable(channel, nsnull, stream, 0, mBody.Length());
listener->OnStopRequest(channel, nsnull, NS_OK);
// Grab the (only) thing that's a channel
// We try RSS 1.0 first, then RSS 0.9, and set up the remaining
// resources accordingly
nsIRDFResource *RSS_items = nsnull;
nsIRDFResource *RSS_title = nsnull;
nsIRDFResource *RSS_link = nsnull;
nsCOMPtr<nsIRDFResource> channelResource = nsnull;
rv = ds->GetSource(mLivemarkService->mLMRDF_type, mLivemarkService->mLMRSS10_channel, PR_TRUE, getter_AddRefs(channelResource));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
if (rv == NS_OK) {
RSS_items = mLivemarkService->mLMRSS10_items;
RSS_title = mLivemarkService->mLMRSS10_title;
RSS_link = mLivemarkService->mLMRSS10_link;
} else {
// try RSS 0.9
rv = ds->GetSource(mLivemarkService->mLMRDF_type, mLivemarkService->mLMRSS09_channel, PR_TRUE, getter_AddRefs(channelResource));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
if (rv == NS_OK) {
RSS_items = nsnull;
RSS_title = mLivemarkService->mLMRSS09_title;
RSS_link = mLivemarkService->mLMRSS09_link;
}
}
if (!channelResource) {
// no channel, either 1.0 or 0.9
return NS_ERROR_FAILURE;
}
// this will get filled in differently.
nsCOMPtr<nsISimpleEnumerator> itemsEnumerator;
if (RSS_items) {
// if there is something that should be rss:items, then it's RSS 1.0
nsCOMPtr<nsIRDFNode> itemsNode;
rv = ds->GetTarget(channelResource, RSS_items, PR_TRUE, getter_AddRefs(itemsNode));
if (NS_FAILED(rv) || rv == NS_RDF_NO_VALUE) return NS_ERROR_FAILURE;
// items is a seq
nsCOMPtr<nsIRDFContainer> itemsContainer = do_CreateInstance (kRDFContainerCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = itemsContainer->Init(ds, (nsIRDFResource *) itemsNode.get());
if (NS_FAILED(rv)) return rv;
rv = itemsContainer->GetElements (getter_AddRefs(itemsEnumerator));
if (NS_FAILED(rv) || rv == NS_RDF_NO_VALUE) return NS_ERROR_FAILURE;
} else {
//
// if there is no rss:items, but we still were able to parse it as RDF
// and found a channel, then it's possibly RSS 0.9. For RSS 0.9,
// we know that each item will be an <item ...>, so we get everything
// that has a type of item.
rv = ds->GetSources(mLivemarkService->mLMRDF_type, mLivemarkService->mLMRSS09_item, PR_TRUE, getter_AddRefs(itemsEnumerator));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
// Go through each resource and pull out its link/title, if present.
PRBool more;
while (NS_SUCCEEDED(rv = itemsEnumerator->HasMoreElements(&more)) && more) {
nsCOMPtr<nsISupports> iSupports;
rv = itemsEnumerator->GetNext(getter_AddRefs(iSupports));
if (NS_FAILED(rv)) break;
nsCOMPtr<nsIRDFResource> item(do_QueryInterface(iSupports));
if (!item) {
rv = NS_ERROR_UNEXPECTED;
break;
}
rv = HandleRDFItem (ds, item, RSS_link, RSS_title);
// ignore rv
}
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
nsresult
nsLivemarkLoadListener::ParseHTMLFragment(nsAString &aFragString,
nsIDocument* aTargetDocument,
nsIDOMNode **outNode)
{
NS_ENSURE_ARG(aTargetDocument);
nsresult rv;
nsCOMPtr<nsIParser> parser;
parser = do_CreateInstance(kCParserCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// create the html fragment sink
nsCOMPtr<nsIContentSink> sink;
sink = do_CreateInstance(NS_HTMLFRAGMENTSINK2_CONTRACTID);
NS_ENSURE_TRUE(sink, NS_ERROR_FAILURE);
nsCOMPtr<nsIFragmentContentSink> fragSink(do_QueryInterface(sink));
NS_ENSURE_TRUE(fragSink, NS_ERROR_FAILURE);
fragSink->SetTargetDocument(aTargetDocument);
// parse the fragment
parser->SetContentSink(sink);
#ifdef MOZILLA_1_8_BRANCH
parser->Parse(aFragString, (void*)0, NS_LITERAL_CSTRING("text/html"), PR_FALSE, PR_TRUE, eDTDMode_fragment);
#else
parser->Parse(aFragString, (void*)0, NS_LITERAL_CSTRING("text/html"), PR_TRUE, eDTDMode_fragment);
#endif
// get the fragment node
nsCOMPtr<nsIDOMDocumentFragment> contextfrag;
rv = fragSink->GetFragment(getter_AddRefs(contextfrag));
NS_ENSURE_SUCCESS(rv, rv);
rv = CallQueryInterface (contextfrag, outNode);
return rv;
}
// find all of the text and CDATA nodes below aNode and return them as a string
nsresult
nsLivemarkLoadListener::FindTextInChildNodes (nsIDOMNode *aNode, nsAString &aString)
{
NS_ENSURE_ARG(aNode);
nsresult rv;
nsCOMPtr<nsIDOMDocument> aDoc;
aNode->GetOwnerDocument(getter_AddRefs(aDoc));
nsCOMPtr<nsIDOMDocumentTraversal> trav = do_QueryInterface(aDoc, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMTreeWalker> walker;
rv = trav->CreateTreeWalker(aNode,
nsIDOMNodeFilter::SHOW_TEXT | nsIDOMNodeFilter::SHOW_CDATA_SECTION,
nsnull, PR_TRUE, getter_AddRefs(walker));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMNode> currentNode;
walker->GetCurrentNode(getter_AddRefs(currentNode));
nsCOMPtr<nsIDOMCharacterData> charTextNode;
nsAutoString tempString;
while (currentNode) {
charTextNode = do_QueryInterface(currentNode);
if (charTextNode) {
charTextNode->GetData(tempString);
aString.Append(tempString);
}
walker->NextNode(getter_AddRefs(currentNode));
}
if (aString.IsEmpty()) {
return NS_ERROR_FAILURE;
} else {
return NS_OK;
}
}
nsresult
nsLivemarkLoadListener::HandleRDFItem (nsIRDFDataSource *aDS, nsIRDFResource *aItem,
nsIRDFResource *aLinkResource,
nsIRDFResource *aTitleResource)
{
nsresult rv;
// We care about this item's link and title
nsCOMPtr<nsIRDFNode> linkNode;
rv = aDS->GetTarget (aItem, aLinkResource, PR_TRUE, getter_AddRefs(linkNode));
if (NS_FAILED(rv) || rv == NS_RDF_NO_VALUE) return NS_ERROR_FAILURE;
nsCOMPtr<nsIRDFNode> titleNode;
rv = aDS->GetTarget (aItem, aTitleResource, PR_TRUE, getter_AddRefs(titleNode));
if (rv == NS_RDF_NO_VALUE) {
rv = aDS->GetTarget (aItem, mLivemarkService->mLMDC_date, PR_TRUE, getter_AddRefs(titleNode));
}
if (NS_FAILED(rv) || rv == NS_RDF_NO_VALUE) return NS_ERROR_FAILURE;
nsCOMPtr<nsIRDFLiteral> linkLiteral(do_QueryInterface(linkNode));
nsCOMPtr<nsIRDFLiteral> titleLiteral(do_QueryInterface(titleNode));
// if the link/title points to something other than a literal skip it.
if (!linkLiteral || !titleLiteral)
return NS_ERROR_FAILURE;
const PRUnichar *linkStr, *titleStr;
rv = linkLiteral->GetValueConst(&linkStr);
rv |= titleLiteral->GetValueConst(&titleStr);
if (NS_FAILED(rv)) return rv;
if (!IsLinkValid(linkStr))
return NS_OK;
// Add new bookmark with the link and title.
nsCOMPtr<nsIURI> linkURI;
rv = NS_NewURI(getter_AddRefs(linkURI), NS_ConvertUTF16toUTF8(linkStr));
rv = mLivemarkService->InsertLivemarkChild(mLivemark->folderId,
linkURI,
nsDependentString(titleStr),
nsDependentString(linkStr));
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
/**
* TryParseAsSimpleRSS
*
* Tries to parse the content as RSS (Userland) 0.91/0.92/2.0, or Atom
* These are not RDF formats.
*/
nsresult
nsLivemarkLoadListener::TryParseAsSimpleRSS ()
{
nsresult rv;
nsCOMPtr<nsIDOMParser> parser(do_CreateInstance("@mozilla.org/xmlextras/domparser;1", &rv));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMDocument> xmldoc;
parser->SetBaseURI(mLivemark->feedURI);
rv = parser->ParseFromBuffer ((const PRUint8*) mBody.get(), mBody.Length(), "text/xml", getter_AddRefs(xmldoc));
if (NS_FAILED(rv)) return rv;
// becomes true if we figure out that this is an atom stream.
PRBool isAtom = PR_FALSE;
nsCOMPtr<nsIDOMElement> docElement;
rv = xmldoc->GetDocumentElement(getter_AddRefs(docElement));
if (!docElement) return NS_ERROR_UNEXPECTED;
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMNode> node;
rv = xmldoc->GetFirstChild(getter_AddRefs(node));
if (!node) return NS_ERROR_UNEXPECTED;
if (NS_FAILED(rv)) return rv;
PRBool lookingForChannel = PR_FALSE;
while (node) {
PRUint16 ntype;
rv = node->GetNodeType(&ntype);
if (NS_FAILED(rv)) return rv;
if (ntype == nsIDOMNode::ELEMENT_NODE) {
nsAutoString nname;
rv = node->GetNodeName (nname);
// slight hack to get node pointing to the thing that
// has items/entries as its children. We need to descend
// into <channel> for RSS, but not for Atom.
if (!lookingForChannel) {
if (nname.Equals(NS_LITERAL_STRING("rss"))) {
lookingForChannel = PR_TRUE;
nsCOMPtr<nsIDOMNode> temp;
rv = node->GetFirstChild(getter_AddRefs(temp));
if (!temp) return NS_ERROR_UNEXPECTED;
if (NS_FAILED(rv)) return rv;
node = temp;
continue;
}
if (nname.Equals(NS_LITERAL_STRING("feed"))) {
// Atom has no <channel>; instead, <item>s are
// children of <feed>
isAtom = PR_TRUE;
break;
}
} else {
if (nname.Equals(NS_LITERAL_STRING("channel"))) {
break;
}
}
}
nsCOMPtr<nsIDOMNode> temp;
rv = node->GetNextSibling(getter_AddRefs(temp));
if (!temp) return NS_ERROR_UNEXPECTED;
if (NS_FAILED(rv)) return rv;
node = temp;
}
// we didn't find a rss/feed/channel or whatever
if (!node)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> chElement = do_QueryInterface(node);
if (!chElement) return NS_ERROR_UNEXPECTED;
// Go through the <channel>/<feed> and do what we need
// with <item> or <entry> nodes
rv = chElement->GetFirstChild(getter_AddRefs(node));
if (!node) return NS_ERROR_UNEXPECTED;
if (NS_FAILED(rv)) return rv;
while (node) {
PRUint16 ntype;
rv = node->GetNodeType(&ntype);
if (NS_FAILED(rv)) return rv;
if (ntype == nsIDOMNode::ELEMENT_NODE) {
nsAutoString nname;
rv = node->GetNodeName (nname);
if ((!isAtom && nname.Equals(NS_LITERAL_STRING("item"))) ||
( isAtom && nname.Equals(NS_LITERAL_STRING("entry"))))
{
// We need to pull out the <title> and <link> children
nsAutoString titleStr;
nsAutoString linkStr;
nsAutoString dateStr;
nsCOMPtr<nsIDOMNode> childNode;
rv = node->GetFirstChild(getter_AddRefs(childNode));
if (NS_FAILED(rv)) return rv;
while (childNode) {
PRUint16 childNtype;
rv = childNode->GetNodeType(&childNtype);
if (NS_FAILED(rv)) return rv;
if (childNtype == nsIDOMNode::ELEMENT_NODE) {
nsAutoString childNname;
rv = childNode->GetNodeName (childNname);
if (childNname.Equals(NS_LITERAL_STRING("title"))) {
if (isAtom) {
/* Atom titles can contain HTML, so we need to find and remove it */
nsCOMPtr<nsIDOMElement> titleElem = do_QueryInterface(childNode);
if (!titleElem) break; // out of while(childNode) loop
nsAutoString titleMode; // Atom 0.3 only
nsAutoString titleType;
titleElem->GetAttribute(NS_LITERAL_STRING("type"), titleType);
titleElem->GetAttribute(NS_LITERAL_STRING("mode"), titleMode);
/* No one does this in <title> except standards pedants making test feeds,
* Atom 0.3 is deprecated, and RFC 4287 doesn't allow it
*/
if (titleMode.EqualsLiteral("base64")) {
break; // out of while(childNode) loop
}
/* Cover Atom 0.3 and RFC 4287 together */
if (titleType.EqualsLiteral("text") ||
titleType.EqualsLiteral("text/plain") ||
titleType.IsEmpty())
{
rv = FindTextInChildNodes(childNode, titleStr);
} else if (titleType.EqualsLiteral("html") || // RFC 4287
(titleType.EqualsLiteral("text/html") && // Atom 0.3
!titleMode.EqualsLiteral("xml")) ||
titleMode.EqualsLiteral("escaped")) // Atom 0.3
{
nsAutoString escapedHTMLStr;
rv = FindTextInChildNodes(childNode, escapedHTMLStr);
if (NS_FAILED(rv)) break; // out of while(childNode) loop
nsCOMPtr<nsIDOMNode> newNode;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(xmldoc);
ParseHTMLFragment(escapedHTMLStr, doc, getter_AddRefs(newNode));
rv = FindTextInChildNodes(newNode, titleStr);
}else if (titleType.EqualsLiteral("xhtml") || // RFC 4287
titleType.EqualsLiteral("application/xhtml") || // Atom 0.3
titleMode.EqualsLiteral("xml")) // Atom 0.3
{
rv = FindTextInChildNodes(childNode, titleStr);
} else {
break; // out of while(childNode) loop
}
} else {
rv = FindTextInChildNodes(childNode, titleStr);
}
if (NS_FAILED(rv)) break;
} else if (childNname.Equals(NS_LITERAL_STRING("pubDate")) ||
childNname.Equals(NS_LITERAL_STRING("updated")))
{
rv = FindTextInChildNodes (childNode, dateStr);
if (NS_FAILED(rv)) break;
} else if (!isAtom && childNname.Equals(NS_LITERAL_STRING("guid"))) {
nsCOMPtr<nsIDOMElement> linkElem = do_QueryInterface(childNode);
if (!linkElem) break; // out of while(childNode) loop
nsAutoString isPermaLink;
linkElem->GetAttribute(NS_LITERAL_STRING("isPermaLink"), isPermaLink);
// Ignore failures. isPermaLink defaults to true.
if (!isPermaLink.Equals(NS_LITERAL_STRING("false"))) {
// in node's TEXT
rv = FindTextInChildNodes (childNode, linkStr);
if (NS_FAILED(rv)) break;
}
} else if (childNname.Equals(NS_LITERAL_STRING("link"))) {
if (isAtom) {
// in HREF attribute
nsCOMPtr<nsIDOMElement> linkElem = do_QueryInterface(childNode);
if (!linkElem) break; // out of while(childNode) loop
nsAutoString rel;
linkElem->GetAttribute(NS_LITERAL_STRING("rel"), rel);
if (rel.Equals(NS_LITERAL_STRING("alternate")) ||
rel.IsEmpty())
{
rv = linkElem->GetAttribute(NS_LITERAL_STRING("href"), linkStr);
if (NS_FAILED(rv)) break; // out of while(childNode) loop
nsCOMPtr<nsIDOM3Node> linkElem3 = do_QueryInterface(childNode);
if (linkElem3) {
// get the BaseURI (as string)
nsAutoString base;
rv = linkElem3->GetBaseURI(base);
if (NS_SUCCEEDED(rv) && !base.IsEmpty()) {
// convert a baseURI (string) to a nsIURI
nsCOMPtr<nsIURI> baseURI;
rv = NS_NewURI(getter_AddRefs(baseURI), base);
if (baseURI) {
nsString absLinkStr;
if (NS_SUCCEEDED(NS_MakeAbsoluteURI(absLinkStr, linkStr, baseURI)))
linkStr = absLinkStr;
}
}
}
}
} else if (linkStr.IsEmpty()) {
// in node's TEXT
rv = FindTextInChildNodes (childNode, linkStr);
if (NS_FAILED(rv)) break;
}
}
}
if (!titleStr.IsEmpty() && !linkStr.IsEmpty())
break;
nsCOMPtr<nsIDOMNode> temp;
rv = childNode->GetNextSibling(getter_AddRefs(temp));
childNode = temp;
if (!childNode || NS_FAILED(rv)) break;
}
// Clean up whitespace
titleStr.CompressWhitespace();
linkStr.Trim("\b\t\r\n ");
dateStr.CompressWhitespace();
if (titleStr.IsEmpty() && !dateStr.IsEmpty())
titleStr.Assign(dateStr);
if (!titleStr.IsEmpty() && !linkStr.IsEmpty() && IsLinkValid(linkStr.get())) {
nsCOMPtr<nsIURI> linkURI;
rv = NS_NewURI(getter_AddRefs(linkURI),
NS_ConvertUTF16toUTF8(linkStr));
if (NS_FAILED(rv)) return rv;
rv = mLivemarkService->InsertLivemarkChild(mLivemark->folderId,
linkURI,
nsDependentString(titleStr),
nsDependentString(linkStr));
if (NS_FAILED(rv)) return rv;
}
}
}
nsCOMPtr<nsIDOMNode> temp;
rv = node->GetNextSibling(getter_AddRefs(temp));
if (NS_FAILED(rv)) return rv;
node = temp;
}
return NS_OK;
}
// return true if this link is valid and a livemark should be created;
// otherwise, false.
PRBool
nsLivemarkLoadListener::IsLinkValid(const PRUnichar *aURI)
{
nsCOMPtr<nsIURI> linkuri;
nsresult rv = NS_NewURI(getter_AddRefs(linkuri), nsDependentString(aURI));
if (NS_FAILED(rv))
return PR_FALSE;
// Er, where'd our security manager go?
if (!mSecMan)
return PR_FALSE;
rv = mSecMan->CheckLoadURI(mLivemark->feedURI, linkuri,
nsIScriptSecurityManager::DISALLOW_FROM_MAIL |
nsIScriptSecurityManager::DISALLOW_SCRIPT_OR_DATA);
if (NS_FAILED(rv))
return PR_FALSE;
return PR_TRUE;
}
///////////////////////////////////////////////////////////////////////////
//// Main entry point for nsLivemarkService to deal with Livemark
//// load listener
////
/*
* Update the child elements of a livemark; take care of cache checking,
* channel setup and firing off the async load and parse. If aForceUpdate
* is true, the livemark will be updated whether or not it has expired; this
* is intended for user "Update Livemark" commands.
*/
nsresult
nsLivemarkService::UpdateLivemarkChildren(PRInt32 aLivemarkIndex, PRBool aForceUpdate)
{
nsresult rv;
if (mLivemarks[aLivemarkIndex]->locked)
{
// We're already loading the livemark
return NS_OK;
}
// Lock the livemark
mLivemarks[aLivemarkIndex]->locked = PR_TRUE;
// Check the TTL/expiration on this. If there isn't one,
// then we assume it's never been loaded. We perform this
// check even when the update is being forced, in case the
// livemark has somehow never been loaded.
PRTime exprTime;
rv = mAnnotationService->GetAnnotationInt64(mLivemarks[aLivemarkIndex]->feedURI,
NS_LITERAL_CSTRING(LMANNO_EXPIRATION),
&exprTime);
if (rv == NS_OK) {
if (! aForceUpdate) {
PRTime nowTime = PR_Now();
if (LL_CMP(exprTime, >, nowTime)) {
// No need to refresh yet.
mLivemarks[aLivemarkIndex]->locked = PR_FALSE;
return rv;
}
}
} else {
// This livemark has never been loaded, since it has no expire time.
rv = InsertLivemarkLoadingItem(mLivemarks[aLivemarkIndex]->folderId);
}
// Create a load group for the request. This will allow us to automatically
// keep track of redirects, so we can always cancel the channel.
nsCOMPtr<nsILoadGroup> loadGroup;
rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), nsnull);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannel> uriChannel;
rv = NS_NewChannel(getter_AddRefs(uriChannel),
mLivemarks[aLivemarkIndex]->feedURI,
nsnull, loadGroup, nsnull,
nsIRequest::LOAD_BACKGROUND);
if (NS_FAILED(rv)) {
mLivemarks[aLivemarkIndex]->locked = PR_FALSE;
return rv;
}
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(uriChannel);
if (httpChannel) {
// XXXvladimir - handle POST livemarks
rv = httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("GET"));
}
nsCOMPtr<nsLivemarkLoadListener> listener = new nsLivemarkLoadListener(this,
mAnnotationService,
mLivemarks[aLivemarkIndex]);
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
mLivemarks[aLivemarkIndex]->feedURI, nsnull, nsnull, nsnull,
nsIRequest::LOAD_BACKGROUND | nsIRequest::VALIDATE_ALWAYS);
if (NS_FAILED(rv)) {
mLivemarks[aLivemarkIndex]->locked = PR_FALSE;
return rv;
}
rv = channel->AsyncOpen(listener, nsnull);
if (NS_FAILED(rv)) {
mLivemarks[aLivemarkIndex]->locked = PR_FALSE;
return rv;
}
mLivemarks[aLivemarkIndex]->loadGroup = loadGroup;
return NS_OK;
}

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

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

@ -1,951 +0,0 @@
/* -*- 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 Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
/**
* This is the favicon service, which stores favicons for web pages with your
* history as you browse. It is also used to save the favicons for bookmarks.
*
* DANGER: The history query system makes assumptions about the favicon storage
* so that icons can be quickly generated for history/bookmark result sets. If
* you change the database layout at all, you will have to update both services.
*/
#include "nsFaviconService.h"
#include "nsICacheVisitor.h"
#include "nsICachingChannel.h"
#include "nsICategoryManager.h"
#include "nsIChannelEventSink.h"
#include "nsIContentSniffer.h"
#include "nsIInterfaceRequestor.h"
#include "nsIStreamListener.h"
#include "nsISupportsPrimitives.h"
#include "nsNavBookmarks.h"
#include "nsNavHistory.h"
#include "nsNetUtil.h"
#include "nsReadableUtils.h"
#include "nsStreamUtils.h"
#include "mozStorageHelper.h"
// This is the maximum favicon size that we will bother storing. Most icons
// are about 4K. Some people add 32x32 versions at different bit depths,
// making them much bigger. It would be nice if could extract just the 16x16
// version that we need. Instead, we'll just store everything below this
// sanity threshold.
#define MAX_FAVICON_SIZE 32768
#define FAVICON_BUFFER_INCREMENT 8192
#define MAX_FAVICON_CACHE_SIZE 512
#define FAVICON_CACHE_REDUCE_COUNT 64
#define CONTENT_SNIFFING_SERVICES "content-sniffing-services"
class FaviconLoadListener : public nsIStreamListener,
public nsIInterfaceRequestor,
public nsIChannelEventSink
{
public:
FaviconLoadListener(nsFaviconService* aFaviconService,
nsIURI* aPageURI, nsIURI* aFaviconURI,
nsIChannel* aChannel);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
private:
~FaviconLoadListener();
nsCOMPtr<nsFaviconService> mFaviconService;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIURI> mPageURI;
nsCOMPtr<nsIURI> mFaviconURI;
nsCString mData;
};
nsFaviconService* nsFaviconService::gFaviconService;
NS_IMPL_ISUPPORTS1(nsFaviconService, nsIFaviconService)
// nsFaviconService::nsFaviconService
nsFaviconService::nsFaviconService() : mFailedFaviconSerial(0)
{
NS_ASSERTION(! gFaviconService, "ATTEMPTING TO CREATE TWO FAVICON SERVICES!");
gFaviconService = this;
}
// nsFaviconService::~nsFaviconService
nsFaviconService::~nsFaviconService()
{
NS_ASSERTION(gFaviconService == this, "Deleting a non-singleton favicon service");
if (gFaviconService == this)
gFaviconService = nsnull;
}
// nsFaviconService::Init
//
// Called when the service is created.
nsresult
nsFaviconService::Init()
{
nsresult rv;
nsNavHistory* historyService = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(historyService, NS_ERROR_OUT_OF_MEMORY);
mDBConn = historyService->GetStorageConnection();
NS_ENSURE_TRUE(mDBConn, NS_ERROR_FAILURE);
// creation of history service will have called InitTables before now
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT id, length(data), expiration FROM moz_favicon WHERE url = ?1"),
getter_AddRefs(mDBGetIconInfo));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT f.id, f.url, length(f.data), f.expiration FROM moz_history h JOIN moz_favicon f ON h.favicon = f.id WHERE h.url = ?1"),
getter_AddRefs(mDBGetURL));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT f.data, f.mime_type FROM moz_favicon f WHERE url = ?1"),
getter_AddRefs(mDBGetData));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_favicon (url, data, mime_type, expiration) VALUES (?1, ?2, ?3, ?4)"),
getter_AddRefs(mDBInsertIcon));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("UPDATE moz_favicon SET data = ?2, mime_type = ?3, expiration = ?4 where id = ?1"),
getter_AddRefs(mDBUpdateIcon));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("UPDATE moz_history SET favicon = ?2 WHERE id = ?1"),
getter_AddRefs(mDBSetPageFavicon));
NS_ENSURE_SUCCESS(rv, rv);
// failed favicon cache
if (! mFailedFavicons.Init(256))
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
// nsFaviconService::InitTables
//
// Called by the history service to create the favicon table. The history
// service uses this table in its queries, so it must exist even if
// nobody has called the favicon service.
nsresult // static
nsFaviconService::InitTables(mozIStorageConnection* aDBConn)
{
nsresult rv;
PRBool exists = PR_FALSE;
aDBConn->TableExists(NS_LITERAL_CSTRING("moz_favicon"), &exists);
if (! exists) {
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_favicon (id INTEGER PRIMARY KEY, url LONGVARCHAR UNIQUE, data BLOB, mime_type VARCHAR(32), expiration LONG)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE INDEX moz_favicon_url ON moz_favicon (url)"));
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
// nsFaviconService::SetFaviconUrlForPage
NS_IMETHODIMP
nsFaviconService::SetFaviconUrlForPage(nsIURI* aPage, nsIURI* aFavicon)
{
// we don't care whether there was data or what the expiration was
PRBool hasData;
PRTime expiration;
nsresult rv = SetFaviconUrlForPageInternal(aPage, aFavicon,
&hasData, &expiration);
NS_ENSURE_SUCCESS(rv, rv);
// send favicon change notifications if the URL has any data
if (hasData)
SendFaviconNotifications(aPage, aFavicon);
return NS_OK;
}
// nsFaviconService::SetFaviconUrlForPageInternal
//
// This creates a new entry in the favicon table if necessary and tells the
// history service to associate the given favicon ID with the given URL. We
// don't want to update the history table directly since that may involve
// creating a new row in the history table, which should only be done by
// history.
//
// This sets aHasData if there was already icon data for this favicon. Used
// to know if we should try reloading.
//
// Expiration will be 0 if the icon has not been set yet.
//
// Does NOT send out notifications. Caller should send out notifications
// if the favicon has data.
nsresult
nsFaviconService::SetFaviconUrlForPageInternal(nsIURI* aPage, nsIURI* aFavicon,
PRBool* aHasData,
PRTime* aExpiration)
{
mozStorageStatementScoper scoper(mDBGetIconInfo);
mozStorageTransaction transaction(mDBConn, PR_FALSE);
nsresult rv = BindStatementURI(mDBGetIconInfo, 0, aFavicon);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult;
rv = mDBGetIconInfo->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
PRInt64 iconId;
if (hasResult) {
// have an entry for this icon already, just get the stats
rv = mDBGetIconInfo->GetInt64(0, &iconId);
NS_ENSURE_SUCCESS(rv, rv);
// see if there's data already
PRInt32 dataSize;
rv = mDBGetIconInfo->GetInt32(1, &dataSize);
NS_ENSURE_SUCCESS(rv, rv);
if (dataSize > 0)
*aHasData = PR_TRUE;
// expiration
rv = mDBGetIconInfo->GetInt64(2, aExpiration);
NS_ENSURE_SUCCESS(rv, rv);
mDBGetIconInfo->Reset();
scoper.Abandon();
} else {
// create a new icon entry
mDBGetIconInfo->Reset();
scoper.Abandon();
*aHasData = PR_FALSE;
*aExpiration = 0;
// no entry for this icon yet, create it
mozStorageStatementScoper scoper2(mDBInsertIcon);
rv = BindStatementURI(mDBInsertIcon, 0, aFavicon);
NS_ENSURE_SUCCESS(rv, rv);
mDBInsertIcon->BindNullParameter(1);
mDBInsertIcon->BindNullParameter(2);
mDBInsertIcon->BindNullParameter(3);
rv = mDBInsertIcon->Execute();
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->GetLastInsertRowID(&iconId);
NS_ENSURE_SUCCESS(rv, rv);
}
// now link our entry with the history service
nsNavHistory* historyService = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(historyService, NS_ERROR_NO_INTERFACE);
PRInt64 pageId;
rv = historyService->GetUrlIdFor(aPage, &pageId, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
mozStorageStatementScoper scoper2(mDBSetPageFavicon);
rv = mDBSetPageFavicon->BindInt64Parameter(0, pageId);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBSetPageFavicon->BindInt64Parameter(1, iconId);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBSetPageFavicon->Execute();
NS_ENSURE_SUCCESS(rv, rv);
transaction.Commit();
return NS_OK;
}
// nsFaviconService::UpdateBookmarkRedirectFavicon
//
// It is not uncommon to have a bookmark (usually manually entered or
// modified) that redirects to some other page. For example, "mozilla.org"
// redirects to "www.mozilla.org". We want that bookmark's favicon to get
// updated. So, we see if this URI has a bookmark redirect and set the
// favicon there as well.
//
// This should be called only when we know there is data for the favicon
// already loaded. We will always send out notifications for the bookmarked
// page.
nsresult
nsFaviconService::UpdateBookmarkRedirectFavicon(nsIURI* aPage, nsIURI* aFavicon)
{
NS_ENSURE_TRUE(aPage, NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(aFavicon, NS_ERROR_INVALID_ARG);
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIURI> bookmarkURI;
nsresult rv = bookmarks->GetBookmarkedURIFor(aPage, getter_AddRefs(bookmarkURI));
NS_ENSURE_SUCCESS(rv, rv);
if (! bookmarkURI)
return NS_OK; // no bookmark redirect
PRBool sameAsBookmark;
if (NS_SUCCEEDED(bookmarkURI->Equals(aPage, &sameAsBookmark)) && sameAsBookmark)
return NS_OK; // bookmarked directly, not through a redirect
PRBool hasData = PR_FALSE;
PRTime expiration = 0;
rv = SetFaviconUrlForPageInternal(bookmarkURI, aFavicon, &hasData, &expiration);
NS_ENSURE_SUCCESS(rv, rv);
if (hasData) {
// send notifications
SendFaviconNotifications(bookmarkURI, aFavicon);
} else {
NS_WARNING("Calling UpdateBookmarkRedirectFavicon when you don't have data for the favicon yet.");
}
return NS_OK;
}
// nsFaviconService::SendFaviconNotifications
//
// Call to send out favicon changed notifications. Shuold only be called
// when you know there is data loaded for the favicon.
void
nsFaviconService::SendFaviconNotifications(nsIURI* aPage, nsIURI* aFaviconURI)
{
nsCAutoString faviconSpec;
nsNavHistory* historyService = nsNavHistory::GetHistoryService();
if (historyService && NS_SUCCEEDED(aFaviconURI->GetSpec(faviconSpec))) {
historyService->SendPageChangedNotification(aPage,
nsINavHistoryObserver::ATTRIBUTE_FAVICON,
NS_ConvertUTF8toUTF16(faviconSpec));
}
}
// nsFaviconService::SetAndLoadFaviconForPage
NS_IMETHODIMP
nsFaviconService::SetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon,
PRBool aForceReload)
{
#ifdef LAZY_ADD
nsNavHistory* historyService = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(historyService, NS_ERROR_OUT_OF_MEMORY);
return historyService->AddLazyLoadFaviconMessage(aPage, aFavicon,
aForceReload);
#else
return DoSetAndLoadFaviconForPage(aPage, aFavicon, aForceReload);
#endif
}
// nsFaviconService::DoSetAndLoadFaviconForPage
nsresult
nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon,
PRBool aForceReload)
{
nsCOMPtr<nsIURI> page(aPage);
// don't load favicons when history is disabled
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, NS_ERROR_FAILURE);
if (history->IsHistoryDisabled()) {
// history is disabled - check to see if this favicon could be for a
// bookmark
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIURI> bookmarkURI;
nsresult rv = bookmarks->GetBookmarkedURIFor(aPage,
getter_AddRefs(bookmarkURI));
NS_ENSURE_SUCCESS(rv, rv);
if (! bookmarkURI) {
// page is not bookmarked, don't save favicon
return NS_OK;
}
// page is bookmarked, set the URI to be the bookmark, the bookmark URI
// might be different than our input URI if there was a redirect, so
// always use the bookmark URI here to avoid setting the favicon for
// non-bookmarked pages.
page = bookmarkURI;
}
// check the failed favicon cache
PRBool previouslyFailed;
nsresult rv = IsFailedFavicon(aFavicon, &previouslyFailed);
NS_ENSURE_SUCCESS(rv, rv);
if (previouslyFailed) {
if (aForceReload)
RemoveFailedFavicon(aFavicon); // force reload clears from failed cache
else
return NS_OK; // ignore previously failed favicons
}
// filter out bad URLs
PRBool canAdd;
rv = history->CanAddURI(page, &canAdd);
NS_ENSURE_SUCCESS(rv, rv);
if (! canAdd)
return NS_OK; // ignore favicons for this url
// If have an image loaded in the main frame, that image will get set as its
// own favicon. It would be nice to store a resampled version of the image,
// but that's prohibitive for now. This workaround just refuses to save the
// favicon in this case.
PRBool pageEqualsFavicon;
rv = page->Equals(aFavicon, &pageEqualsFavicon);
NS_ENSURE_SUCCESS(rv, rv);
if (pageEqualsFavicon)
return NS_OK;
// ignore data URL favicons. The main case here is the error page, which uses
// a data URL as the favicon. The result is that we get the data URL in the
// favicon table associated with the decoded version of the data URL.
PRBool isDataURL;
rv = aFavicon->SchemeIs("data", &isDataURL);
NS_ENSURE_SUCCESS(rv, rv);
if (isDataURL)
return NS_OK;
// See if we have data and get the expiration time for this favicon. It might
// be nice to say SetFaviconUrlForPageInternal here but we DON'T want to set
// the favicon for the page unless we know we have it. For example, if I go
// to random site x.com, the browser will still tell us that the favicon is
// x.com/favicon.ico even if there is no such file. We don't want to pollute
// our tables with this useless data.
PRBool hasData = PR_FALSE;
PRTime expiration = 0;
{ // scope for statement
mozStorageStatementScoper scoper(mDBGetIconInfo);
rv = BindStatementURI(mDBGetIconInfo, 0, aFavicon);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasMatch;
rv = mDBGetIconInfo->ExecuteStep(&hasMatch);
NS_ENSURE_SUCCESS(rv, rv);
if (hasMatch) {
PRInt32 dataSize;
mDBGetIconInfo->GetInt32(1, &dataSize);
hasData = dataSize > 0;
mDBGetIconInfo->GetInt64(2, &expiration);
}
}
// See if this favicon has expired yet. We don't want to waste time reloading
// from the web or cache if we have a recent version.
PRTime now = PR_Now();
if (hasData && now < expiration && ! aForceReload) {
// data still valid, no need to reload
// For page revisits (pretty common) we DON'T want to send out any
// notifications if we've already set the favicon. These notifications will
// cause parts of the UI to update and will be slow. This also saves us a
// database write in these cases.
nsCOMPtr<nsIURI> oldFavicon;
PRBool faviconsEqual;
if (NS_SUCCEEDED(GetFaviconForPage(page, getter_AddRefs(oldFavicon))) &&
NS_SUCCEEDED(aFavicon->Equals(oldFavicon, &faviconsEqual)) &&
faviconsEqual)
return NS_OK; // already set
// This will associate the favicon URL with the page.
rv = SetFaviconUrlForPageInternal(page, aFavicon, &hasData, &expiration);
NS_ENSURE_SUCCESS(rv, rv);
SendFaviconNotifications(page, aFavicon);
UpdateBookmarkRedirectFavicon(page, aFavicon);
return NS_OK;
}
nsCOMPtr<nsIIOService> ioservice = do_GetIOService(&rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannel> channel;
rv = ioservice->NewChannelFromURI(aFavicon, getter_AddRefs(channel));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> listener =
new FaviconLoadListener(this, page, aFavicon, channel);
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIInterfaceRequestor> listenerRequestor =
do_QueryInterface(listener, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = channel->SetNotificationCallbacks(listenerRequestor);
NS_ENSURE_SUCCESS(rv, rv);
rv = channel->AsyncOpen(listener, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
// DB will be update and observers will be notified when the data has
// finished loading
return NS_OK;
}
// nsFaviconService::SetFaviconData
//
// See the IDL for this function for lots of info. Note from there: we don't
// send out notifications.
NS_IMETHODIMP
nsFaviconService::SetFaviconData(nsIURI* aFavicon, const PRUint8* aData,
PRUint32 aDataLen, const nsACString& aMimeType,
PRTime aExpiration)
{
nsresult rv;
mozIStorageStatement* statement;
{
// this block forces the scoper to reset our statement: necessary for the
// next statement
mozStorageStatementScoper scoper(mDBGetIconInfo);
rv = BindStatementURI(mDBGetIconInfo, 0, aFavicon);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult;
rv = mDBGetIconInfo->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
if (hasResult) {
// update old one (statement parameter 0 = ID)
PRInt64 id;
rv = mDBGetIconInfo->GetInt64(0, &id);
NS_ENSURE_SUCCESS(rv, rv);
statement = mDBUpdateIcon;
rv = statement->BindInt64Parameter(0, id);
} else {
// insert new one (statement parameter 0 = favicon URL)
statement = mDBInsertIcon;
rv = BindStatementURI(statement, 0, aFavicon);
}
NS_ENSURE_SUCCESS(rv, rv);
}
mozStorageStatementScoper scoper(statement);
// the insert and update statements share all but the 0th parameter
rv = statement->BindBlobParameter(1, aData, aDataLen);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindUTF8StringParameter(2, aMimeType);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt64Parameter(3, aExpiration);
NS_ENSURE_SUCCESS(rv, rv);
return statement->Execute();
}
// nsFaviconService::GetFaviconData
NS_IMETHODIMP
nsFaviconService::GetFaviconData(nsIURI* aFavicon, nsACString& aMimeType,
PRUint32* aDataLen, PRUint8** aData)
{
mozStorageStatementScoper scoper(mDBGetData);
nsresult rv = BindStatementURI(mDBGetData, 0, aFavicon);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult;
rv = mDBGetData->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
if (! hasResult)
return NS_ERROR_NOT_AVAILABLE;
rv = mDBGetData->GetUTF8String(1, aMimeType);
NS_ENSURE_SUCCESS(rv, rv);
return mDBGetData->GetBlob(0, aDataLen, aData);
}
// nsFaviconService::GetFaviconForPage
NS_IMETHODIMP
nsFaviconService::GetFaviconForPage(nsIURI* aPage, nsIURI** _retval)
{
mozStorageStatementScoper scoper(mDBGetURL);
nsresult rv = BindStatementURI(mDBGetURL, 0, aPage);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult;
rv = mDBGetURL->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
if (! hasResult)
return NS_ERROR_NOT_AVAILABLE;
nsCAutoString url;
rv = mDBGetURL->GetUTF8String(1, url);
NS_ENSURE_SUCCESS(rv, rv);
return NS_NewURI(_retval, url);
}
// nsFaviconService::GetFaviconImageForPage
NS_IMETHODIMP
nsFaviconService::GetFaviconImageForPage(nsIURI* aPage, nsIURI** _retval)
{
mozStorageStatementScoper scoper(mDBGetURL);
nsresult rv = BindStatementURI(mDBGetURL, 0, aPage);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult;
rv = mDBGetURL->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> faviconURI;
if (hasResult)
{
PRInt32 dataLen;
rv = mDBGetURL->GetInt32(2, &dataLen);
NS_ENSURE_SUCCESS(rv, rv);
if (dataLen > 0) {
// this page has a favicon entry with data
nsCAutoString favIconUri;
rv = mDBGetURL->GetUTF8String(1, favIconUri);
NS_ENSURE_SUCCESS(rv, rv);
return GetFaviconLinkForIconString(favIconUri, _retval);
}
}
// not found, use default
if (! mDefaultIcon) {
nsresult rv = NS_NewURI(getter_AddRefs(mDefaultIcon),
NS_LITERAL_CSTRING(FAVICON_DEFAULT_URL));
NS_ENSURE_SUCCESS(rv, rv);
}
return mDefaultIcon->Clone(_retval);
}
// nsFaviconService::GetFaviconLinkForIcon
nsresult
nsFaviconService::GetFaviconLinkForIcon(nsIURI* aIcon, nsIURI** aOutput)
{
nsCAutoString spec;
if (aIcon) {
nsresult rv = aIcon->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
}
return GetFaviconLinkForIconString(spec, aOutput);
}
// nsFaviconService::AddFailedFavicon
PR_STATIC_CALLBACK(PLDHashOperator)
ExpireFailedFaviconsCallback(nsCStringHashKey::KeyType aKey,
PRUint32& aData,
void* userArg)
{
PRUint32* threshold = NS_REINTERPRET_CAST(PRUint32*, userArg);
if (aData < *threshold)
return PL_DHASH_REMOVE;
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
nsFaviconService::AddFailedFavicon(nsIURI* aIcon)
{
nsCAutoString spec;
nsresult rv = aIcon->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
if (! mFailedFavicons.Put(spec, mFailedFaviconSerial))
return NS_ERROR_OUT_OF_MEMORY;
mFailedFaviconSerial ++;
if (mFailedFavicons.Count() > MAX_FAVICON_CACHE_SIZE) {
// need to expire some entries, delete the FAVICON_CACHE_REDUCE_COUNT number
// of items that are the oldest
PRUint32 threshold = mFailedFaviconSerial -
MAX_FAVICON_CACHE_SIZE + FAVICON_CACHE_REDUCE_COUNT;
mFailedFavicons.Enumerate(ExpireFailedFaviconsCallback, &threshold);
}
return NS_OK;
}
// nsFaviconService::RemoveFailedFavicon
NS_IMETHODIMP
nsFaviconService::RemoveFailedFavicon(nsIURI* aIcon)
{
nsCAutoString spec;
nsresult rv = aIcon->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
// we silently do nothing and succeed if the icon is not in the cache
mFailedFavicons.Remove(spec);
return NS_OK;
}
// nsFaviconService::IsFailedFavicon
NS_IMETHODIMP
nsFaviconService::IsFailedFavicon(nsIURI* aIcon, PRBool* _retval)
{
nsCAutoString spec;
nsresult rv = aIcon->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 serial;
*_retval = mFailedFavicons.Get(spec, &serial);
return NS_OK;
}
// nsFaviconService::GetFaviconLinkForIconString
//
// This computes a favicon URL with string input and using the cached
// default one to minimize parsing.
nsresult
nsFaviconService::GetFaviconLinkForIconString(const nsCString& aSpec, nsIURI** aOutput)
{
if (aSpec.IsEmpty()) {
// default icon for empty strings
if (! mDefaultIcon) {
nsresult rv = NS_NewURI(getter_AddRefs(mDefaultIcon),
NS_LITERAL_CSTRING(FAVICON_DEFAULT_URL));
NS_ENSURE_SUCCESS(rv, rv);
}
return mDefaultIcon->Clone(aOutput);
}
if (StringBeginsWith(aSpec, NS_LITERAL_CSTRING("chrome:"))) {
// pass through for chrome URLs, since they can be referenced without
// this service
return NS_NewURI(aOutput, aSpec);
}
nsCAutoString annoUri;
annoUri.AssignLiteral("moz-anno:" FAVICON_ANNOTATION_NAME ":");
annoUri += aSpec;
return NS_NewURI(aOutput, annoUri);
}
// nsFaviconService::GetFaviconSpecForIconString
//
// This computes a favicon spec for when you don't want a URI object (as in
// the tree view implementation), sparing all parsing and normalization.
void
nsFaviconService::GetFaviconSpecForIconString(const nsCString& aSpec, nsACString& aOutput)
{
if (aSpec.IsEmpty()) {
aOutput.AssignLiteral(FAVICON_DEFAULT_URL);
} else if (StringBeginsWith(aSpec, NS_LITERAL_CSTRING("chrome:"))) {
aOutput = aSpec;
} else {
aOutput.AssignLiteral("moz-anno:" FAVICON_ANNOTATION_NAME ":");
aOutput += aSpec;
}
}
NS_IMPL_ISUPPORTS3(FaviconLoadListener,
nsIStreamListener, // is a nsIRequestObserver
nsIInterfaceRequestor,
nsIChannelEventSink)
// FaviconLoadListener::FaviconLoadListener
FaviconLoadListener::FaviconLoadListener(nsFaviconService* aFaviconService,
nsIURI* aPageURI, nsIURI* aFaviconURI,
nsIChannel* aChannel) :
mFaviconService(aFaviconService),
mChannel(aChannel),
mPageURI(aPageURI),
mFaviconURI(aFaviconURI)
{
}
// FaviconLoadListener::~FaviconLoadListener
FaviconLoadListener::~FaviconLoadListener()
{
}
// FaviconLoadListener::OnStartRequest (nsIRequestObserver)
NS_IMETHODIMP
FaviconLoadListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
{
return NS_OK;
}
// FaviconLoadListener::OnStopRequest (nsIRequestObserver)
NS_IMETHODIMP
FaviconLoadListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
nsresult aStatusCode)
{
if (NS_FAILED(aStatusCode) || mData.Length() == 0) {
// load failed, add to failed cache
mFaviconService->AddFailedFavicon(mFaviconURI);
return NS_OK;
}
// sniff the MIME type
nsresult rv;
nsCOMPtr<nsICategoryManager> categoryManager =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISimpleEnumerator> sniffers;
rv = categoryManager->EnumerateCategory(CONTENT_SNIFFING_SERVICES,
getter_AddRefs(sniffers));
NS_ENSURE_SUCCESS(rv, rv);
nsCString mimeType;
PRBool hasMore = PR_FALSE;
while (mimeType.IsEmpty() && NS_SUCCEEDED(sniffers->HasMoreElements(&hasMore))
&& hasMore) {
nsCOMPtr<nsISupports> snifferCIDSupports;
rv = sniffers->GetNext(getter_AddRefs(snifferCIDSupports));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsCString> snifferCIDSupportsCString =
do_QueryInterface(snifferCIDSupports, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString snifferCID;
rv = snifferCIDSupportsCString->GetData(snifferCID);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContentSniffer> sniffer = do_GetService(snifferCID.get(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
sniffer->GetMIMETypeFromContent(
#ifndef MOZILLA_1_8_BRANCH
aRequest,
#endif
NS_REINTERPRET_CAST(PRUint8*, NS_CONST_CAST(char*, mData.get())),
mData.Length(), mimeType);
// ignore errors: mime type will be left empty and we'll try the next sniffer
}
if (mimeType.IsEmpty()) {
// we can not handle favicons that do not have a recognisable MIME type
mFaviconService->AddFailedFavicon(mFaviconURI);
return NS_OK;
}
// Expire this favicon in one day. An old version of this actually extracted
// the expiration time from the cache. But what if people (especially web
// developers) get a bad favicon or change it? The problem is that we're not
// aware when the icon has been reloaded in the cache or cleared. This way
// we'll always pick up any changes in the cache after a day. In most cases
// re-set favicons will come from the cache anyway and reloading them is not
// very expensive.
PRTime expiration = PR_Now() +
(PRInt64)(24 * 60 * 60) * (PRInt64)PR_USEC_PER_SEC;
// save the favicon data
rv = mFaviconService->SetFaviconData(mFaviconURI,
NS_REINTERPRET_CAST(PRUint8*, NS_CONST_CAST(char*, mData.get())),
mData.Length(), mimeType, expiration);
NS_ENSURE_SUCCESS(rv, rv);
// set the favicon for the page
PRBool hasData;
rv = mFaviconService->SetFaviconUrlForPageInternal(mPageURI, mFaviconURI,
&hasData, &expiration);
NS_ENSURE_SUCCESS(rv, rv);
mFaviconService->SendFaviconNotifications(mPageURI, mFaviconURI);
mFaviconService->UpdateBookmarkRedirectFavicon(mPageURI, mFaviconURI);
return NS_OK;
}
// FaviconLoadListener::OnDataAvailable (nsIStreamListener)
NS_IMETHODIMP
FaviconLoadListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
nsIInputStream *aInputStream,
PRUint32 aOffset, PRUint32 aCount)
{
if (aOffset + aCount > MAX_FAVICON_SIZE)
return NS_ERROR_FAILURE; // too big
nsCString buffer;
nsresult rv = NS_ConsumeStream(aInputStream, aCount, buffer);
if (rv != NS_BASE_STREAM_WOULD_BLOCK && NS_FAILED(rv))
return rv;
mData.Append(buffer);
return NS_OK;
}
// FaviconLoadListener::GetInterface (nsIInterfaceRequestor)
NS_IMETHODIMP
FaviconLoadListener::GetInterface(const nsIID& uuid, void** aResult)
{
return QueryInterface(uuid, aResult);
}
// FaviconLoadListener::OnChannelRedirect (nsIChannelEventSink)
NS_IMETHODIMP
FaviconLoadListener::OnChannelRedirect(nsIChannel* oldChannel,
nsIChannel* newChannel, PRUint32 flags)
{
mChannel = newChannel;
return NS_OK;
}

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

@ -1,129 +0,0 @@
/* -*- 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 Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 "nsCOMPtr.h"
#include "nsDataHashtable.h"
#include "nsIFaviconService.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "mozIStorageConnection.h"
#include "mozIStorageValueArray.h"
#include "mozIStorageStatement.h"
// forward definition for friend class
class FaviconLoadListener;
class nsFaviconService : public nsIFaviconService
{
public:
nsFaviconService();
nsresult Init();
// called by nsNavHistory::Init
static nsresult InitTables(mozIStorageConnection* aDBConn);
/**
* Returns a cached pointer to the favicon service for consumers in the
* places directory.
*/
static nsFaviconService* GetFaviconService()
{
if (! gFaviconService) {
// note that we actually have to set the service to a variable here
// because the work in do_GetService actually happens during assignment >:(
nsresult rv;
nsCOMPtr<nsIFaviconService> serv(do_GetService("@mozilla.org/browser/favicon-service;1", &rv));
NS_ENSURE_SUCCESS(rv, nsnull);
// our constructor should have set the static variable. If it didn't,
// something is wrong.
NS_ASSERTION(gFaviconService, "Favicon service creation failed");
}
// the service manager will keep the pointer to our service around, so
// this should always be valid even if nobody currently has a reference.
return gFaviconService;
}
// internal version called by history when done lazily
nsresult DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon,
PRBool aForceReload);
// addition to API for strings to prevent excessive parsing of URIs
nsresult GetFaviconLinkForIconString(const nsCString& aIcon, nsIURI** aOutput);
void GetFaviconSpecForIconString(const nsCString& aIcon, nsACString& aOutput);
NS_DECL_ISUPPORTS
NS_DECL_NSIFAVICONSERVICE
private:
~nsFaviconService();
nsCOMPtr<mozIStorageConnection> mDBConn; // from history service
nsCOMPtr<mozIStorageStatement> mDBGetURL; // returns URL, data len given page
nsCOMPtr<mozIStorageStatement> mDBGetData; // returns actual data given URL
nsCOMPtr<mozIStorageStatement> mDBGetIconInfo;
nsCOMPtr<mozIStorageStatement> mDBInsertIcon;
nsCOMPtr<mozIStorageStatement> mDBUpdateIcon;
nsCOMPtr<mozIStorageStatement> mDBSetPageFavicon;
static nsFaviconService* gFaviconService;
/**
* A cached URI for the default icon. We return this a lot, and don't want to
* re-parse and normalize our unchanging string many times. Important: do
* not return this directly; use Clone() since callers may change the object
* they get back. May be null, in which case it needs initialization.
*/
nsCOMPtr<nsIURI> mDefaultIcon;
PRUint32 mFailedFaviconSerial;
nsDataHashtable<nsCStringHashKey, PRUint32> mFailedFavicons;
nsresult SetFaviconUrlForPageInternal(nsIURI* aURI, nsIURI* aFavicon,
PRBool* aHasData, PRTime* aExpiration);
nsresult UpdateBookmarkRedirectFavicon(nsIURI* aPage, nsIURI* aFavicon);
void SendFaviconNotifications(nsIURI* aPage, nsIURI* aFaviconURI);
friend class FaviconLoadListener;
};
#define FAVICON_DEFAULT_URL "chrome://browser/skin/places/defaultFavicon.png"
#define FAVICON_ANNOTATION_NAME "favicon"

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

@ -1,778 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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 Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Annie Sullivan <annie.sullivan@gmail.com> (original author)
* Joe Hughes <joe@retrovirus.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 "nsIRDFService.h"
#include "nsLivemarkService.h"
#include "nsIServiceManager.h"
#include "nsNavBookmarks.h"
#include "nsNavHistoryResult.h"
#include "nsIAnnotationService.h"
#include "nsFaviconService.h"
#include "nsNetUtil.h"
#include "rdf.h"
#include "nsRDFCID.h"
#include "nsIObserverService.h"
#include "nsCRT.h"
#include "nsXPCOM.h"
#define LIVEMARK_TIMEOUT 15000 // fire every 15 seconds
#define PLACES_STRING_BUNDLE_URI "chrome://browser/locale/places/places.properties"
#define LIVEMARK_ICON_URI "chrome://browser/skin/places/livemarkItem.png"
// Constants for parsing RDF Livemarks
// These are used in nsBookmarksFeedHandler.cpp, but because there is
// no initialization function in the nsLivemarkLoadListener class, they
// are initialized by the nsLivemarkService::Init() function in this file.
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
#ifndef RSS09_NAMESPACE_URI
#define RSS09_NAMESPACE_URI "http://my.netscape.com/rdf/simple/0.9/"
#endif
#ifndef RSS10_NAMESPACE_URI
#define RSS10_NAMESPACE_URI "http://purl.org/rss/1.0/"
#endif
#ifndef DC_NAMESPACE_URI
#define DC_NAMESPACE_URI "http://purl.org/dc/elements/1.1/"
#endif
nsLivemarkService* nsLivemarkService::sInstance = nsnull;
nsLivemarkService::nsLivemarkService()
: mTimer(nsnull)
{
NS_ASSERTION(!sInstance, "Multiple nsLivemarkService instances!");
sInstance = this;
}
nsLivemarkService::~nsLivemarkService()
{
NS_ASSERTION(sInstance == this, "Expected sInstance == this");
sInstance = nsnull;
}
NS_IMPL_ISUPPORTS3(nsLivemarkService,
nsILivemarkService,
nsIRemoteContainer,
nsIObserver)
nsresult
nsLivemarkService::Init()
{
nsresult rv;
// Get string bundle for livemark messages
nsCOMPtr<nsIStringBundleService> bundleService =
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = bundleService->CreateBundle(
PLACES_STRING_BUNDLE_URI,
getter_AddRefs(mBundle));
NS_ENSURE_SUCCESS(rv, rv);
// Initialize the folder icon uri.
rv = NS_NewURI(getter_AddRefs(mIconURI), NS_LITERAL_STRING(LIVEMARK_ICON_URI));
NS_ENSURE_SUCCESS(rv, rv);
// Initialize the localized strings for the names of the dummy
// "livemark loading..." and "livemark failed to load" bookmarks
rv = mBundle->GetStringFromName(NS_LITERAL_STRING("bookmarksLivemarkLoading").get(),
getter_Copies(mLivemarkLoading));
if (NS_FAILED(rv)) {
mLivemarkLoading.Assign(NS_LITERAL_STRING("Live Bookmark loading..."));
}
nsXPIDLString lmfailedName;
rv = mBundle->GetStringFromName(NS_LITERAL_STRING("bookmarksLivemarkFailed").get(),
getter_Copies(mLivemarkFailed));
if (NS_FAILED(rv)) {
mLivemarkFailed.Assign(NS_LITERAL_STRING("Live Bookmark feed failed to load."));
}
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
// Create timer to check whether to update livemarks
if (!mTimer) {
mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer");
if (NS_FAILED(rv)) return rv;
mTimer->InitWithFuncCallback(nsLivemarkService::FireTimer, this, LIVEMARK_TIMEOUT,
nsITimer::TYPE_REPEATING_SLACK);
// Note: don't addref "this" as we'll cancel the timer in the nsLivemarkService destructor
}
// Use the annotations service to store data about livemarks
mAnnotationService = do_GetService("@mozilla.org/browser/annotation-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Initialize the constants used to parse RDF livemark feeds
nsCOMPtr<nsIRDFService> pRDF;
pRDF = do_GetService(kRDFServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
pRDF->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
getter_AddRefs(mLMRDF_type));
pRDF->GetResource(NS_LITERAL_CSTRING(RSS09_NAMESPACE_URI "channel"),
getter_AddRefs(mLMRSS09_channel));
pRDF->GetResource(NS_LITERAL_CSTRING(RSS09_NAMESPACE_URI "item"),
getter_AddRefs(mLMRSS09_item));
pRDF->GetResource(NS_LITERAL_CSTRING(RSS09_NAMESPACE_URI "title"),
getter_AddRefs(mLMRSS09_title));
pRDF->GetResource(NS_LITERAL_CSTRING(RSS09_NAMESPACE_URI "link"),
getter_AddRefs(mLMRSS09_link));
pRDF->GetResource(NS_LITERAL_CSTRING(RSS10_NAMESPACE_URI "channel"),
getter_AddRefs(mLMRSS10_channel));
pRDF->GetResource(NS_LITERAL_CSTRING(RSS10_NAMESPACE_URI "items"),
getter_AddRefs(mLMRSS10_items));
pRDF->GetResource(NS_LITERAL_CSTRING(RSS10_NAMESPACE_URI "title"),
getter_AddRefs(mLMRSS10_title));
pRDF->GetResource(NS_LITERAL_CSTRING(RSS10_NAMESPACE_URI "link"),
getter_AddRefs(mLMRSS10_link));
pRDF->GetResource(NS_LITERAL_CSTRING(DC_NAMESPACE_URI "date"),
getter_AddRefs(mLMDC_date));
// Initialize the list of livemarks from the list of URIs
// that have a feed uri annotation.
nsCOMArray<nsIURI> pLivemarks;
rv = mAnnotationService->GetPagesWithAnnotationCOMArray(
NS_LITERAL_CSTRING(LMANNO_FEEDURI), &pLivemarks);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 i = 0; i < pLivemarks.Count(); ++i) {
// Get the feed URI from the annotation.
nsAutoString feedURIString;
rv = mAnnotationService->GetAnnotationString(pLivemarks[i],
NS_LITERAL_CSTRING(LMANNO_FEEDURI),
feedURIString);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> feedURI;
rv = NS_NewURI(getter_AddRefs(feedURI), NS_ConvertUTF16toUTF8(feedURIString));
NS_ENSURE_SUCCESS(rv, rv);
// Use QueryStringToQueryArray() to get the folderId from the place:uri.
// (It ends up in folders[0] since we know that this place: uri was
// generated by the bookmark service to uniquely identify the folder)
nsCAutoString folderQueryString;
rv = pLivemarks[i]->GetSpec(folderQueryString);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMArray<nsNavHistoryQuery> queries;
nsCOMPtr<nsNavHistoryQueryOptions> options;
rv = History()->QueryStringToQueryArray(folderQueryString, &queries,
getter_AddRefs(options));
NS_ENSURE_SUCCESS(rv, rv);
if (queries.Count() != 1 || queries[0]->Folders().Length() != 1)
continue; // invalid folder URI (should identify exactly one folder)
// Create the livemark and add it to the list.
LivemarkInfo *li = new LivemarkInfo(queries[0]->Folders()[0],
pLivemarks[i], feedURI);
NS_ENSURE_TRUE(li, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(mLivemarks.AppendElement(li), NS_ERROR_OUT_OF_MEMORY);
}
return rv;
}
NS_IMETHODIMP
nsLivemarkService::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *aData)
{
if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
nsresult rv;
// Clear timer and pending loads to prevent leaks of the livemark service
// during shutdown.
if (mTimer) {
// be sure to cancel the timer, as it holds a
// weak reference back to nsLivemarkService
mTimer->Cancel();
mTimer = nsnull;
}
// Cancel any pending loads
for (PRUint32 i = 0; i < mLivemarks.Length(); ++i) {
LivemarkInfo *li = mLivemarks[i];
if (li->loadGroup) {
li->loadGroup->Cancel(NS_BINDING_ABORTED);
}
}
// Remove our xpcom-shutdown observer so we don't leak the observer
// service.
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
}
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::CreateLivemark(PRInt64 aFolder,
const nsAString &aName,
nsIURI *aSiteURI,
nsIURI *aFeedURI,
PRInt32 aIndex,
PRInt64 *aNewLivemark)
{
// Create the livemark as a bookmark container
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
nsresult rv = bookmarks->CreateContainer(aFolder, aName,
NS_LITERAL_STRING(NS_LIVEMARKSERVICE_CONTRACTID),
aIndex, aNewLivemark);
NS_ENSURE_SUCCESS(rv, rv);
// Get the livemark URI
nsCOMPtr<nsIURI> livemarkURI;
rv = bookmarks->GetFolderURI(*aNewLivemark, getter_AddRefs(livemarkURI));
NS_ENSURE_SUCCESS(rv, rv);
// Add an annotation to map the folder URI to the livemark feed URI
nsCAutoString feedURISpec;
rv = aFeedURI->GetSpec(feedURISpec);
NS_ENSURE_SUCCESS(rv, rv);
mAnnotationService->SetAnnotationString(livemarkURI,
NS_LITERAL_CSTRING(LMANNO_FEEDURI),
NS_ConvertUTF8toUTF16(feedURISpec),
0,
nsIAnnotationService::EXPIRE_NEVER);
// Set the icon for the livemark
nsFaviconService* faviconService = nsFaviconService::GetFaviconService();
NS_ENSURE_TRUE(faviconService, NS_ERROR_OUT_OF_MEMORY);
faviconService->SetFaviconUrlForPage(livemarkURI, mIconURI);
if (aSiteURI) {
// Add an annotation to map the folder URI to the livemark site URI
nsCAutoString siteURISpec;
rv = aSiteURI->GetSpec(siteURISpec);
NS_ENSURE_SUCCESS(rv, rv);
rv = mAnnotationService->SetAnnotationString(livemarkURI,
NS_LITERAL_CSTRING(LMANNO_SITEURI),
NS_ConvertUTF8toUTF16(siteURISpec),
0,
nsIAnnotationService::EXPIRE_NEVER);
NS_ENSURE_SUCCESS(rv, rv);
}
// Store the livemark info in our array.
LivemarkInfo *info = new LivemarkInfo(*aNewLivemark, livemarkURI, aFeedURI);
NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(mLivemarks.AppendElement(info), NS_ERROR_OUT_OF_MEMORY);
UpdateLivemarkChildren(mLivemarks.Length() - 1, PR_FALSE);
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::IsLivemark(PRInt64 aFolder, PRBool *aResult)
{
nsresult rv;
*aResult = PR_FALSE;
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_FAILURE);
nsCOMPtr<nsIURI> folderURI;
rv = bookmarks->GetFolderURI(aFolder, getter_AddRefs(folderURI));
NS_ENSURE_SUCCESS(rv, rv);
rv = mAnnotationService->HasAnnotation(
folderURI, NS_LITERAL_CSTRING(LMANNO_FEEDURI), aResult);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::GetSiteURI(PRInt64 aContainer, nsIURI **aURI)
{
nsresult rv;
// First off, make sure we're dealing with a livemark ID.
PRBool isLivemark = PR_FALSE;
rv = IsLivemark(aContainer, &isLivemark);
NS_ENSURE_SUCCESS(rv, rv);
if (!isLivemark)
return NS_ERROR_INVALID_ARG;
// Now convert the container ID to a container URI for annotation operations
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_FAILURE);
nsCOMPtr<nsIURI> containerURI;
rv = bookmarks->GetFolderURI(aContainer, getter_AddRefs(containerURI));
NS_ENSURE_SUCCESS(rv, rv);
// If there's no site URI annotation, return null
nsAutoString siteURIString;
rv = mAnnotationService->GetAnnotationString(
containerURI, NS_LITERAL_CSTRING(LMANNO_SITEURI), siteURIString);
if (NS_FAILED(rv)) {
*aURI = nsnull;
return NS_OK;
}
nsCOMPtr<nsIURI> siteURI;
rv = NS_NewURI(getter_AddRefs(siteURI), NS_ConvertUTF16toUTF8(siteURIString));
NS_ENSURE_SUCCESS(rv, rv);
*aURI = siteURI.get();
NS_IF_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::SetSiteURI(PRInt64 aContainer, nsIURI *aSiteURI)
{
nsresult rv;
// First off, make sure we're dealing with a livemark ID.
PRBool isLivemark = PR_FALSE;
rv = IsLivemark(aContainer, &isLivemark);
NS_ENSURE_SUCCESS(rv, rv);
if (!isLivemark)
return NS_ERROR_INVALID_ARG;
// Now convert the container ID to a container URI for annotation operations
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_FAILURE);
nsCOMPtr<nsIURI> containerURI;
rv = bookmarks->GetFolderURI(aContainer, getter_AddRefs(containerURI));
NS_ENSURE_SUCCESS(rv, rv);
if (!aSiteURI) { // clear any existing site URI
rv = mAnnotationService->RemoveAnnotation(
containerURI, NS_LITERAL_CSTRING(LMANNO_SITEURI));
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsCAutoString siteURISpec;
rv = aSiteURI->GetSpec(siteURISpec);
NS_ENSURE_SUCCESS(rv, rv);
rv = mAnnotationService->SetAnnotationString(
containerURI,
NS_LITERAL_CSTRING(LMANNO_SITEURI),
NS_ConvertUTF8toUTF16(siteURISpec),
0,
nsIAnnotationService::EXPIRE_NEVER);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::GetFeedURI(PRInt64 aContainer, nsIURI **aURI)
{
nsresult rv;
// Convert the container ID to a container URI for annotation operations
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_FAILURE);
nsCOMPtr<nsIURI> containerURI;
rv = bookmarks->GetFolderURI(aContainer, getter_AddRefs(containerURI));
NS_ENSURE_SUCCESS(rv, rv);
// If there's no feed URI annotation, that means this isn't a livemark
nsAutoString feedURIString;
rv = mAnnotationService->GetAnnotationString(
containerURI, NS_LITERAL_CSTRING(LMANNO_FEEDURI), feedURIString);
if (NS_FAILED(rv))
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIURI> feedURI;
rv = NS_NewURI(getter_AddRefs(feedURI), NS_ConvertUTF16toUTF8(feedURIString));
NS_ENSURE_SUCCESS(rv, rv);
*aURI = feedURI.get();
NS_IF_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::SetFeedURI(PRInt64 aContainer, nsIURI *aFeedURI)
{
nsresult rv;
if (!aFeedURI) // a livemark folder with no feed URI is an illegal state
return NS_ERROR_NULL_POINTER;
// Convert the container ID to a container URI for annotation operations
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_FAILURE);
nsCOMPtr<nsIURI> containerURI;
rv = bookmarks->GetFolderURI(aContainer, getter_AddRefs(containerURI));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString feedURISpec;
rv = aFeedURI->GetSpec(feedURISpec);
NS_ENSURE_SUCCESS(rv, rv);
rv = mAnnotationService->SetAnnotationString(
containerURI,
NS_LITERAL_CSTRING(LMANNO_FEEDURI),
NS_ConvertUTF8toUTF16(feedURISpec),
0,
nsIAnnotationService::EXPIRE_NEVER);
NS_ENSURE_SUCCESS(rv, rv);
// Now update our internal table
PRInt32 livemarkIndex = GetLivemarkIndex(aContainer);
NS_ENSURE_TRUE(livemarkIndex > -1, NS_ERROR_FAILURE);
mLivemarks[livemarkIndex]->feedURI = aFeedURI;
return NS_OK;
}
#if 0
// These two container API functions are not currently in the remote container
// service because they are untested. We do not need them here.
NS_IMETHODIMP
nsLivemarkService::OnContainerOpening(
nsINavHistoryContainerResultNode* container,
nsINavHistoryQueryOptions* options)
{
// Nothing to do here since the containers are filled in
// as the livemarks are loaded through FireTimer().
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::OnContainerClosed(nsINavHistoryContainerResultNode* container)
{
// Nothing to clean up
return NS_OK;
}
#endif
NS_IMETHODIMP
nsLivemarkService::OnContainerRemoving(PRInt64 aContainer)
{
nsresult rv;
// Find the livemark id in the list of livemarks.
PRInt32 lmIndex = -1;
PRInt32 i;
for (i = 0; i < PRInt32(mLivemarks.Length()); i++) {
if (mLivemarks[i]->folderId == aContainer) {
lmIndex = i;
break;
}
}
// If there livemark isn't in the list, it's not valid.
if (lmIndex == -1)
return NS_ERROR_INVALID_ARG;
// Remove the annotations that link the folder URI to the
// Feed URI and Site URI
LivemarkInfo *removedItem = mLivemarks[lmIndex];
rv = mAnnotationService->RemoveAnnotation(removedItem->folderURI,
NS_LITERAL_CSTRING(LMANNO_FEEDURI));
NS_ENSURE_SUCCESS(rv, rv);
rv = mAnnotationService->RemoveAnnotation(removedItem->folderURI,
NS_LITERAL_CSTRING(LMANNO_SITEURI));
NS_ENSURE_SUCCESS(rv, rv);
// Check if there are any other livemarks pointing to this feed.
// If not, remove the annotations for the feed.
PRBool stillInUse = PR_FALSE;
PRBool urisEqual = PR_FALSE;
for (i = 0; i < PRInt32(mLivemarks.Length()); i++) {
if (i != lmIndex &&
(NS_OK == mLivemarks[i]->feedURI->Equals(removedItem->feedURI, &urisEqual)) &&
urisEqual) {
stillInUse = PR_TRUE;
break;
}
}
if (!stillInUse) {
// No other livemarks use this feed. Clear all the annotations for it.
rv = mAnnotationService->RemoveAnnotation(removedItem->feedURI,
NS_LITERAL_CSTRING("livemark_expiration"));
NS_ENSURE_SUCCESS(rv, rv);
}
// Cancel the load before we remove the element; this will ensure that
// a LivemarkLoadListener won't try to add items for this load.
if (removedItem->loadGroup) {
removedItem->loadGroup->Cancel(NS_BINDING_ABORTED);
}
// Take the annotation out of the list of annotations.
mLivemarks.RemoveElementAt(lmIndex);
// Get rid of the children for this feed, clearing their annotations.
DeleteLivemarkChildren(aContainer);
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::OnContainerMoved(PRInt64 aContainer,
PRInt64 aNewFolder,
PRInt32 aNewIndex)
{
nsresult rv;
// Find the livemark in the list.
PRInt32 index = -1;
for (PRInt32 i = 0; i < PRInt32(mLivemarks.Length()); i++) {
if (mLivemarks[i]->folderId == aContainer) {
index = i;
break;
}
}
if (index == -1)
return NS_ERROR_INVALID_ARG;
// Get the new uri
nsCOMPtr<nsIURI> newURI;
rv = nsNavBookmarks::GetBookmarksService()->GetFolderURI(aContainer,
getter_AddRefs(newURI));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> oldURI = mLivemarks[index]->folderURI;
mLivemarks[index]->folderURI = newURI;
// Update the annotation that maps the folder URI to the livemark feed URI
nsAutoString feedURIString;
rv = mAnnotationService->GetAnnotationString(oldURI,
NS_LITERAL_CSTRING(LMANNO_FEEDURI),
feedURIString);
NS_ENSURE_SUCCESS(rv, rv);
rv = mAnnotationService->RemoveAnnotation(oldURI,
NS_LITERAL_CSTRING(LMANNO_FEEDURI));
NS_ENSURE_SUCCESS(rv, rv);
rv = mAnnotationService->SetAnnotationString(newURI,
NS_LITERAL_CSTRING(LMANNO_FEEDURI),
feedURIString,
0,
nsIAnnotationService::EXPIRE_NEVER);
NS_ENSURE_SUCCESS(rv, rv);
// Update the annotation that maps the folder URI to the livemark site URI
nsAutoString siteURIString;
rv = mAnnotationService->GetAnnotationString(oldURI,
NS_LITERAL_CSTRING(LMANNO_SITEURI),
siteURIString);
// rv will be failure if no site URI annotation is present
if (NS_SUCCEEDED(rv)) {
rv = mAnnotationService->RemoveAnnotation(
oldURI,
NS_LITERAL_CSTRING(LMANNO_SITEURI));
NS_ENSURE_SUCCESS(rv, rv);
rv = mAnnotationService->SetAnnotationString(
newURI,
NS_LITERAL_CSTRING(LMANNO_SITEURI),
siteURIString,
0,
nsIAnnotationService::EXPIRE_NEVER);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::GetChildrenReadOnly(PRBool *aResult)
{
*aResult = PR_TRUE;
return NS_OK;
}
void
nsLivemarkService::FireTimer(nsITimer* aTimer, void* aClosure)
{
nsLivemarkService *lmks = NS_STATIC_CAST(nsLivemarkService *, aClosure);
if (!lmks) return;
// Go through all of the livemarks, and check if each needs to be updated.
for (PRUint32 i = 0; i < lmks->mLivemarks.Length(); i++) {
lmks->UpdateLivemarkChildren(i, PR_FALSE);
}
}
nsresult
nsLivemarkService::DeleteLivemarkChildren(PRInt64 aLivemarkFolderId)
{
nsresult rv;
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
nsNavHistory* history = History();
nsCOMPtr<nsINavHistoryQuery> query;
rv = history->GetNewQuery(getter_AddRefs(query));
NS_ENSURE_TRUE(query, NS_ERROR_OUT_OF_MEMORY);
rv = query->SetFolders(&aLivemarkFolderId, 1);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINavHistoryQueryOptions> options;
rv = history->GetNewQueryOptions(getter_AddRefs(options));
NS_ENSURE_TRUE(options, NS_ERROR_OUT_OF_MEMORY);
PRUint32 mode = nsINavHistoryQueryOptions::GROUP_BY_FOLDER;
rv = options->SetGroupingMode(&mode, 1);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINavHistoryResult> result;
rv = history->ExecuteQuery(query, options, getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINavHistoryQueryResultNode> root;
rv = result->GetRoot(getter_AddRefs(root));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 cc;
root->SetContainerOpen(PR_TRUE);
rv = root->GetChildCount(&cc);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < cc; i++) {
nsCOMPtr<nsINavHistoryResultNode> node;
rv = root->GetChild(i, getter_AddRefs(node));
if (NS_FAILED(rv)) continue;
nsCAutoString spec;
rv = node->GetUri(spec);
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), spec, nsnull);
if (NS_FAILED(rv)) continue;
rv = mAnnotationService->RemoveAnnotation(uri,
NS_LITERAL_CSTRING(LMANNO_BMANNO));
if (NS_FAILED(rv)) continue;
}
// Get the folder children.
rv = bookmarks->RemoveFolderChildren(aLivemarkFolderId);
return rv;
}
nsresult
nsLivemarkService::InsertLivemarkChild(PRInt64 aLivemarkFolderId,
nsIURI *aURI,
const nsAString &aTitle,
const nsAString &aFeedURI)
{
nsresult rv;
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
rv = bookmarks->InsertItem(aLivemarkFolderId, aURI, -1);
NS_ENSURE_SUCCESS(rv, rv);
rv = bookmarks->SetItemTitle(aURI, aTitle);
NS_ENSURE_SUCCESS(rv, rv);
mAnnotationService->SetAnnotationString(aURI,
NS_LITERAL_CSTRING(LMANNO_BMANNO),
aFeedURI,
0,
nsIAnnotationService::EXPIRE_NEVER);
return NS_OK;
}
nsresult
nsLivemarkService::InsertLivemarkLoadingItem(PRInt64 aFolder)
{
nsresult rv;
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
nsCOMPtr<nsIURI> loadingURI;
rv = NS_NewURI(getter_AddRefs(loadingURI), NS_LITERAL_CSTRING("about:livemark-loading"));
NS_ENSURE_SUCCESS(rv, rv);
rv = bookmarks->InsertItem(aFolder, loadingURI, -1);
NS_ENSURE_SUCCESS(rv, rv);
rv = bookmarks->SetItemTitle(loadingURI, mLivemarkLoading);
return rv;
}
nsresult
nsLivemarkService::InsertLivemarkFailedItem(PRInt64 aFolder)
{
nsresult rv;
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
nsCOMPtr<nsIURI> failedURI;
rv = NS_NewURI(getter_AddRefs(failedURI), NS_LITERAL_CSTRING("about:livemark-failed"));
NS_ENSURE_SUCCESS(rv, rv);
rv = bookmarks->InsertItem(aFolder, failedURI, -1);
NS_ENSURE_SUCCESS(rv, rv);
rv = bookmarks->SetItemTitle(failedURI, mLivemarkFailed);
return rv;
}
NS_IMETHODIMP
nsLivemarkService::ReloadAllLivemarks()
{
for (PRUint32 i = 0; i < mLivemarks.Length(); i++) {
UpdateLivemarkChildren(i, PR_TRUE);
}
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::ReloadLivemarkFolder(PRInt64 aFolderId)
{
PRInt32 folderIndex = GetLivemarkIndex(aFolderId);
if (folderIndex == -1)
return NS_ERROR_INVALID_ARG;
return UpdateLivemarkChildren(folderIndex, PR_TRUE);
}
// Returns the index into mLivemarks that corresponds to the given
// folder ID, or -1 if not found.
PRInt32
nsLivemarkService::GetLivemarkIndex(PRInt64 aFolderId)
{
for (PRUint32 i = 0; i < mLivemarks.Length(); i++) {
if (mLivemarks[i]->folderId == aFolderId) {
return i;
}
}
return -1;
}

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

@ -1,170 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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 Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Annie Sullivan <annie.sullivan@gmail.com> (original author)
*
* 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 "nsILivemarkService.h"
#include "nsIStringBundle.h"
#include "nsIAnnotationService.h"
#include "nsNavHistory.h"
#include "nsToolkitCompsCID.h"
#include "nsILoadGroup.h"
#include "nsIObserver.h"
/**
* This annotation's value is a string containing the URI of the
* source feed for the given livemark. It should be attached to the URI
* of the livemark container.
*/
#define LMANNO_FEEDURI "livemark/feedURI"
/**
* This annotation's value is a string containing the URI of the
* website associated with the source feed for the given livemark.
* It should be attached to the URI of the livemark container.
*/
#define LMANNO_SITEURI "livemark/siteURI"
/**
* This annotation's value is an Int64 representing the time
* (in milliseconds since January 1, 1970 GMT) when a
* livemark feed should expire and thus have its associated livemark
* refreshed. It should be attached to the URI of the livemark's
* source feed.
*/
#define LMANNO_EXPIRATION "livemark/expiration"
/**
* This annotation's value is a string containing the URI of the
* syndication feed which was this source for a livemark item.
* It should be attached to the URI of a livemark item (that is, a
* child of a livemark container).
*/
#define LMANNO_BMANNO "livemark/bookmarkFeedURI"
class nsIRDFResource;
class nsLivemarkService : public nsILivemarkService, public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREMOTECONTAINER
NS_DECL_NSILIVEMARKSERVICE
NS_DECL_NSIOBSERVER
nsLivemarkService();
nsresult Init();
static nsLivemarkService* GetLivemarkService() {
if (!sInstance) {
nsresult rv;
nsCOMPtr<nsILivemarkService> serv(do_GetService(NS_LIVEMARKSERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, nsnull);
NS_ASSERTION(sInstance, "Should have static instance pointer now");
}
return sInstance;
}
// These functions are called by the livemarks feed loader
// to set the livemark children.
nsresult DeleteLivemarkChildren(PRInt64 aLivemarkFolderId);
nsresult InsertLivemarkChild(PRInt64 aLivemarkFolderId,
nsIURI *aURI,
const nsAString &aTitle,
const nsAString &aFeedURI);
nsresult InsertLivemarkLoadingItem(PRInt64 aFolder);
nsresult InsertLivemarkFailedItem(PRInt64 aFolder);
struct LivemarkInfo {
PRInt64 folderId;
nsCOMPtr<nsIURI> folderURI;
nsCOMPtr<nsIURI> feedURI;
PRBool locked;
// Keep track of the load group that contains the channel we're using
// to load this livemark. This allows the load to be cancelled if
// necessary. The load group automatically adds redirect channels, so
// cancelling the load group cancels everything.
nsCOMPtr<nsILoadGroup> loadGroup;
LivemarkInfo(PRInt64 aFolderId, nsIURI *aFolderURI, nsIURI *aFeedURI)
: folderId(aFolderId), folderURI(aFolderURI), feedURI(aFeedURI),
locked(PR_FALSE) { }
void AddRef() { ++mRefCnt; }
void Release() { if (--mRefCnt == 0) delete this; }
private:
nsAutoRefCnt mRefCnt;
};
nsCOMPtr<nsIRDFResource> mLMRDF_type;
nsCOMPtr<nsIRDFResource> mLMRSS09_channel;
nsCOMPtr<nsIRDFResource> mLMRSS09_item;
nsCOMPtr<nsIRDFResource> mLMRSS09_title;
nsCOMPtr<nsIRDFResource> mLMRSS09_link;
nsCOMPtr<nsIRDFResource> mLMRSS10_channel;
nsCOMPtr<nsIRDFResource> mLMRSS10_items;
nsCOMPtr<nsIRDFResource> mLMRSS10_title;
nsCOMPtr<nsIRDFResource> mLMRSS10_link;
nsCOMPtr<nsIRDFResource> mLMDC_date;
private:
static nsLivemarkService *sInstance;
~nsLivemarkService();
// remove me when there is better query initialization
nsNavHistory* History() { return nsNavHistory::GetHistoryService(); }
// For localized "livemark loading...", "livemark failed to load",
// etc. messages
nsCOMPtr<nsIStringBundle> mBundle;
nsXPIDLString mLivemarkLoading;
nsXPIDLString mLivemarkFailed;
nsCOMPtr<nsIURI> mIconURI;
nsCOMPtr<nsIAnnotationService> mAnnotationService;
// The list of livemarks is stored in this array
nsTArray< nsRefPtr<LivemarkInfo> > mLivemarks;
// Livemarks are updated on a timer.
nsCOMPtr<nsITimer> mTimer;
static void FireTimer(nsITimer* aTimer, void* aClosure);
nsresult UpdateLivemarkChildren(PRInt32 aLivemarkIndex, PRBool aForceUpdate);
PRInt32 GetLivemarkIndex(PRInt64 folderID);
};

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

@ -1,114 +0,0 @@
/* -*- 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 Places code.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com> (original author)
*
* 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 "nsMaybeWeakPtr.h"
void*
nsMaybeWeakPtr_base::GetValueAs(const nsIID &iid) const
{
nsresult rv;
void *ref;
if (mPtr) {
rv = mPtr->QueryInterface(iid, &ref);
if (NS_SUCCEEDED(rv)) {
return ref;
}
}
nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(mPtr);
if (weakRef) {
rv = weakRef->QueryReferent(iid, &ref);
if (NS_FAILED(rv)) {
ref = nsnull;
}
}
return ref;
}
/* static */ nsresult
nsMaybeWeakPtrArray_base::AppendWeakElementBase(nsTArray_base *aArray,
nsISupports *aElement,
PRBool aOwnsWeak)
{
nsCOMPtr<nsISupports> ref;
if (aOwnsWeak) {
nsCOMPtr<nsIWeakReference> weakRef;
weakRef = do_GetWeakReference(aElement);
NS_REINTERPRET_CAST(nsCOMPtr<nsISupports>*, &weakRef)->swap(ref);
} else {
ref = aElement;
}
isupports_type *array = NS_STATIC_CAST(isupports_type*, aArray);
if (array->IndexOf(ref) != isupports_type::NoIndex) {
return NS_ERROR_INVALID_ARG; // already present
}
if (!array->AppendElement(ref)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
/* static */ nsresult
nsMaybeWeakPtrArray_base::RemoveWeakElementBase(nsTArray_base *aArray,
nsISupports *aElement)
{
isupports_type *array = NS_STATIC_CAST(isupports_type*, aArray);
PRUint32 index = array->IndexOf(aElement);
if (index != isupports_type::NoIndex) {
array->RemoveElementAt(index);
return NS_OK;
}
// Don't use do_GetWeakReference; it should only be called if we know
// the object supports weak references.
nsCOMPtr<nsISupportsWeakReference> supWeakRef = do_QueryInterface(aElement);
NS_ENSURE_TRUE(supWeakRef, NS_ERROR_INVALID_ARG);
nsCOMPtr<nsIWeakReference> weakRef;
nsresult rv = supWeakRef->GetWeakReference(getter_AddRefs(weakRef));
NS_ENSURE_SUCCESS(rv, rv);
index = array->IndexOf(weakRef);
if (index == isupports_type::NoIndex) {
return NS_ERROR_INVALID_ARG;
}
array->RemoveElementAt(index);
return NS_OK;
}

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

@ -1,124 +0,0 @@
/* -*- 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 Places code.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com> (original author)
*
* 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 ***** */
#ifndef nsMaybeWeakPtr_h_
#define nsMaybeWeakPtr_h_
#include "nsCOMPtr.h"
#include "nsWeakReference.h"
#include "nsTArray.h"
#ifdef MOZILLA_1_8_BRANCH
#define NS_GET_TEMPLATE_IID NS_GET_IID
#endif
// nsMaybeWeakPtr is a helper object to hold a strong-or-weak reference
// to the template class. It's pretty minimal, but sufficient.
class nsMaybeWeakPtr_base
{
protected:
// Returns an addref'd pointer to the requested interface
void* GetValueAs(const nsIID& iid) const;
nsCOMPtr<nsISupports> mPtr;
};
template<class T>
class nsMaybeWeakPtr : private nsMaybeWeakPtr_base
{
public:
nsMaybeWeakPtr(nsISupports *ref) { mPtr = ref; }
nsMaybeWeakPtr(const nsCOMPtr<nsIWeakReference> &ref) { mPtr = ref; }
nsMaybeWeakPtr(const nsCOMPtr<T> &ref) { mPtr = ref; }
PRBool operator==(const nsMaybeWeakPtr<T> &other) const {
return mPtr == other.mPtr;
}
operator const nsCOMPtr<T>() const { return GetValue(); }
protected:
const nsCOMPtr<T> GetValue() const {
return nsCOMPtr<T>(dont_AddRef(NS_STATIC_CAST(T*,
GetValueAs(NS_GET_TEMPLATE_IID(T)))));
}
};
// nsMaybeWeakPtrArray is an array of MaybeWeakPtr objects, that knows how to
// grab a weak reference to a given object if requested. It only allows a
// given object to appear in the array once.
class nsMaybeWeakPtrArray_base
{
protected:
static nsresult AppendWeakElementBase(nsTArray_base *aArray,
nsISupports *aElement, PRBool aWeak);
static nsresult RemoveWeakElementBase(nsTArray_base *aArray,
nsISupports *aElement);
typedef nsTArray< nsMaybeWeakPtr<nsISupports> > isupports_type;
};
template<class T>
class nsMaybeWeakPtrArray : public nsTArray< nsMaybeWeakPtr<T> >,
private nsMaybeWeakPtrArray_base
{
public:
nsresult AppendWeakElement(T *aElement, PRBool aOwnsWeak)
{
return AppendWeakElementBase(this, aElement, aOwnsWeak);
}
nsresult RemoveWeakElement(T *aElement)
{
return RemoveWeakElementBase(this, aElement);
}
};
// Call a method on each element in the array, but only if the element is
// non-null.
#define ENUMERATE_WEAKARRAY(array, type, method) \
for (PRUint32 array_idx = 0; array_idx < array.Length(); ++array_idx) { \
const nsCOMPtr<type> &e = array.ElementAt(array_idx); \
if (e) \
e->method; \
}
#endif

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

@ -1,255 +0,0 @@
/* -*- 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 Places.
*
* 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):
* Brian Ryner <bryner@brianryner.com> (original author)
*
* 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 "nsMorkHistoryImporter.h"
#include "nsNavHistory.h"
#include "mozStorageHelper.h"
#include "prprf.h"
#include "nsNetUtil.h"
#include "nsTArray.h"
NS_IMPL_ISUPPORTS1(nsMorkHistoryImporter, nsIMorkHistoryImporter)
// Columns for entry (non-meta) history rows
enum {
kURLColumn,
kNameColumn,
kVisitCountColumn,
kHiddenColumn,
kTypedColumn,
kLastVisitColumn,
kColumnCount // keep me last
};
static const char * const gColumnNames[] = {
"URL", "Name", "VisitCount", "Hidden", "Typed", "LastVisitDate"
};
struct TableReadClosure
{
TableReadClosure(nsMorkReader *aReader, nsNavHistory *aHistory)
: reader(aReader), history(aHistory), swapBytes(PR_FALSE),
byteOrderColumn(-1)
{
NS_CONST_CAST(nsString*, &voidString)->SetIsVoid(PR_TRUE);
for (PRUint32 i = 0; i < kColumnCount; ++i) {
columnIndexes[i] = -1;
}
}
// Backpointers to the reader and history we're operating on
const nsMorkReader *reader;
nsNavHistory *history;
// A voided string to use for the user title
const nsString voidString;
// Whether we need to swap bytes (file format is other-endian)
PRBool swapBytes;
// Indexes of the columns that we care about
PRInt32 columnIndexes[kColumnCount];
PRInt32 byteOrderColumn;
};
// Reverses the high and low bytes in a PRUnichar buffer.
// This is used if the file format has a different endianness from the
// current architecture.
static void
SwapBytes(PRUnichar *buffer)
{
for (PRUnichar *b = buffer; *b; ++b) {
PRUnichar c = *b;
*b = (c << 8) | ((c >> 8) & 0xff);
}
}
// Enumerator callback to add a table row to the NavHistoryService
/* static */ PLDHashOperator PR_CALLBACK
nsMorkHistoryImporter::AddToHistoryCB(const nsCSubstring &aRowID,
const nsTArray<nsCString> *aValues,
void *aData)
{
TableReadClosure *data = NS_STATIC_CAST(TableReadClosure*, aData);
const nsMorkReader *reader = data->reader;
nsCString values[kColumnCount];
const PRInt32 *columnIndexes = data->columnIndexes;
for (PRInt32 i = 0; i < kColumnCount; ++i) {
if (columnIndexes[i] != -1) {
values[i] = (*aValues)[columnIndexes[i]];
reader->NormalizeValue(values[i]);
}
}
// title is really a UTF-16 string at this point
nsCString &titleC = values[kNameColumn];
PRUint32 titleLength;
const char *titleBytes;
if (titleC.IsEmpty()) {
titleBytes = "\0";
titleLength = 0;
} else {
titleLength = titleC.Length() / 2;
// add an extra null byte onto the end, so that the buffer ends
// with a complete unicode null character.
titleC.Append('\0');
// Swap the bytes in the unicode characters if necessary.
if (data->swapBytes) {
SwapBytes(NS_REINTERPRET_CAST(PRUnichar*, titleC.BeginWriting()));
}
titleBytes = titleC.get();
}
const PRUnichar *title = NS_REINTERPRET_CAST(const PRUnichar*, titleBytes);
PRInt32 err;
PRInt32 count = values[kVisitCountColumn].ToInteger(&err);
if (err != 0 || count == 0) {
count = 1;
}
PRTime date;
if (PR_sscanf(values[kLastVisitColumn].get(), "%lld", &date) != 1) {
date = -1;
}
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), values[kURLColumn]);
if (uri) {
PRBool isTyped = values[kTypedColumn].EqualsLiteral("1");
PRInt32 transition = isTyped ?
(PRInt32) nsINavHistoryService::TRANSITION_TYPED
: (PRInt32) nsINavHistoryService::TRANSITION_LINK;
nsNavHistory *history = data->history;
history->AddPageWithVisit(uri,
nsDependentString(title, titleLength),
data->voidString,
values[kHiddenColumn].EqualsLiteral("1"),
isTyped, count, transition, date);
}
return PL_DHASH_NEXT;
}
// ImportHistory is the main entry point to the importer.
// It sets up the file stream and loops over the lines in the file to
// parse them, then adds the resulting row set to history.
NS_IMETHODIMP
nsMorkHistoryImporter::ImportHistory(nsIFile *aFile,
nsINavHistoryService *aHistory)
{
NS_ENSURE_TRUE(aFile && aHistory, NS_ERROR_NULL_POINTER);
// Check that the file exists before we try to open it
PRBool exists;
aFile->Exists(&exists);
if (!exists) {
return NS_OK;
}
// Read in the mork file
nsMorkReader reader;
nsresult rv = reader.Init();
NS_ENSURE_SUCCESS(rv, rv);
rv = reader.Read(aFile);
NS_ENSURE_SUCCESS(rv, rv);
// Gather up the column ids so we don't need to find them on each row
nsNavHistory *history = NS_STATIC_CAST(nsNavHistory*, aHistory);
TableReadClosure data(&reader, history);
const nsTArray<nsMorkReader::MorkColumn> &columns = reader.GetColumns();
for (PRUint32 i = 0; i < columns.Length(); ++i) {
const nsCSubstring &name = columns[i].name;
for (PRUint32 j = 0; j < kColumnCount; ++j) {
if (name.Equals(gColumnNames[j])) {
data.columnIndexes[j] = i;
break;
}
}
if (name.EqualsLiteral("ByteOrder")) {
data.byteOrderColumn = i;
}
}
// Determine the byte order from the table's meta-row.
const nsTArray<nsCString> *metaRow = reader.GetMetaRow();
if (metaRow && data.byteOrderColumn != -1) {
const nsCString &byteOrder = (*metaRow)[data.byteOrderColumn];
if (!byteOrder.IsVoid()) {
// Note whether the file uses a non-native byte ordering.
// If it does, we'll have to swap bytes for PRUnichar values.
// "BE" and "LE" are the only recognized values, anything
// else is garbage and the file will be treated as native-endian
// (no swapping).
nsCAutoString byteOrderValue(byteOrder);
reader.NormalizeValue(byteOrderValue);
#ifdef IS_LITTLE_ENDIAN
data.swapBytes = byteOrderValue.EqualsLiteral("BE");
#else
data.swapBytes = byteOrderValue.EqualsLiteral("LE");
#endif
}
}
// Now add the results to history
mozIStorageConnection *conn = history->GetStorageConnection();
NS_ENSURE_TRUE(conn, NS_ERROR_NOT_INITIALIZED);
mozStorageTransaction transaction(conn, PR_FALSE);
#ifdef IN_MEMORY_LINKS
mozIStorageConnection *memoryConn = history->GetMemoryStorageConnection();
mozStorageTransaction memTransaction(memoryConn, PR_FALSE);
#endif
reader.EnumerateRows(AddToHistoryCB, &data);
// Make sure we don't have any duplicate items in the database.
rv = history->RemoveDuplicateURIs();
NS_ENSURE_SUCCESS(rv, rv);
#ifdef IN_MEMORY_LINKS
memTransaction.Commit();
#endif
return transaction.Commit();
}

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

@ -1,66 +0,0 @@
/* -*- 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 Places.
*
* 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):
* Brian Ryner <bryner@brianryner.com> (original author)
*
* 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 ***** */
#ifndef nsMorkHistoryImporter_h_
#define nsMorkHistoryImporter_h_
#include "nsINavHistoryService.h"
#include "nsMorkReader.h"
template<class E> class nsTArray;
// The nsMorkHistoryImporter object parses a Mork-format history file and
// adds the history items to the NavHistoryService. It is invoked the first
// time the history service is created for a given profile, if a Mork history
// (history.dat) file exists.
class nsMorkHistoryImporter : public nsIMorkHistoryImporter
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMORKHISTORYIMPORTER
private:
// Enumerator callback to add a single row to the NavHistory.
static PLDHashOperator PR_CALLBACK
AddToHistoryCB(const nsCSubstring &aRowID,
const nsTArray<nsCString> *aValues,
void *aData);
};
#endif // nsMorkHistoryImporter_h_

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

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

@ -1,263 +0,0 @@
/* -*- 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 Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com> (original author)
*
* 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 ***** */
#ifndef nsNavBookmarks_h_
#define nsNavBookmarks_h_
#include "nsINavBookmarksService.h"
#include "nsIStringBundle.h"
#include "nsITransaction.h"
#include "nsNavHistory.h"
#include "nsNavHistoryResult.h" // need for Int64 hashtable
#include "nsToolkitCompsCID.h"
class nsIOutputStream;
class nsNavBookmarks : public nsINavBookmarksService,
public nsINavHistoryObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSINAVBOOKMARKSSERVICE
NS_DECL_NSINAVHISTORYOBSERVER
nsNavBookmarks();
nsresult Init();
// called by nsNavHistory::Init
static nsresult InitTables(mozIStorageConnection* aDBConn);
static nsNavBookmarks* GetBookmarksService() {
if (!sInstance) {
nsresult rv;
nsCOMPtr<nsINavBookmarksService> serv(do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, nsnull);
NS_ASSERTION(sInstance, "Should have static instance pointer now");
}
return sInstance;
}
nsresult AddBookmarkToHash(PRInt64 aBookmarkId, PRTime aMinTime);
nsresult ResultNodeForFolder(PRInt64 aID, nsNavHistoryQueryOptions *aOptions,
nsNavHistoryResultNode **aNode);
// Find all the children of a folder, using the given query and options.
// For each child, a ResultNode is created and added to |children|.
// The results are ordered by folder position.
nsresult QueryFolderChildren(PRInt64 aFolderId,
nsNavHistoryQueryOptions *aOptions,
nsCOMArray<nsNavHistoryResultNode> *children);
// If aFolder is -1, uses the autoincrement id for folder index. Returns
// the index of the new folder in aIndex, whether it was passed in or
// generated by autoincrement. If aSendNotifications is true, sends
// OnFolderAdded notifications to bookmark observers.
nsresult CreateFolderWithID(PRInt64 aFolder, PRInt64 aParent,
const nsAString& title,
PRBool aSendNotifications,
PRInt32 *aIndex, PRInt64* aNewFolder);
// Creates a new container of the given type. If aFolder is -1, uses the
// autoincrement id for folder index. Sends OnFolderAdded notifications
// to all observers after the folder has been created and its type has
// been set.
nsresult CreateContainerWithID(PRInt64 aFolder, PRInt64 aParent,
const nsAString& title, const nsAString& type,
PRInt32 aIndex, PRInt64* aNewFolder);
// Returns a statement to get information about a folder id
mozIStorageStatement* DBGetFolderInfo() { return mDBGetFolderInfo; }
// constants for the above statement
static const PRInt32 kGetFolderInfoIndex_FolderID;
static const PRInt32 kGetFolderInfoIndex_Title;
static const PRInt32 kGetFolderInfoIndex_Type;
private:
static nsNavBookmarks *sInstance;
~nsNavBookmarks();
nsresult InitRoots();
nsresult CreateRoot(mozIStorageStatement* aGetRootStatement,
const nsCString& name, PRInt64* aID,
PRBool* aWasCreated);
nsresult AdjustIndices(PRInt64 aFolder,
PRInt32 aStartIndex, PRInt32 aEndIndex,
PRInt32 aDelta);
PRInt32 FolderCount(PRInt64 aFolder);
nsresult GetFolderType(PRInt64 aFolder, nsACString &aType);
// remove me when there is better query initialization
nsNavHistory* History() { return nsNavHistory::GetHistoryService(); }
mozIStorageStatement* DBGetURLPageInfo()
{ return History()->DBGetURLPageInfo(); }
mozIStorageConnection* DBConn() { return History()->GetStorageConnection(); }
nsMaybeWeakPtrArray<nsINavBookmarkObserver> mObservers;
PRInt64 mRoot;
PRInt64 mBookmarksRoot;
PRInt64 mToolbarRoot;
PRInt64 mTagRoot;
// the level of nesting of batches, 0 when no batches are open
PRInt32 mBatchLevel;
// true if the outermost batch has an associated transaction that should
// be committed when our batch level reaches 0 again.
PRBool mBatchHasTransaction;
// This stores a mapping from all pages reachable by redirects from bookmarked
// pages to the bookmarked page. Used by GetBookmarkedURIFor.
nsDataHashtable<nsTrimInt64HashKey, PRInt64> mBookmarksHash;
nsresult FillBookmarksHash();
nsresult RecursiveAddBookmarkHash(PRInt64 aBookmarkId, PRInt64 aCurrentSource,
PRTime aMinTime);
nsresult UpdateBookmarkHashOnRemove(PRInt64 aBookmarkId);
nsresult GetParentAndIndexOfFolder(PRInt64 aFolder, PRInt64* aParent,
PRInt32* aIndex);
nsresult IsBookmarkedInDatabase(PRInt64 aBookmarkID, PRBool* aIsBookmarked);
nsCOMPtr<mozIStorageStatement> mDBGetFolderInfo; // kGetFolderInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBGetChildren; // kGetInfoIndex_* results + kGetChildrenIndex_* results
static const PRInt32 kGetChildrenIndex_Position;
static const PRInt32 kGetChildrenIndex_ItemChild;
static const PRInt32 kGetChildrenIndex_FolderChild;
static const PRInt32 kGetChildrenIndex_FolderTitle;
nsCOMPtr<mozIStorageStatement> mDBFindURIBookmarks; // kFindBookmarksIndex_* results
static const PRInt32 kFindBookmarksIndex_ItemChild;
static const PRInt32 kFindBookmarksIndex_FolderChild;
static const PRInt32 kFindBookmarksIndex_Parent;
static const PRInt32 kFindBookmarksIndex_Position;
nsCOMPtr<mozIStorageStatement> mDBFolderCount;
nsCOMPtr<mozIStorageStatement> mDBIndexOfItem;
nsCOMPtr<mozIStorageStatement> mDBIndexOfFolder;
nsCOMPtr<mozIStorageStatement> mDBGetChildAt;
nsCOMPtr<mozIStorageStatement> mDBGetRedirectDestinations;
// keywords
nsCOMPtr<mozIStorageStatement> mDBGetKeywordForURI;
nsCOMPtr<mozIStorageStatement> mDBGetURIForKeyword;
nsCOMPtr<nsIStringBundle> mBundle;
class RemoveFolderTransaction : public nsITransaction {
public:
RemoveFolderTransaction(PRInt64 aID, PRInt64 aParent,
const nsAString& aTitle, PRInt32 aIndex,
const nsACString& aType)
: mID(aID),
mParent(aParent),
mIndex(aIndex){
mTitle = aTitle;
mType = aType;
}
NS_DECL_ISUPPORTS
NS_IMETHOD DoTransaction() {
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
return bookmarks->RemoveFolder(mID);
}
NS_IMETHOD UndoTransaction() {
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
PRInt64 newFolder;
// If the transaction has no specific type, default to a folder, and send notifications
// to all bookmark observers (controlled by the PR_TRUE argument to CreateFolderWithID).
if (mType.IsEmpty())
return bookmarks->CreateFolderWithID(mID, mParent, mTitle, PR_TRUE, &mIndex, &newFolder);
nsAutoString type; type.AssignWithConversion(mType);
return bookmarks->CreateContainerWithID(mID, mParent, mTitle, type, mIndex, &newFolder);
}
NS_IMETHOD RedoTransaction() {
return DoTransaction();
}
NS_IMETHOD GetIsTransient(PRBool* aResult) {
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHOD Merge(nsITransaction* aTransaction, PRBool* aResult) {
*aResult = PR_FALSE;
return NS_OK;
}
private:
PRInt64 mID;
PRInt64 mParent;
nsString mTitle;
nsCString mType;
PRInt32 mIndex;
};
// in nsBookmarksHTML
nsresult ImportBookmarksHTMLInternal(nsIURI* aURL,
PRBool aAllowRootChanges,
PRInt64 aFolder);
nsresult WriteContainer(PRInt64 aFolder, const nsCString& aIndent,
nsIOutputStream* aOutput);
nsresult WriteContainerHeader(PRInt64 aFolder, const nsCString& aIndent,
nsIOutputStream* aOutput);
nsresult WriteContainerTitle(PRInt64 aFolder, nsIOutputStream* aOutput);
nsresult WriteLivemark(PRInt64 aFolderId, const nsCString& aIndent,
nsIOutputStream* aOutput);
nsresult WriteContainerContents(PRInt64 aFolder, const nsCString& aIndent,
nsIOutputStream* aOutput);
};
struct nsBookmarksUpdateBatcher
{
nsBookmarksUpdateBatcher() { nsNavBookmarks::GetBookmarksService()->BeginUpdateBatch(); }
~nsBookmarksUpdateBatcher() { nsNavBookmarks::GetBookmarksService()->EndUpdateBatch(); }
};
#endif // nsNavBookmarks_h_

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

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

@ -1,610 +0,0 @@
/* -*- 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 Places code.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
#ifndef nsNavHistory_h_
#define nsNavHistory_h_
#include "mozIStorageService.h"
#include "mozIStorageConnection.h"
#include "mozIStorageValueArray.h"
#include "mozIStorageStatement.h"
#include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsDataHashtable.h"
#include "nsIAtom.h"
#include "nsINavHistoryService.h"
#include "nsIAutoCompleteSearch.h"
#include "nsIAutoCompleteResult.h"
#include "nsIAutoCompleteSimpleResult.h"
#include "nsIBrowserHistory.h"
#include "nsICollation.h"
#include "nsIDateTimeFormat.h"
#include "nsIGlobalHistory.h"
#include "nsIGlobalHistory3.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsServiceManagerUtils.h"
#include "nsIStringBundle.h"
#include "nsITimer.h"
#include "nsITreeSelection.h"
#include "nsITreeView.h"
#include "nsString.h"
#include "nsVoidArray.h"
#include "nsWeakReference.h"
#include "nsTArray.h"
#include "nsINavBookmarksService.h"
#include "nsMaybeWeakPtr.h"
#include "nsNavHistoryExpire.h"
#include "nsNavHistoryResult.h"
#include "nsNavHistoryQuery.h"
// set to use more optimized (in-memory database) link coloring
//#define IN_MEMORY_LINKS
// define to enable lazy link adding
#define LAZY_ADD
#define QUERYUPDATE_TIME 0
#define QUERYUPDATE_SIMPLE 1
#define QUERYUPDATE_COMPLEX 2
#define QUERYUPDATE_COMPLEX_WITH_BOOKMARKS 3
class AutoCompleteIntermediateResult;
class AutoCompleteResultComparator;
class mozIAnnotationService;
class nsNavHistory;
class nsNavBookmarks;
class QueryKeyValuePair;
// nsNavHistory
class nsNavHistory : public nsSupportsWeakReference,
public nsINavHistoryService,
public nsIObserver,
public nsIBrowserHistory,
public nsIGlobalHistory3,
public nsIAutoCompleteSearch
{
friend class AutoCompleteIntermediateResultSet;
friend class AutoCompleteResultComparator;
public:
nsNavHistory();
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYSERVICE
NS_DECL_NSIGLOBALHISTORY2
NS_DECL_NSIGLOBALHISTORY3
NS_DECL_NSIBROWSERHISTORY
NS_DECL_NSIOBSERVER
NS_DECL_NSIAUTOCOMPLETESEARCH
nsresult Init();
/**
* Used by other components in the places directory such as the annotation
* service to get a reference to this history object. Returns a pointer to
* the service if it exists. Otherwise creates one. Returns NULL on error.
*/
static nsNavHistory* GetHistoryService()
{
if (! gHistoryService) {
nsresult rv;
nsCOMPtr<nsINavHistoryService> serv(do_GetService("@mozilla.org/browser/nav-history-service;1", &rv));
NS_ENSURE_SUCCESS(rv, nsnull);
// our constructor should have set the static variable. If it didn't,
// something is wrong.
NS_ASSERTION(gHistoryService, "History service creation failed");
}
return gHistoryService;
}
/**
* Call this function before doing any database reads. It will ensure that
* any data not flushed to the DB yet is flushed.
*/
void SyncDB()
{
#ifdef LAZY_ADD
CommitLazyMessages();
#endif
}
#ifdef LAZY_ADD
/**
* Adds a lazy message for adding a favicon. Used by the favicon service so
* that favicons are handled lazily just like page adds.
*/
nsresult AddLazyLoadFaviconMessage(nsIURI* aPage, nsIURI* aFavicon,
PRBool aForceReload);
#endif
/**
* Returns the database ID for the given URI, or 0 if not found an autoCreate
* is false.
*/
nsresult GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID,
PRBool aAutoCreate);
/**
* Returns a pointer to the storage connection used by history. This
* connection object is also used by the annotation service and bookmarks, so
* that things can be grouped into transactions across these components.
*
* NOT ADDREFed.
*
* This connection can only be used in the thread that created it the
* history service!
*/
mozIStorageConnection* GetStorageConnection()
{
return mDBConn;
}
#ifdef IN_MEMORY_LINKS
mozIStorageConnection* GetMemoryStorageConnection()
{
return mMemDBConn;
}
#endif
// see comment above StartDummyStatement
nsresult StartDummyStatement();
nsresult StopDummyStatement();
/**
* These functions return non-owning references to the locale-specific
* objects for places components. Guaranteed to return non-NULL.
*/
nsIStringBundle* GetBundle()
{ return mBundle; }
nsILocale* GetLocale()
{ return mLocale; }
nsICollation* GetCollation()
{ return mCollation; }
nsIDateTimeFormat* GetDateFormatter()
{ return mDateFormatter; }
// returns true if history has been disabled
PRBool IsHistoryDisabled() { return mExpireDays == 0; }
// remember tree state
void SaveExpandItem(const nsAString& aTitle);
void SaveCollapseItem(const nsAString& aTitle);
// get the statement for selecting a history row by URL
mozIStorageStatement* DBGetURLPageInfo() { return mDBGetURLPageInfo; }
// Constants for the columns returned by the above statement.
static const PRInt32 kGetInfoIndex_PageID;
static const PRInt32 kGetInfoIndex_URL;
static const PRInt32 kGetInfoIndex_Title;
static const PRInt32 kGetInfoIndex_UserTitle;
static const PRInt32 kGetInfoIndex_RevHost;
static const PRInt32 kGetInfoIndex_VisitCount;
// select a history row by URL, with visit date info (extra work)
mozIStorageStatement* DBGetURLPageInfoFull()
{ return mDBGetURLPageInfoFull; }
// select a history row by id
mozIStorageStatement* DBGetIdPageInfo() { return mDBGetIdPageInfo; }
// select a history row by id, with visit date info (extra work)
mozIStorageStatement* DBGetIdPageInfoFull()
{ return mDBGetIdPageInfoFull; }
// Constants for the columns returned by the above statement
// (in addition to the ones above).
static const PRInt32 kGetInfoIndex_VisitDate;
static const PRInt32 kGetInfoIndex_FaviconURL;
// used in execute queries to get session ID info (only for visits)
static const PRInt32 kGetInfoIndex_SessionId;
static nsIAtom* sMenuRootAtom;
static nsIAtom* sToolbarRootAtom;
static nsIAtom* sSessionStartAtom;
static nsIAtom* sSessionContinueAtom;
static nsIAtom* sContainerAtom;
// this actually executes a query and gives you results, it is used by
// nsNavHistoryQueryResultNode
nsresult GetQueryResults(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions *aOptions,
nsCOMArray<nsNavHistoryResultNode>* aResults);
// Take a row of kGetInfoIndex_* columns and construct a ResultNode.
// The row must contain the full set of columns.
nsresult RowToResult(mozIStorageValueArray* aRow,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aResult);
nsresult QueryRowToResult(const nsACString& aURI, const nsACString& aTitle,
PRUint32 aAccessCount, PRTime aTime,
const nsACString& aFavicon,
nsNavHistoryResultNode** aNode);
nsresult VisitIdToResultNode(PRInt64 visitId,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aResult);
nsresult UriToResultNode(nsIURI* aUri,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aResult);
// used by other places components to send history notifications (for example,
// when the favicon has changed)
void SendPageChangedNotification(nsIURI* aURI, PRUint32 aWhat,
const nsAString& aValue)
{
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
OnPageChanged(aURI, aWhat, aValue));
}
// current time optimization
PRTime GetNow();
// well-known annotations used by the history and bookmarks systems
static const char kAnnotationPreviousEncoding[];
// used by query result nodes to update: see comment on body of CanLiveUpdateQuery
static PRUint32 GetUpdateRequirements(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions,
PRBool* aHasSearchTerms);
PRBool EvaluateQueryForNode(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode* aNode);
static nsresult AsciiHostNameFromHostString(const nsACString& aHostName,
nsACString& aAscii);
static void DomainNameFromHostName(const nsCString& aHostName,
nsACString& aDomainName);
static PRTime NormalizeTime(PRUint32 aRelative, PRTime aOffset);
nsresult RecursiveGroup(const nsCOMArray<nsNavHistoryResultNode>& aSource,
const PRUint32* aGroupingMode, PRUint32 aGroupCount,
nsCOMArray<nsNavHistoryResultNode>* aDest);
// better alternative to QueryStringToQueries (in nsNavHistoryQuery.cpp)
nsresult QueryStringToQueryArray(const nsACString& aQueryString,
nsCOMArray<nsNavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions** aOptions);
// Import-friendly version of SetPageDetails + AddVisit.
// This method adds a page to history along with a single last visit.
// It is an error to call this method if aURI might already be in history.
// The given aVisitCount should include the given last-visit date.
// aLastVisitDate can be -1 if there is no last visit date to record.
nsresult AddPageWithVisit(nsIURI *aURI,
const nsString &aTitle,
const nsString &aUserTitle,
PRBool aHidden, PRBool aTyped,
PRInt32 aVisitCount,
PRInt32 aLastVisitTransition,
PRTime aLastVisitDate);
// Checks the database for any duplicate URLs. If any are found,
// all but the first are removed. This must be called after using
// AddPageWithVisit, to ensure that the database is in a consistent state.
nsresult RemoveDuplicateURIs();
private:
~nsNavHistory();
// used by GetHistoryService
static nsNavHistory* gHistoryService;
protected:
//
// Constants
//
nsCOMPtr<nsIPrefBranch> mPrefBranch; // MAY BE NULL when we are shutting down
nsDataHashtable<nsStringHashKey, int> gExpandedItems;
//
// Database stuff
//
nsCOMPtr<mozIStorageService> mDBService;
nsCOMPtr<mozIStorageConnection> mDBConn;
nsCOMPtr<mozIStorageStatement> mDBGetURLPageInfo; // kGetInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBGetURLPageInfoFull; // kGetInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBGetIdPageInfo; // kGetInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBGetIdPageInfoFull; // kGetInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBFullAutoComplete; // kAutoCompleteIndex_* results, 1 arg (max # results)
static const PRInt32 kAutoCompleteIndex_URL;
static const PRInt32 kAutoCompleteIndex_Title;
static const PRInt32 kAutoCompleteIndex_UserTitle;
static const PRInt32 kAutoCompleteIndex_VisitCount;
static const PRInt32 kAutoCompleteIndex_Typed;
nsCOMPtr<mozIStorageStatement> mDBRecentVisitOfURL; // converts URL into most recent visit ID/session ID
nsCOMPtr<mozIStorageStatement> mDBInsertVisit; // used by AddVisit
nsCOMPtr<mozIStorageStatement> mDBGetPageVisitStats; // used by AddVisit
nsCOMPtr<mozIStorageStatement> mDBUpdatePageVisitStats; // used by AddVisit
nsCOMPtr<mozIStorageStatement> mDBAddNewPage; // used by InternalAddNewPage
// these are used by VisitIdToResultNode for making new result nodes from IDs
nsCOMPtr<mozIStorageStatement> mDBVisitToURLResult; // kGetInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBVisitToVisitResult; // kGetInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBUrlToUrlResult; // kGetInfoIndex_* results
nsresult InitDB(PRBool *aDoImport);
nsresult InitStatements();
#ifdef IN_MEMORY_LINKS
// this is the cache DB in memory used for storing visited URLs
nsCOMPtr<mozIStorageConnection> mMemDBConn;
nsCOMPtr<mozIStorageStatement> mMemDBAddPage;
nsCOMPtr<mozIStorageStatement> mMemDBGetPage;
nsresult InitMemDB();
#endif
// this statement is kept open to persist the cache, see InitDB
nsCOMPtr<mozIStorageConnection> mDummyDBConn;
nsCOMPtr<mozIStorageStatement> mDBDummyStatement;
nsresult AddURIInternal(nsIURI* aURI, PRTime aTime, PRBool aRedirect,
PRBool aToplevel, nsIURI* aReferrer);
nsresult AddVisitChain(nsIURI* aURI, PRTime aTime,
PRBool aToplevel, PRBool aRedirect,
nsIURI* aReferrer, PRInt64* aVisitID,
PRInt64* aSessionID, PRInt64* aRedirectBookmark);
nsresult InternalAddNewPage(nsIURI* aURI, const nsAString& aTitle,
PRBool aHidden, PRBool aTyped,
PRInt32 aVisitCount, PRInt64* aPageID);
nsresult InternalAddVisit(PRInt64 aPageID, PRInt64 aReferringVisit,
PRInt64 aSessionID, PRTime aTime,
PRInt32 aTransitionType, PRInt64* aVisitID);
PRBool FindLastVisit(nsIURI* aURI, PRInt64* aVisitID,
PRInt64* aSessionID);
PRBool IsURIStringVisited(const nsACString& url);
nsresult LoadPrefs();
// Current time optimization
PRTime mLastNow;
PRBool mNowValid;
nsCOMPtr<nsITimer> mExpireNowTimer;
static void expireNowTimerCallback(nsITimer* aTimer, void* aClosure);
// expiration
friend class nsNavHistoryExpire;
nsNavHistoryExpire mExpire;
#ifdef LAZY_ADD
// lazy add committing
struct LazyMessage {
enum MessageType { Type_Invalid, Type_AddURI, Type_Title, Type_Favicon };
LazyMessage()
{
type = Type_Invalid;
isRedirect = PR_FALSE;
isToplevel = PR_FALSE;
time = 0;
alwaysLoadFavicon = PR_FALSE;
}
// call this with common parms to initialize. Caller is responsible for
// setting other elements manually depending on type.
nsresult Init(MessageType aType, nsIURI* aURI)
{
type = aType;
nsresult rv = aURI->Clone(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
return uri->GetSpec(uriSpec);
}
// common elements
MessageType type;
nsCOMPtr<nsIURI> uri;
nsCString uriSpec; // stringified version of URI, for quick isVisited
// valid when type == Type_AddURI
nsCOMPtr<nsIURI> referrer;
PRBool isRedirect;
PRBool isToplevel;
PRTime time;
// valid when type == Type_Title
nsString title;
// valid when type == LAZY_FAVICON
nsCOMPtr<nsIURI> favicon;
PRBool alwaysLoadFavicon;
};
nsTArray<LazyMessage> mLazyMessages;
nsCOMPtr<nsITimer> mLazyTimer;
PRBool mLazyTimerSet;
PRUint32 mLazyTimerDeferments; // see StartLazyTimer
nsresult StartLazyTimer();
nsresult AddLazyMessage(const LazyMessage& aMessage);
static void LazyTimerCallback(nsITimer* aTimer, void* aClosure);
void CommitLazyMessages();
#endif
nsresult QueryToSelectClause(nsNavHistoryQuery* aQuery,
PRInt32 aStartParameter,
nsCString* aClause,
PRInt32* aParamCount,
const nsACString& aCommonConditions);
nsresult BindQueryClauseParameters(mozIStorageStatement* statement,
PRInt32 aStartParameter,
nsNavHistoryQuery* aQuery,
PRInt32* aParamCount);
nsresult ResultsAsList(mozIStorageStatement* statement,
nsNavHistoryQueryOptions* aOptions,
nsCOMArray<nsNavHistoryResultNode>* aResults);
void TitleForDomain(const nsCString& domain, nsACString& aTitle);
nsresult SetPageTitleInternal(nsIURI* aURI, PRBool aIsUserTitle,
const nsAString& aTitle);
nsresult GroupByHost(const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest,
PRBool aIsDomain);
nsresult FilterResultSet(const nsCOMArray<nsNavHistoryResultNode>& aSet,
nsCOMArray<nsNavHistoryResultNode>* aFiltered,
const nsString& aSearch);
// observers
nsMaybeWeakPtrArray<nsINavHistoryObserver> mObservers;
PRInt32 mBatchesInProgress;
// localization
nsCOMPtr<nsIStringBundle> mBundle;
nsCOMPtr<nsILocale> mLocale;
nsCOMPtr<nsICollation> mCollation;
nsCOMPtr<nsIDateTimeFormat> mDateFormatter;
// annotation service : MAY BE NULL!
//nsCOMPtr<mozIAnnotationService> mAnnotationService;
// recent events
typedef nsDataHashtable<nsCStringHashKey, PRInt64> RecentEventHash;
RecentEventHash mRecentTyped;
RecentEventHash mRecentBookmark;
PRBool CheckIsRecentEvent(RecentEventHash* hashTable,
const nsACString& url);
void ExpireNonrecentEvents(RecentEventHash* hashTable);
// redirect tracking. See GetRedirectFor for a description of how this works.
struct RedirectInfo {
nsCString mSourceURI;
PRTime mTimeCreated;
PRUint32 mType; // one of TRANSITION_REDIRECT_[TEMPORARY,PERMANENT]
};
typedef nsDataHashtable<nsCStringHashKey, RedirectInfo> RedirectHash;
RedirectHash mRecentRedirects;
PR_STATIC_CALLBACK(PLDHashOperator) ExpireNonrecentRedirects(
nsCStringHashKey::KeyType aKey, RedirectInfo& aData, void* aUserArg);
PRBool GetRedirectFor(const nsACString& aDestination, nsACString& aSource,
PRTime* aTime, PRUint32* aRedirectType);
// session tracking
PRInt64 mLastSessionID;
PRInt64 GetNewSessionID() { mLastSessionID ++; return mLastSessionID; }
//
// AutoComplete stuff
//
struct AutoCompletePrefix
{
AutoCompletePrefix(const nsAString& aPrefix, PRBool aSecondLevel) :
prefix(aPrefix), secondLevel(aSecondLevel) {}
// The prefix, for example, "http://" or "https://www."
nsString prefix;
// Set when this prefix contains a spec AND a host. For example,
// "http://www." is a second level prefix, but "http://" is not. This
// flag is used to exclude matches. For example, if I type "http://w"
// I probably want it to autocomplete to sites beginning with w and
// NOT every "www" site I've ever visited.
PRBool secondLevel;
};
nsTArray<AutoCompletePrefix> mAutoCompletePrefixes;
nsCOMPtr<mozIStorageStatement> mDBAutoCompleteQuery;
nsresult InitAutoComplete();
nsresult CreateAutoCompleteQuery();
PRInt32 mAutoCompleteMaxCount;
PRInt32 mExpireDays;
PRBool mAutoCompleteOnlyTyped;
// Used to describe what prefixes shouldn't be cut from
// history urls when doing an autocomplete url comparison.
struct AutoCompleteExclude {
// these are indices into mIgnoreSchemes and mIgnoreHostnames, or -1
PRInt32 schemePrefix;
PRInt32 hostnamePrefix;
// this is the offset of the character immediately after the prefix
PRInt32 postPrefixOffset;
};
nsresult AutoCompleteTypedSearch(nsIAutoCompleteSimpleResult* result);
nsresult AutoCompleteFullHistorySearch(const nsAString& aSearchString,
nsIAutoCompleteSimpleResult* result);
nsresult AutoCompleteQueryOnePrefix(const nsString& aSearchString,
const nsTArray<PRInt32>& aExcludePrefixes,
PRInt32 aPriorityDelta,
nsTArray<AutoCompleteIntermediateResult>* aResult);
PRInt32 AutoCompleteGetPrefixLength(const nsString& aSpec);
// in nsNavHistoryQuery.cpp
nsresult TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
nsCOMArray<nsNavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions* aOptions);
// creates supplemental indexes that we'd like to not bother with
// updating during import.
nsresult CreateLookupIndexes();
};
/**
* Shared between the places components, this function binds the given URI as
* UTF8 to the given parameter for the statement.
*/
nsresult BindStatementURI(mozIStorageStatement* statement, PRInt32 index,
nsIURI* aURI);
#define PLACES_URI_PREFIX "place:"
/* Returns true if the given URI represents a history query. */
inline PRBool IsQueryURI(const nsCString &uri)
{
return StringBeginsWith(uri, NS_LITERAL_CSTRING(PLACES_URI_PREFIX));
}
/* Extracts the query string from a query URI. */
inline const nsDependentCSubstring QueryURIToQuery(const nsCString &uri)
{
NS_ASSERTION(IsQueryURI(uri), "should only be called for query URIs");
return Substring(uri, NS_LITERAL_CSTRING(PLACES_URI_PREFIX).Length());
}
#endif // nsNavHistory_h_

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

@ -1,711 +0,0 @@
/* -*- 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 Places code.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com>
* Joe Hewitt <hewitt@netscape.com>
* Blake Ross <blaker@netscape.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 ***** */
/**
* Autocomplte algorithm:
*
* Scoring
* -------
* Generally ordering is by visit count. We given boosts to items that have
* been bookmarked or typed into the address bar (as opposed to clicked links).
* The penalties below for schemes and prefix matches also apply. We also
* prefer paths (URLs ending in '/') and try to have shorter ones generally
* appear first. The results are then presented in descending numeric order
* using this score.
*
* Database queries
* ----------------
* It is tempting to do a select for "url LIKE user_input" but this is a very
* slow query since it is brute-force over all URLs in histroy. We can,
* however, do very efficient queries using < and > for strings. These
* operators use the index over the URL column.
*
* Therefore, we try to prepend any prefixes that should be considered and
* query for them individually. Therefore, we execute several very efficient
* queries, score the results, and sort it.
*
* To limit the amount of searching we do, we ask the database to order the
* results based on visit count for us and give us on the top N results.
* These results will be in approximate order of score. As long as each query
* has more results than the user is likely to see, they will not notice the
* effects of this.
*
* First see if any specs match that from the beginning
* ----------------------------------------------------
* - If it matches the beginning of a known prefix prefix, exclude that prefix
* when querying. We would therefore exclude "http://" and "https://" if you type
* "ht". But match any other schemes that begin with "ht" (probably none).
*
* - Penalize all results. Most people don't type the scheme and don't want
* matches like this. This will make "file://" links go below
* "http://www.fido.com/". If one is typing the scheme "file:" for example, by
* the time you type the colon it won't match anything else (like "http://file:")
* and the penalty won't have any effect on the ordering (it will be applied to
* all results).
*
* Try different known prefixes
* ----------------------------
* - Prepend each prefix, running a query. If the concatenated string is itself a
* prefix of another known prefix (ie input is "w" and we prepend "http://", it
* will be a prefix of "http://www."), select out that known prefix. In this
* case we'll query for everything starting with "http://w" except things
* starting with "http://www."
*
* - For each selected out prefix above, run a query but apply prefix match
* penalty to the results. This way you'll still get "http://www." results
* if you type "w", but they will generally be lower than "http://wookie.net/"
* For your favorite few sites with many visits, you might still get matches
* for "www" first, which is probably what you want for your favorite sites.
*/
#include "nsNavHistory.h"
#include "nsNetUtil.h"
#include "mozIStorageService.h"
#include "mozIStorageConnection.h"
#include "mozIStorageValueArray.h"
#include "mozIStorageStatement.h"
#include "mozIStorageFunction.h"
#include "mozStorageCID.h"
#include "mozStorageHelper.h"
#define NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID \
"@mozilla.org/autocomplete/simple-result;1"
// Size of visit count boost to give to URLs which are sites or paths
#define AUTOCOMPLETE_NONPAGE_VISIT_COUNT_BOOST 5
// Boost to give to URLs which have been typed
#define AUTOCOMPLETE_TYPED_BOOST 5
// Boost to give to URLs which are bookmarked
#define AUTOCOMPLETE_BOOKMARKED_BOOST 5
// Penalty to add to sites that match a prefix. For example, if I type "w"
// we will complte on "http://www.w..." like normal. We we will also complete
// on "http://w" which will match almost every site, but will have this penalty
// applied so they will come later. We want a pretty big penalty so that you'll
// only get "www" beating domain names that start with w for your very favorite
// sites.
#define AUTOCOMPLETE_MATCHES_PREFIX_PENALTY (-50)
// Penalty applied to matches that don't have prefixes applied. See
// discussion above.
#define AUTOCOMPLETE_MATCHES_SCHEME_PENALTY (-20)
// Number of results we will consider for each prefix. Each prefix lookup is
// done separately. Typically, we will only match one prefix, so this should be
// a sufficient number to give "enough" autocomplete matches per prefix. The
// total number of results that could ever be returned is this times the number
// of prefixes. This should be as small as is reasonable to make it faster.
#define AUTOCOMPLETE_MAX_PER_PREFIX 50
// This is the maximum results we'll return for a "typed" search (usually
// happens in response to clicking the down arrow next to the URL).
#define AUTOCOMPLETE_MAX_PER_TYPED 100
// This is the maximum number of visits that an item can have for us to
// try to remove the path and put a virtual item with just the hostname as the
// first entry. The virtual item helps the case where you've visited a site deep
// down and want to visit the main site. This limit makes sure we don't take
// the first autocomplete spot for a page you are more likely to go to.
#define AUTOCOMPLETE_MAX_TRUNCATION_VISIT 6
PRInt32 ComputeAutoCompletePriority(const nsAString& aUrl, PRInt32 aVisitCount,
PRBool aWasTyped, PRBool aIsBookmarked);
nsresult NormalizeAutocompleteInput(const nsAString& aInput,
nsString& aOutput);
// nsIAutoCompleteSearch *******************************************************
// AutoCompleteIntermediateResult/Set
//
// This class holds intermediate autocomplete results so that they can be
// sorted. This list is then handed off to a result using FillResult. The
// major reason for this is so that we can use nsArray's sorting functions,
// not use COM, yet have well-defined lifetimes for the objects. This uses
// a void array, but makes sure to delete the objects on desctruction.
struct AutoCompleteIntermediateResult
{
AutoCompleteIntermediateResult(const nsString& aUrl, const nsString& aTitle,
PRInt32 aVisitCount, PRInt32 aPriority) :
url(aUrl), title(aTitle), visitCount(aVisitCount), priority(aPriority) {}
nsString url;
nsString title;
PRInt32 visitCount;
PRInt32 priority;
};
// AutoCompleteResultComparator
class AutoCompleteResultComparator
{
public:
AutoCompleteResultComparator(nsNavHistory* history) : mHistory(history) {}
PRBool Equals(const AutoCompleteIntermediateResult& a,
const AutoCompleteIntermediateResult& b) const {
// Don't need an equals, this call will be optimized out when it
// is used by nsQuickSortComparator above
return PR_FALSE;
}
PRBool LessThan(const AutoCompleteIntermediateResult& match1,
const AutoCompleteIntermediateResult& match2) const {
// we actually compare GREATER than here, since we want the array to be in
// most relevant (highest priority value) first
// In most cases the priorities will be different and we just use them
if (match1.priority != match2.priority)
{
return match1.priority > match2.priority;
}
else
{
// secondary sorting gives priority to site names and paths (ending in a /)
PRBool isPath1 = PR_FALSE, isPath2 = PR_FALSE;
if (!match1.url.IsEmpty())
isPath1 = (match1.url.Last() == PRUnichar('/'));
if (!match2.url.IsEmpty())
isPath2 = (match2.url.Last() == PRUnichar('/'));
if (isPath1 && !isPath2) return PR_FALSE; // match1->url is a website/path, match2->url isn't
if (!isPath1 && isPath2) return PR_TRUE; // match1->url isn't a website/path, match2->url is
// find the prefixes so we can sort by the stuff after the prefixes
PRInt32 prefix1 = mHistory->AutoCompleteGetPrefixLength(match1.url);
PRInt32 prefix2 = mHistory->AutoCompleteGetPrefixLength(match2.url);
// Compare non-prefixed urls using the current locale string compare. This will sort
// things alphabetically (ignoring common prefixes). For example, "http://www.abc.com/"
// will come before "ftp://ftp.xyz.com"
PRInt32 ret = 0;
mHistory->mCollation->CompareString(
nsICollation::kCollationCaseInSensitive,
Substring(match1.url, prefix1), Substring(match2.url, prefix2),
&ret);
if (ret != 0)
return ret > 0;
// sort http://xyz.com before http://www.xyz.com
return prefix1 > prefix2;
}
return PR_FALSE;
}
protected:
nsNavHistory* mHistory;
};
// nsNavHistory::InitAutoComplete
nsresult
nsNavHistory::InitAutoComplete()
{
nsresult rv = CreateAutoCompleteQuery();
NS_ENSURE_SUCCESS(rv, rv);
AutoCompletePrefix* ok;
// These are the prefixes we check for implicitly. Prefixes with a
// host portion (like "www.") get their second level flag set.
ok = mAutoCompletePrefixes.AppendElement(AutoCompletePrefix(NS_LITERAL_STRING("http://"), PR_FALSE));
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
ok = mAutoCompletePrefixes.AppendElement(AutoCompletePrefix(NS_LITERAL_STRING("http://www."), PR_TRUE));
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
ok = mAutoCompletePrefixes.AppendElement(AutoCompletePrefix(NS_LITERAL_STRING("ftp://"), PR_FALSE));
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
ok = mAutoCompletePrefixes.AppendElement(AutoCompletePrefix(NS_LITERAL_STRING("ftp://ftp."), PR_TRUE));
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
ok = mAutoCompletePrefixes.AppendElement(AutoCompletePrefix(NS_LITERAL_STRING("https://"), PR_FALSE));
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
ok = mAutoCompletePrefixes.AppendElement(AutoCompletePrefix(NS_LITERAL_STRING("https://www."), PR_TRUE));
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
// nsNavHistory::CreateAutoCompleteQuery
//
// The auto complete query we use depends on options, so we have it in
// a separate function so it can be re-created when the option changes.
nsresult
nsNavHistory::CreateAutoCompleteQuery()
{
nsCString sql;
if (mAutoCompleteOnlyTyped) {
sql = NS_LITERAL_CSTRING(
"SELECT url, title, visit_count, typed, "
"(SELECT item_child FROM moz_bookmarks WHERE item_child = id) "
"FROM moz_history "
"WHERE url >= ?1 AND url < ?2 "
"AND typed = 1 "
"ORDER BY visit_count DESC "
"LIMIT ");
} else {
sql = NS_LITERAL_CSTRING(
"SELECT url, title, visit_count, typed, "
"(SELECT item_child FROM moz_bookmarks WHERE item_child = id) "
"FROM moz_history "
"WHERE url >= ?1 AND url < ?2 "
"AND (hidden <> 1 OR typed = 1) "
"ORDER BY visit_count DESC "
"LIMIT ");
}
sql.AppendInt(AUTOCOMPLETE_MAX_PER_PREFIX);
nsresult rv = mDBConn->CreateStatement(sql,
getter_AddRefs(mDBAutoCompleteQuery));
return rv;
}
// nsNavHistory::StartSearch
//
NS_IMETHODIMP
nsNavHistory::StartSearch(const nsAString & aSearchString,
const nsAString & aSearchParam,
nsIAutoCompleteResult *aPreviousResult,
nsIAutoCompleteObserver *aListener)
{
nsresult rv;
NS_ENSURE_ARG_POINTER(aListener);
nsCOMPtr<nsIAutoCompleteSimpleResult> result =
do_CreateInstance(NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
result->SetSearchString(aSearchString);
// Performance: We can improve performance for refinements of a previous
// result by filtering the old result with the new string. However, since
// our results are not a full match of history, we'll need to requery if
// any of the subresults returned the maximum number of elements (i.e. we
// didn't load all of them).
//
// Timing measurements show that the performance of this is actually very
// good for specific queries. Thus, the times where we can do the
// optimization (when there are few results) are exactly the times when
// we don't have to. As a result, we keep it this much simpler way.
if (aSearchString.IsEmpty()) {
rv = AutoCompleteTypedSearch(result);
} else {
rv = AutoCompleteFullHistorySearch(aSearchString, result);
}
NS_ENSURE_SUCCESS(rv, rv);
// Determine the result of the search
PRUint32 count;
result->GetMatchCount(&count);
if (count > 0) {
result->SetSearchResult(nsIAutoCompleteResult::RESULT_SUCCESS);
result->SetDefaultIndex(0);
} else {
result->SetSearchResult(nsIAutoCompleteResult::RESULT_NOMATCH);
result->SetDefaultIndex(-1);
}
aListener->OnSearchResult(this, result);
return NS_OK;
}
// nsNavHistory::StopSearch
NS_IMETHODIMP
nsNavHistory::StopSearch()
{
return NS_OK;
}
// nsNavHistory::AutoCompleteTypedSearch
//
// Called when there is no search string. This happens when you press
// down arrow from the URL bar: the most recent things you typed are listed.
//
// Ordering here is simpler because there are no boosts for typing, and there
// is no URL information to use. The ordering just comes out of the DB by
// visit count (primary) and time since last visited (secondary).
nsresult nsNavHistory::AutoCompleteTypedSearch(
nsIAutoCompleteSimpleResult* result)
{
// need to get more than the required minimum number since some will be dupes
nsCOMPtr<mozIStorageStatement> dbSelectStatement;
nsCString sql = NS_LITERAL_CSTRING(
"SELECT url, title "
"FROM moz_historyvisit v JOIN moz_history h ON v.page_id = h.id "
"WHERE h.typed = 1 ORDER BY visit_date DESC LIMIT ");
sql.AppendInt(AUTOCOMPLETE_MAX_PER_TYPED * 3);
nsresult rv = mDBConn->CreateStatement(sql, getter_AddRefs(dbSelectStatement));
NS_ENSURE_SUCCESS(rv, rv);
// prevent duplicates
nsDataHashtable<nsStringHashKey, PRInt32> urls;
if (! urls.Init(500))
return NS_ERROR_OUT_OF_MEMORY;
PRInt32 dummy;
PRInt32 count = 0;
PRBool hasMore = PR_FALSE;
while (count < AUTOCOMPLETE_MAX_PER_TYPED &&
NS_SUCCEEDED(dbSelectStatement->ExecuteStep(&hasMore)) && hasMore) {
nsAutoString entryURL, entryTitle;
dbSelectStatement->GetString(0, entryURL);
dbSelectStatement->GetString(1, entryTitle);
if (! urls.Get(entryURL, &dummy)) {
// new item
rv = result->AppendMatch(entryURL, entryTitle);
NS_ENSURE_SUCCESS(rv, rv);
urls.Put(entryURL, 1);
count ++;
}
}
return NS_OK;
}
// nsNavHistory::AutoCompleteFullHistorySearch
//
// A brute-force search of the entire history. This matches the given input
// with every possible history entry, and sorts them by likelihood.
//
// This may be slow for people on slow computers with large histories.
nsresult
nsNavHistory::AutoCompleteFullHistorySearch(const nsAString& aSearchString,
nsIAutoCompleteSimpleResult* aResult)
{
nsString searchString;
nsresult rv = NormalizeAutocompleteInput(aSearchString, searchString);
if (NS_FAILED(rv))
return NS_OK; // no matches for invalid input
nsTArray<AutoCompleteIntermediateResult> matches;
// Try a query using this search string and every prefix. Keep track of
// known prefixes that the input matches for exclusion later
PRUint32 i;
const nsTArray<PRInt32> emptyArray;
nsTArray<PRInt32> firstLevelMatches;
nsTArray<PRInt32> secondLevelMatches;
for (i = 0; i < mAutoCompletePrefixes.Length(); i ++) {
if (StringBeginsWith(mAutoCompletePrefixes[i].prefix, searchString)) {
if (mAutoCompletePrefixes[i].secondLevel)
secondLevelMatches.AppendElement(i);
else
firstLevelMatches.AppendElement(i);
}
// current string to search for
nsString cur = mAutoCompletePrefixes[i].prefix + searchString;
// see if the concatenated string itself matches any prefixes
nsTArray<PRInt32> curPrefixMatches;
for (PRUint32 prefix = 0; prefix < mAutoCompletePrefixes.Length(); prefix ++) {
if (StringBeginsWith(mAutoCompletePrefixes[prefix].prefix, cur))
curPrefixMatches.AppendElement(prefix);
}
// search for the current string, excluding those matching prefixes
AutoCompleteQueryOnePrefix(cur, curPrefixMatches, 0, &matches);
// search for each of those matching prefixes, applying the prefix penalty
for (PRUint32 match = 0; match < curPrefixMatches.Length(); match ++) {
AutoCompleteQueryOnePrefix(mAutoCompletePrefixes[curPrefixMatches[match]].prefix,
emptyArray, AUTOCOMPLETE_MATCHES_PREFIX_PENALTY,
&matches);
}
}
// Now try searching with no prefix
if (firstLevelMatches.Length() > 0) {
// This will get all matches that DON'T match any prefix. For example, if
// the user types "http://w" we will match "http://westinghouse.com" but
// not "http://www.something".
AutoCompleteQueryOnePrefix(searchString,
firstLevelMatches, 0, &matches);
} else if (secondLevelMatches.Length() > 0) {
// if there are no first level matches (i.e. "http://") then we fall back on
// second level matches. Here, we assume that a first level match implies
// a second level match as well, so we only have to check when there are no
// first level matches.
AutoCompleteQueryOnePrefix(searchString,
secondLevelMatches, 0, &matches);
// now we try to fill in matches of the prefix. For example, if you type
// "http://w" we will still match against "http://www." but with a penalty.
// We only do this for second level prefixes.
for (PRUint32 match = 0; match < secondLevelMatches.Length(); match ++) {
AutoCompleteQueryOnePrefix(mAutoCompletePrefixes[secondLevelMatches[match]].prefix,
emptyArray, AUTOCOMPLETE_MATCHES_SCHEME_PENALTY,
&matches);
}
} else {
// Input matched no prefix, try to query for all URLs beinning with this
// exact input.
AutoCompleteQueryOnePrefix(searchString, emptyArray,
AUTOCOMPLETE_MATCHES_SCHEME_PENALTY, &matches);
}
// sort according to priorities
AutoCompleteResultComparator comparator(this);
matches.Sort(comparator);
// fill into result
nsAutoString zerothEntry;
if (matches.Length() > 0 &&
matches[0].visitCount <= AUTOCOMPLETE_MAX_TRUNCATION_VISIT) {
// Here, we try to make sure that the first match is always a host name
// we take the previous first match and extract its host name and add it
// before. If the first item has been visited a lot, don't do that because
// they probably want to go there instead
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(matches[0].url));
NS_ENSURE_SUCCESS(rv, rv);
uri->SetPath(NS_LITERAL_CSTRING("/"));
nsCAutoString spec;
uri->GetSpec(spec);
zerothEntry = NS_ConvertUTF8toUTF16(spec);
if (! zerothEntry.Equals(matches[0].url))
aResult->AppendMatch(zerothEntry, EmptyString());
rv = aResult->AppendMatch(matches[0].url, matches[0].title);
NS_ENSURE_SUCCESS(rv, rv);
} else if (matches.Length() > 0) {
// otherwise, just append the first match
rv = aResult->AppendMatch(matches[0].url, matches[0].title);
NS_ENSURE_SUCCESS(rv, rv);
}
for (i = 1; i < matches.Length(); i ++) {
// only add ones that are NOT the same as the previous one. It's possible
// to get duplicates from the queries.
if (! matches[i].url.Equals(matches[i-1].url) &&
! zerothEntry.Equals(matches[i].url)) {
rv = aResult->AppendMatch(matches[i].url, matches[i].title);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
// nsNavHistory::AutoCompleteQueryOnePrefix
//
// The values in aExcludePrefixes are indices into mAutoCompletePrefixes
// of prefixes to exclude during this query. For example, if I type
// "ht" this function will be called to match everything starting with
// "ht" EXCEPT "http://" and "https://".
nsresult
nsNavHistory::AutoCompleteQueryOnePrefix(const nsString& aSearchString,
const nsTArray<PRInt32>& aExcludePrefixes,
PRInt32 aPriorityDelta,
nsTArray<AutoCompleteIntermediateResult>* aResult)
{
// All URL queries are in UTF-8. Compute the beginning (inclusive) and
// ending (exclusive) of the range of URLs to include when compared
// using strcmp (which is what sqlite does).
nsCAutoString beginQuery = NS_ConvertUTF16toUTF8(aSearchString);
if (beginQuery.IsEmpty())
return NS_OK;
nsCAutoString endQuery = beginQuery;
unsigned char maxChar[6] = { 0xfd, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf };
endQuery.Append(NS_REINTERPRET_CAST(const char*, maxChar), 6);
nsTArray<nsCString> ranges;
if (aExcludePrefixes.Length() > 0) {
// we've been requested to include holes in our range, sort these ranges
ranges.AppendElement(beginQuery);
for (PRUint32 i = 0; i < aExcludePrefixes.Length(); i ++) {
nsCAutoString thisPrefix = NS_ConvertUTF16toUTF8(
mAutoCompletePrefixes[aExcludePrefixes[i]].prefix);
ranges.AppendElement(thisPrefix);
thisPrefix.Append(NS_REINTERPRET_CAST(const char*, maxChar), 6);
ranges.AppendElement(thisPrefix);
}
ranges.AppendElement(endQuery);
ranges.Sort();
} else {
// simple range with no holes
ranges.AppendElement(beginQuery);
ranges.AppendElement(endQuery);
}
NS_ASSERTION(ranges.Length() % 2 == 0, "Ranges should be pairs!");
// The nested select expands to nonzero when the item is bookmarked.
// It might be nice to also select hidden bookmarks (unvisited) but that
// made this statement more complicated and should be an unusual case.
nsresult rv;
for (PRUint32 range = 0; range < ranges.Length() - 1; range += 2) {
mozStorageStatementScoper scoper(mDBAutoCompleteQuery);
rv = mDBAutoCompleteQuery->BindUTF8StringParameter(0, ranges[range]);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBAutoCompleteQuery->BindUTF8StringParameter(1, ranges[range + 1]);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasMore;
nsAutoString url, title;
while (NS_SUCCEEDED(mDBAutoCompleteQuery->ExecuteStep(&hasMore)) && hasMore) {
mDBAutoCompleteQuery->GetString(0, url);
mDBAutoCompleteQuery->GetString(1, title);
PRInt32 visitCount = mDBAutoCompleteQuery->AsInt32(2);
PRInt32 priority = ComputeAutoCompletePriority(url, visitCount,
mDBAutoCompleteQuery->AsInt32(3) > 0,
mDBAutoCompleteQuery->AsInt32(4) > 0) + aPriorityDelta;
aResult->AppendElement(AutoCompleteIntermediateResult(
url, title, visitCount, priority));
}
}
return NS_OK;
}
// nsNavHistory::AutoCompleteGetPrefixLength
PRInt32
nsNavHistory::AutoCompleteGetPrefixLength(const nsString& aSpec)
{
for (PRUint32 i = 0; i < mAutoCompletePrefixes.Length(); ++i) {
if (StringBeginsWith(aSpec, mAutoCompletePrefixes[i].prefix))
return mAutoCompletePrefixes[i].prefix.Length();
}
return 0; // no prefix
}
// ComputeAutoCompletePriority
//
// Favor websites and webpaths more than webpages by boosting
// their visit counts. This assumes that URLs have been normalized,
// appending a trailing '/'.
//
// We use addition to boost the visit count rather than multiplication
// since we want URLs with large visit counts to remain pretty much
// in raw visit count order - we assume the user has visited these urls
// often for a reason and there shouldn't be a problem with putting them
// high in the autocomplete list regardless of whether they are sites/
// paths or pages. However for URLs visited only a few times, sites
// & paths should be presented before pages since they are generally
// more likely to be visited again.
PRInt32
ComputeAutoCompletePriority(const nsAString& aUrl, PRInt32 aVisitCount,
PRBool aWasTyped, PRBool aIsBookmarked)
{
PRInt32 aPriority = aVisitCount;
if (!aUrl.IsEmpty()) {
// url is a site/path if it has a trailing slash
if (aUrl.Last() == PRUnichar('/'))
aPriority += AUTOCOMPLETE_NONPAGE_VISIT_COUNT_BOOST;
}
if (aWasTyped)
aPriority += AUTOCOMPLETE_TYPED_BOOST;
if (aIsBookmarked)
aPriority += AUTOCOMPLETE_BOOKMARKED_BOOST;
return aPriority;
}
// NormalizeAutocompleteInput
nsresult NormalizeAutocompleteInput(const nsAString& aInput,
nsString& aOutput)
{
nsresult rv;
if (aInput.IsEmpty()) {
aOutput.Truncate();
return NS_OK;
}
nsCAutoString input = NS_ConvertUTF16toUTF8(aInput);
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), input);
PRBool isSchemeAdded = PR_FALSE;
if (NS_FAILED(rv)) {
// it may have failed because there is no scheme, prepend one
isSchemeAdded = PR_TRUE;
input = NS_LITERAL_CSTRING("http://") + input;
rv = NS_NewURI(getter_AddRefs(uri), input);
if (NS_FAILED(rv))
return rv; // still not valid, can't autocomplete this URL
}
nsCAutoString spec;
rv = uri->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
if (spec.IsEmpty())
return NS_OK; // should never happen but we assume it's not empty below, so check
aOutput = NS_ConvertUTF8toUTF16(spec);
// trim the "http://" scheme if we added it
if (isSchemeAdded) {
NS_ASSERTION(aOutput.Length() > 7, "String impossibly short");
aOutput = Substring(aOutput, 7);
}
// it may have appended a slash, get rid of it
// example: input was "http://www.mozil" the URI spec will be
// "http://www.mozil/" which is obviously wrong to complete against.
// However, it won't always append a slash, for example, for the input
// "http://www.mozilla.org/supp"
if (input[input.Length() - 1] != '/' && aOutput[aOutput.Length() - 1] == '/')
aOutput.Truncate(aOutput.Length() - 1);
return NS_OK;
}

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

@ -1,643 +0,0 @@
//* -*- 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 Mozilla History 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):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
/**
* This class handles expiration of history for nsNavHistory. There is a 1-1
* mapping between nsNavHistory class and a nsNavHistoryExpire class, the
* code is separated for better understandability.
*/
#include "nsNavHistory.h"
#include "mozStorageHelper.h"
#include "nsNetUtil.h"
struct nsNavHistoryExpireRecord {
nsNavHistoryExpireRecord(mozIStorageStatement* statement);
PRInt64 visitID;
PRInt64 pageID;
PRTime visitDate;
nsCString uri;
PRInt64 faviconID;
PRBool hidden;
PRBool bookmarked;
PRBool erased; // set to true if/when the history entry is erased
};
// Number of things we'll expire at once. Runtime of expiration is approximately
// linear with the number of things we expire at once. This number was picked so
// we expire "several" things at once, but still run quickly. Just doing 3
// expirations at once isn't much faster than 6 due to constant overhead of
// running the query.
#define EXPIRATION_COUNT_PER_RUN 6
// The time in ms to wait after AddURI to try expiration of pages. Short is
// actually better. If expiration takes an unusually long period of time, it
// will interfere with video playback in the browser, for example. Such a blip
// is not likely to be noticable when the page has just appeared.
#define PARTIAL_EXPIRATION_TIMEOUT 3500
// The time in ms to wait after the initial expiration run for additional ones
#define SUBSEQUENT_EXIPRATION_TIMEOUT 20000
// Number of expirations we'll do after the most recent page is loaded before
// stopping. We don't want to keep the computer chugging forever expiring
// annotations if the user stopped using the browser.
//
// This current value of one prevents history expiration while the page is
// being shown, because expiration may interfere with media playback.
#define MAX_SEQUENTIAL_RUNS 1
// nsNavHistoryExpire::nsNavHistoryExpire
//
// Warning: don't do anything with aHistory in the constructor, since
// this is a member of the nsNavHistory, it is still being constructed
// when this is called.
nsNavHistoryExpire::nsNavHistoryExpire(nsNavHistory* aHistory) :
mHistory(aHistory),
mSequentialRuns(0),
mTimerSet(PR_FALSE),
mAnyEmptyRuns(PR_FALSE),
mNextExpirationTime(0),
mAddCount(0),
mExpiredItems(0),
mExpireRuns(0)
{
}
// nsNavHistoryExpire::~nsNavHistoryExpire
nsNavHistoryExpire::~nsNavHistoryExpire()
{
}
// nsNavHistoryExpire::OnAddURI
//
// Called by history when a URI is added to history. This starts the timer
// for when we are going to expire.
//
// The current time is passed in by the history service as an optimization.
// The AddURI function has already computed the proper time, and getting the
// time again from the OS is nontrivial.
void
nsNavHistoryExpire::OnAddURI(PRTime aNow)
{
mAddCount ++;
mSequentialRuns = 0;
if (mTimer && mTimerSet) {
mTimer->Cancel();
mTimerSet = PR_FALSE;
}
if (mNextExpirationTime != 0 && aNow < mNextExpirationTime)
return; // we know there's nothing to expire yet
StartTimer(PARTIAL_EXPIRATION_TIMEOUT);
}
// nsNavHistoryExpire::OnQuit
//
// Here we check for some edge cases and fix them
void
nsNavHistoryExpire::OnQuit()
{
mozIStorageConnection* connection = mHistory->GetStorageConnection();
if (! connection) {
NS_NOTREACHED("No connection");
return;
}
// Need to cancel any pending timers so we don't try to expire during shutdown
if (mTimer)
mTimer->Cancel();
// Handle degenerate runs:
ExpireForDegenerateRuns();
// vacuum up dangling items
ExpireHistoryParanoid(connection);
ExpireFaviconsParanoid(connection);
ExpireAnnotationsParanoid(connection);
}
// nsNavHistoryExpire::ClearHistory
//
// Performance: ExpireItems sends notifications. We may want to disable this
// for clear history cases. However, my initial tests show that the
// notifications are not a significant part of clear history time.
nsresult
nsNavHistoryExpire::ClearHistory()
{
PRBool keepGoing;
mozIStorageConnection* connection = mHistory->GetStorageConnection();
NS_ENSURE_TRUE(connection, NS_ERROR_OUT_OF_MEMORY);
ExpireItems(0, &keepGoing);
ExpireHistoryParanoid(connection);
ExpireFaviconsParanoid(connection);
ExpireAnnotationsParanoid(connection);
ENUMERATE_WEAKARRAY(mHistory->mObservers, nsINavHistoryObserver,
OnClearHistory())
return NS_OK;
}
// nsNavHistoryExpire::OnExpirationChanged
//
// Called when the expiration length in days has changed. We clear any
// next expiration time, meaning that we'll try to expire stuff next time,
// and recompute the value if there's still nothing to expire.
void
nsNavHistoryExpire::OnExpirationChanged()
{
mNextExpirationTime = 0;
}
// nsNavHistoryExpire::DoPartialExpiration
nsresult
nsNavHistoryExpire::DoPartialExpiration()
{
mSequentialRuns ++;
PRBool keepGoing;
ExpireItems(EXPIRATION_COUNT_PER_RUN, &keepGoing);
if (keepGoing && mSequentialRuns < MAX_SEQUENTIAL_RUNS)
StartTimer(SUBSEQUENT_EXIPRATION_TIMEOUT);
return NS_OK;
}
// nsNavHistoryExpire::ExpireItems
//
// Here, we try to expire aNumToExpire items and their associated data,
// If we expired things and then stopped because we hit this limit,
// aKeepGoing will be set indicating we should keep expiring. If we ran
// out of things to expire, it will be unset indicating we should wait.
//
// As a special case, aNumToExpire can be 0 and we'll expire everything
// in history.
nsresult
nsNavHistoryExpire::ExpireItems(PRUint32 aNumToExpire, PRBool* aKeepGoing)
{
// mark how many times we've been able to run
mExpireRuns ++;
mozIStorageConnection* connection = mHistory->GetStorageConnection();
NS_ENSURE_TRUE(connection, NS_ERROR_OUT_OF_MEMORY);
// This transaction is important for performance. It makes the DB flush
// everything to disk in one larger operation rather than many small ones.
// Note that this transaction always commits.
mozStorageTransaction transaction(connection, PR_TRUE);
*aKeepGoing = PR_TRUE;
PRInt64 expireTime;
if (aNumToExpire == 0) {
// special case: erase all history
expireTime = 0;
} else {
expireTime = PR_Now() - GetExpirationTimeAgo();
}
// find some visits to expire
nsTArray<nsNavHistoryExpireRecord> expiredVisits;
nsresult rv = FindVisits(expireTime, aNumToExpire, connection,
expiredVisits);
NS_ENSURE_SUCCESS(rv, rv);
// if we didn't find the as many things to expire as we could have, then
// we should note the next time we need to expire.
if (expiredVisits.Length() < aNumToExpire) {
*aKeepGoing = PR_FALSE;
ComputeNextExpirationTime(connection);
if (expiredVisits.Length() == 0) {
// Nothing to expire. Set the flag so we know we don't have to do any
// work on shutdown.
mAnyEmptyRuns = PR_TRUE;
return NS_OK;
}
}
mExpiredItems += expiredVisits.Length();
rv = EraseVisits(connection, expiredVisits);
NS_ENSURE_SUCCESS(rv, rv);
rv = EraseHistory(connection, expiredVisits);
NS_ENSURE_SUCCESS(rv, rv);
// send observer messages
nsCOMPtr<nsIURI> uri;
for (PRUint32 i = 0; i < expiredVisits.Length(); i ++) {
rv = NS_NewURI(getter_AddRefs(uri), expiredVisits[i].uri);
if (NS_FAILED(rv)) continue;
// FIXME bug 325241 provide a way to observe hidden elements
if (expiredVisits[i].hidden) continue;
ENUMERATE_WEAKARRAY(mHistory->mObservers, nsINavHistoryObserver,
OnPageExpired(uri, expiredVisits[i].visitDate,
expiredVisits[i].erased));
}
// don't worry about errors here, it doesn't affect out ability to continue
EraseFavicons(connection, expiredVisits);
EraseAnnotations(connection, expiredVisits);
return NS_OK;
}
// nsNavHistoryExpireRecord::nsNavHistoryExpireRecord
//
// Statement should be the one created in FindVisits. The parameters must
// agree.
nsNavHistoryExpireRecord::nsNavHistoryExpireRecord(
mozIStorageStatement* statement)
{
visitID = statement->AsInt64(0);
pageID = statement->AsInt64(1);
visitDate = statement->AsInt64(2);
statement->GetUTF8String(3, uri);
faviconID = statement->AsInt64(4);
hidden = (statement->AsInt32(5) > 0);
bookmarked = (statement->AsInt32(6) > 0);
erased = PR_FALSE;
}
// nsNavHistoryExpire::FindVisits
//
// aExpireThreshold is the time at which we will delete visits before.
// If it is zero, we will not use a threshold and will match everything.
//
// aNumToExpire is the maximum number of visits to find. If it is 0, then
// we will get all matching visits.
nsresult
nsNavHistoryExpire::FindVisits(PRTime aExpireThreshold, PRUint32 aNumToExpire,
mozIStorageConnection* aConnection,
nsTArray<nsNavHistoryExpireRecord>& aRecords)
{
nsresult rv;
// get info for expiring visits, special case no threshold so there is no
// SQL parameter
nsCOMPtr<mozIStorageStatement> selectStatement;
nsCString sql;
sql.AssignLiteral("SELECT "
"v.visit_id, v.page_id, v.visit_date, h.url, h.favicon, h.hidden, b.item_child "
"FROM moz_historyvisit v LEFT JOIN moz_history h ON v.page_id = h.id "
"LEFT OUTER JOIN moz_bookmarks b on v.page_id = b.item_child");
if (aExpireThreshold != 0)
sql.AppendLiteral(" WHERE visit_date < ?1");
rv = aConnection->CreateStatement(sql, getter_AddRefs(selectStatement));
NS_ENSURE_SUCCESS(rv, rv);
if (aExpireThreshold != 0) {
rv = selectStatement->BindInt64Parameter(0, aExpireThreshold);
NS_ENSURE_SUCCESS(rv, rv);
}
PRBool hasMore = PR_FALSE;
while (NS_SUCCEEDED(selectStatement->ExecuteStep(&hasMore)) && hasMore &&
(aNumToExpire == 0 || aRecords.Length() < aNumToExpire)) {
nsNavHistoryExpireRecord record(selectStatement);
aRecords.AppendElement(record);
}
return NS_OK;
}
// nsNavHistoryExpire::EraseVisits
nsresult
nsNavHistoryExpire::EraseVisits(mozIStorageConnection* aConnection,
const nsTArray<nsNavHistoryExpireRecord>& aRecords)
{
nsCOMPtr<mozIStorageStatement> deleteStatement;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"DELETE FROM moz_historyvisit WHERE visit_id = ?1"),
getter_AddRefs(deleteStatement));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 i;
for (i = 0; i < aRecords.Length(); i ++) {
deleteStatement->BindInt64Parameter(0, aRecords[i].visitID);
rv = deleteStatement->Execute();
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
// nsNavHistoryExpire::EraseHistory
//
// This erases records in moz_history when there are no more visits.
// We need to be careful not to delete bookmarks and place:URIs.
//
// This will modify the input by setting the erased flag on each of the
// array elements according to whether the history item was erased or not.
nsresult
nsNavHistoryExpire::EraseHistory(mozIStorageConnection* aConnection,
nsTArray<nsNavHistoryExpireRecord>& aRecords)
{
nsCOMPtr<mozIStorageStatement> deleteStatement;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"DELETE FROM moz_history WHERE id = ?1"),
getter_AddRefs(deleteStatement));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageStatement> selectStatement;
rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT page_id FROM moz_historyvisit WHERE page_id = ?1"),
getter_AddRefs(selectStatement));
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < aRecords.Length(); i ++) {
if (aRecords[i].bookmarked)
continue; // don't delete bookmarked entries
if (StringBeginsWith(aRecords[i].uri, NS_LITERAL_CSTRING("place:")))
continue; // don't delete "place" URIs
// check that there are no visits
rv = selectStatement->BindInt64Parameter(0, aRecords[i].pageID);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasVisit = PR_FALSE;
rv = selectStatement->ExecuteStep(&hasVisit);
selectStatement->Reset();
if (hasVisit) continue;
aRecords[i].erased = PR_TRUE;
rv = deleteStatement->BindInt64Parameter(0, aRecords[i].pageID);
rv = deleteStatement->Execute();
}
return NS_OK;
}
// nsNavHistoryExpire::EraseFavicons
nsresult
nsNavHistoryExpire::EraseFavicons(mozIStorageConnection* aConnection,
const nsTArray<nsNavHistoryExpireRecord>& aRecords)
{
// see if this favicon still has an entry
nsCOMPtr<mozIStorageStatement> selectStatement;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT id FROM moz_history where favicon = ?1"),
getter_AddRefs(selectStatement));
NS_ENSURE_SUCCESS(rv, rv);
// delete a favicon
nsCOMPtr<mozIStorageStatement> deleteStatement;
rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"DELETE FROM moz_favicon WHERE id = ?1"),
getter_AddRefs(deleteStatement));
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < aRecords.Length(); i ++) {
if (! aRecords[i].erased)
continue; // main entry not expired
if (aRecords[i].faviconID == 0)
continue; // no favicon
selectStatement->BindInt64Parameter(0, aRecords[i].faviconID);
// see if there are any history entries and skip if so
PRBool hasEntry;
if (NS_SUCCEEDED(selectStatement->ExecuteStep(&hasEntry)) && hasEntry) {
selectStatement->Reset();
continue; // favicon still referenced
}
selectStatement->Reset();
// delete the favicon, ignoring errors. We could have the same favicon
// referenced twice in our list, and we'd try to delete it twice.
deleteStatement->BindInt64Parameter(0, aRecords[i].faviconID);
deleteStatement->Execute();
}
return NS_OK;
}
// nsNavHistoryExpire::EraseAnnotations
nsresult
nsNavHistoryExpire::EraseAnnotations(mozIStorageConnection* aConnection,
const nsTArray<nsNavHistoryExpireRecord>& aRecords)
{
// FIXME bug 319455 expire annotations
return NS_OK;
}
// nsNavHistoryExpire::ExpireHistoryParanoid
//
// Deletes any dangling history entries that aren't associated with any
// visits or bookmarks. Also, special case "place:" URIs.
nsresult
nsNavHistoryExpire::ExpireHistoryParanoid(mozIStorageConnection* aConnection)
{
// delete history entries with no visits that are not bookmarked
// also never delete any "place:" URIs (see function header comment)
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DELETE FROM moz_history WHERE id IN (SELECT id FROM moz_history h "
"LEFT OUTER JOIN moz_historyvisit v ON h.id = v.page_id "
"LEFT OUTER JOIN moz_bookmarks b ON h.id = b.item_child "
"WHERE v.visit_id IS NULL "
"AND b.item_child IS NULL "
"AND SUBSTR(url,0,6) <> 'place:')"));
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// nsNavHistoryExpire::ExpireFaviconsParanoid
//
// Deletes any dangling favicons that aren't associated with any pages.
nsresult
nsNavHistoryExpire::ExpireFaviconsParanoid(mozIStorageConnection* aConnection)
{
return aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DELETE FROM moz_favicon WHERE id IN "
"(SELECT f.id FROM moz_favicon f "
"LEFT OUTER JOIN moz_history h ON f.id = h.favicon "
"WHERE h.favicon IS NULL)"));
}
// nsNavHistoryExpire::ExpireAnnotationsParanoid
nsresult
nsNavHistoryExpire::ExpireAnnotationsParanoid(mozIStorageConnection* aConnection)
{
// FIXME bug 319455 expire annotations
// Also remember to expire unused names in moz_anno_name
return NS_OK;
}
// nsNavHistoryExpire::ExpireForDegenerateRuns
//
// This checks for potentiall degenerate runs. For example, a tinderbox
// loads many web pages quickly and we'll never have a chance to expire.
// Particularly crazy users might also do this. If we detect this, then we
// want to force some expiration so history doesn't keep increasing.
//
// Returns true if we did anything.
PRBool
nsNavHistoryExpire::ExpireForDegenerateRuns()
{
// If there were any times that we didn't have anything to expire, this is
// not a degenerate run.
if (mAnyEmptyRuns)
return PR_FALSE;
// If very few URIs were added this run, or we expired more items than we
// added, don't worry about it
if (mAddCount < 10 || mAddCount < mExpiredItems)
return PR_FALSE;
// This run looks suspicious, try to expire up to the number of items
// we may have missed this session.
PRBool keepGoing;
ExpireItems(mAddCount - mExpiredItems, &keepGoing);
return PR_TRUE;
}
// nsNavHistoryExpire::ComputeNextExpirationTime
//
// This computes mNextExpirationTime. See that var in the header file.
// It is passed the number of microseconds that things expire in.
void
nsNavHistoryExpire::ComputeNextExpirationTime(
mozIStorageConnection* aConnection)
{
mNextExpirationTime = 0;
nsCOMPtr<mozIStorageStatement> statement;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT MIN(visit_date) FROM moz_historyvisit"),
getter_AddRefs(statement));
NS_ASSERTION(NS_SUCCEEDED(rv), "Could not create statement");
if (NS_FAILED(rv)) return;
PRBool hasMore;
rv = statement->ExecuteStep(&hasMore);
if (NS_FAILED(rv) || ! hasMore)
return; // no items, we'll leave mNextExpirationTime = 0 and try to expire
// again next time
PRTime minTime = statement->AsInt64(0);
mNextExpirationTime = minTime + GetExpirationTimeAgo();
}
// nsNavHistoryExpire::StartTimer
nsresult
nsNavHistoryExpire::StartTimer(PRUint32 aMilleseconds)
{
if (! mTimer)
mTimer = do_CreateInstance("@mozilla.org/timer;1");
NS_ENSURE_STATE(mTimer); // returns on error
nsresult rv = mTimer->InitWithFuncCallback(TimerCallback, this,
aMilleseconds,
nsITimer::TYPE_ONE_SHOT);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// nsNavHistoryExpire::TimerCallback
void // static
nsNavHistoryExpire::TimerCallback(nsITimer* aTimer, void* aClosure)
{
nsNavHistoryExpire* that = NS_STATIC_CAST(nsNavHistoryExpire*, aClosure);
that->mTimerSet = PR_FALSE;
that->DoPartialExpiration();
}
// nsNavHistoryExpire::GetExpirationTimeAgo
PRTime
nsNavHistoryExpire::GetExpirationTimeAgo()
{
PRInt64 expireDays = mHistory->mExpireDays;
// Prevent Int64 overflow for people that type in huge numbers.
// This number is 2^63 / 24 / 60 / 60 / 1000000 (reversing the math below)
const PRInt64 maxDays = 106751991;
if (expireDays > maxDays)
expireDays = maxDays;
// compute how long ago to expire from
const PRInt64 secsPerDay = 24*60*60;
const PRInt64 usecsPerSec = 1000000;
const PRInt64 usecsPerDay = secsPerDay * usecsPerSec;
return expireDays * usecsPerDay;
}

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

@ -1,114 +0,0 @@
//* -*- 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 Mozilla History 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):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
/**
* This class handles expiration of history for nsNavHistory. There is a 1-1
* mapping between nsNavHistory class and a nsNavHistoryExpire class, the
* code is separated for better understandability.
*/
class mozIStorageConnection;
class nsNavHistory;
class nsNavHistoryExpireRecord;
class nsNavHistoryExpire
{
public:
nsNavHistoryExpire(nsNavHistory* aHistory);
~nsNavHistoryExpire();
void OnAddURI(PRTime aNow);
void OnQuit();
nsresult ClearHistory();
void OnExpirationChanged();
protected:
nsNavHistory* mHistory;
// Number of partial expirations since last AddURI call.
PRUint32 mSequentialRuns;
nsCOMPtr<nsITimer> mTimer;
PRBool mTimerSet;
// Set when we try to expire something and find there is nothing to expire.
// This short-curcuits the shutdown logic by indicating that there probably
// isn't anything important we need to expire.
PRBool mAnyEmptyRuns;
// When we have found nothing to expire, we compute the time the next item
// will expire. This is that time so we won't try to expire anything until
// then. It is 0 when we don't need to wait to expire stuff.
PRTime mNextExpirationTime;
void ComputeNextExpirationTime(mozIStorageConnection* aConnection);
// global statistics
PRUint32 mAddCount;
PRUint32 mExpiredItems;
PRUint32 mExpireRuns;
nsresult DoPartialExpiration();
nsresult ExpireItems(PRUint32 aNumToExpire, PRBool* aKeepGoing);
// parts of ExpireItems
nsresult FindVisits(PRTime aExpireThreshold, PRUint32 aNumToExpire,
mozIStorageConnection* aConnection,
nsTArray<nsNavHistoryExpireRecord>& aRecords);
nsresult EraseVisits(mozIStorageConnection* aConnection,
const nsTArray<nsNavHistoryExpireRecord>& aRecords);
nsresult EraseHistory(mozIStorageConnection* aConnection,
nsTArray<nsNavHistoryExpireRecord>& aRecords);
nsresult EraseFavicons(mozIStorageConnection* aConnection,
const nsTArray<nsNavHistoryExpireRecord>& aRecords);
nsresult EraseAnnotations(mozIStorageConnection* aConnection,
const nsTArray<nsNavHistoryExpireRecord>& aRecords);
// paranoid checks
nsresult ExpireHistoryParanoid(mozIStorageConnection* aConnection);
nsresult ExpireFaviconsParanoid(mozIStorageConnection* aConnection);
nsresult ExpireAnnotationsParanoid(mozIStorageConnection* aConnection);
PRBool ExpireForDegenerateRuns();
nsresult StartTimer(PRUint32 aMilleseconds);
static void TimerCallback(nsITimer* aTimer, void* aClosure);
PRTime GetExpirationTimeAgo();
};

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

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

@ -1,180 +0,0 @@
/* -*- 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 Places code.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
/**
* The definitions of nsNavHistoryQuery and nsNavHistoryQueryOptions. This
* header file should only be included from nsNavHistory.h, include that if
* you want these classes.
*/
#ifndef nsNavHistoryQuery_h_
#define nsNavHistoryQuery_h_
// nsNavHistoryQuery
//
// This class encapsulates the parameters for basic history queries for
// building UI, trees, lists, etc.
#define NS_NAVHISTORYQUERY_IID \
{ 0xb10185e0, 0x86eb, 0x4612, { 0x95, 0x7c, 0x09, 0x34, 0xf2, 0xb1, 0xce, 0xd7 } }
class nsNavHistoryQuery : public nsINavHistoryQuery
{
public:
nsNavHistoryQuery();
// note: we use a copy constructor in Clone(), the default is good enough
#ifdef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(NS_NAVHISTORYQUERY_IID)
#else
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYQUERY_IID)
#endif
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYQUERY
PRTime BeginTime() { return mBeginTime; }
PRUint32 BeginTimeReference() { return mBeginTimeReference; }
PRTime EndTime() { return mEndTime; }
PRUint32 EndTimeReference() { return mEndTimeReference; }
const nsString& SearchTerms() { return mSearchTerms; }
PRBool OnlyBookmarked() { return mOnlyBookmarked; }
PRBool DomainIsHost() { return mDomainIsHost; }
const nsCString& Domain() { return mDomain; }
PRBool UriIsPrefix() { return mUriIsPrefix; }
nsIURI* Uri() { return mUri; } // NOT AddRef-ed!
PRBool AnnotationIsNot() { return mAnnotationIsNot; }
const nsCString& Annotation() { return mAnnotation; }
const nsTArray<PRInt64>& Folders() const { return mFolders; }
private:
~nsNavHistoryQuery() {}
protected:
PRTime mBeginTime;
PRUint32 mBeginTimeReference;
PRTime mEndTime;
PRUint32 mEndTimeReference;
nsString mSearchTerms;
PRBool mOnlyBookmarked;
PRBool mDomainIsHost;
nsCString mDomain; // Default is IsVoid, empty string is valid query
PRBool mUriIsPrefix;
nsCOMPtr<nsIURI> mUri;
PRBool mAnnotationIsNot;
nsCString mAnnotation;
nsTArray<PRInt64> mFolders;
};
#ifndef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryQuery, NS_NAVHISTORYQUERY_IID)
#endif
// nsNavHistoryQueryOptions
#define NS_NAVHISTORYQUERYOPTIONS_IID \
{0x95f8ba3b, 0xd681, 0x4d89, {0xab, 0xd1, 0xfd, 0xae, 0xf2, 0xa3, 0xde, 0x18}}
class nsNavHistoryQueryOptions : public nsINavHistoryQueryOptions
{
public:
nsNavHistoryQueryOptions() : mSort(0), mResultType(0),
mGroupCount(0), mGroupings(nsnull),
mExcludeItems(PR_FALSE),
mExcludeQueries(PR_FALSE),
mExcludeReadOnlyFolders(PR_FALSE),
mExpandQueries(PR_FALSE),
mForceOriginalTitle(PR_FALSE),
mIncludeHidden(PR_FALSE),
mMaxResults(0)
{ }
#ifdef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(NS_NAVHISTORYQUERYOPTIONS_IID)
#else
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYQUERYOPTIONS_IID)
#endif
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYQUERYOPTIONS
PRUint32 SortingMode() const { return mSort; }
PRUint32 ResultType() const { return mResultType; }
const PRUint32* GroupingMode(PRUint32 *count) const {
*count = mGroupCount; return mGroupings;
}
PRBool ExcludeItems() const { return mExcludeItems; }
PRBool ExcludeQueries() const { return mExcludeQueries; }
PRBool ExcludeReadOnlyFolders() const { return mExcludeReadOnlyFolders; }
PRBool ExpandQueries() const { return mExpandQueries; }
PRBool ForceOriginalTitle() const { return mForceOriginalTitle; }
PRBool IncludeHidden() const { return mIncludeHidden; }
PRUint32 MaxResults() const { return mMaxResults; }
nsresult Clone(nsNavHistoryQueryOptions **aResult);
private:
nsNavHistoryQueryOptions(const nsNavHistoryQueryOptions& other) {} // no copy
~nsNavHistoryQueryOptions() { delete[] mGroupings; }
// IF YOU ADD MORE ITEMS:
// * Add a new getter for C++ above if it makes sense
// * Add to the serialization code
// * Add to the deserialization code
// * Add to the nsNavHistoryQueryOptions::Clone() function
// * Add to the nsNavHistory.cpp:IsSimpleBookmarksQuery function if applicable
PRUint32 mSort;
PRUint32 mResultType;
PRUint32 mGroupCount;
PRUint32 *mGroupings;
PRBool mExcludeItems;
PRBool mExcludeQueries;
PRBool mExcludeReadOnlyFolders;
PRBool mExpandQueries;
PRBool mForceOriginalTitle;
PRBool mIncludeHidden;
PRUint32 mMaxResults;
};
#ifndef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryQueryOptions, NS_NAVHISTORYQUERYOPTIONS_IID)
#endif
#endif // nsNavHistoryQuery_h_

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

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

@ -1,803 +0,0 @@
/* -*- 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 Places code.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* 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 ***** */
/**
* The definitions of objects that make up a history query result set. This file
* should only be included by nsNavHistory.h, include that if you want these
* classes.
*/
#ifndef nsNavHistoryResult_h_
#define nsNavHistoryResult_h_
#include "nsTArray.h"
#include "nsInterfaceHashtable.h"
#include "nsDataHashtable.h"
class nsNavHistory;
class nsIDateTimeFormat;
class nsIWritablePropertyBag;
class nsNavHistoryQuery;
class nsNavHistoryQueryOptions;
class nsNavHistoryContainerResultNode;
class nsNavHistoryFolderResultNode;
class nsNavHistoryQueryResultNode;
class nsNavHistoryVisitResultNode;
/**
* hashkey wrapper using PRInt64 KeyType
*
* @see nsTHashtable::EntryType for specification
*
* This just truncates the 64-bit int to a 32-bit one for using a hash number.
* It is used for bookmark folder IDs, which should be way less than 2^32.
*/
class nsTrimInt64HashKey : public PLDHashEntryHdr
{
public:
typedef const PRInt64& KeyType;
typedef const PRInt64* KeyTypePointer;
nsTrimInt64HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
nsTrimInt64HashKey(const nsTrimInt64HashKey& toCopy) : mValue(toCopy.mValue) { }
~nsTrimInt64HashKey() { }
KeyType GetKey() const { return mValue; }
KeyTypePointer GetKeyPointer() const { return &mValue; }
PRBool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey)
{ return NS_STATIC_CAST(PRUint32, (*aKey) & PR_UINT32_MAX); }
enum { ALLOW_MEMMOVE = PR_TRUE };
private:
const PRInt64 mValue;
};
// Declare methods for implementing nsINavBookmarkObserver
// and nsINavHistoryObserver (some methods, such as BeginUpdateBatch overlap)
#define NS_DECL_BOOKMARK_HISTORY_OBSERVER \
NS_DECL_NSINAVBOOKMARKOBSERVER \
NS_IMETHOD OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime, \
PRInt64 aSessionId, PRInt64 aReferringId, \
PRUint32 aTransitionType); \
NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle, \
const nsAString& aUserTitle, \
PRBool aIsUserTitleChanged); \
NS_IMETHOD OnDeleteURI(nsIURI *aURI); \
NS_IMETHOD OnClearHistory(); \
NS_IMETHOD OnPageChanged(nsIURI *aURI, PRUint32 aWhat, \
const nsAString &aValue); \
NS_IMETHOD OnPageExpired(nsIURI* aURI, PRTime aVisitTime, \
PRBool aWholeEntry);
// nsNavHistoryResult
//
// nsNavHistory creates this object and fills in mChildren (by getting
// it through GetTopLevel()). Then FilledAllResults() is called to finish
// object initialization.
//
// This object implements nsITreeView so you can just set it to a tree
// view and it will work. This object also observes the necessary history
// and bookmark events to keep itself up-to-date.
#define NS_NAVHISTORYRESULT_IID \
{ 0x455d1d40, 0x1b9b, 0x40e6, { 0xa6, 0x41, 0x8b, 0xb7, 0xe8, 0x82, 0x23, 0x87 } }
class nsNavHistoryResult : public nsSupportsWeakReference,
public nsINavHistoryResult,
public nsINavBookmarkObserver,
public nsINavHistoryObserver
{
public:
static nsresult NewHistoryResult(nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryContainerResultNode* aRoot,
nsNavHistoryResult** result);
// the tree viewer can go faster if it can bypass XPCOM
friend class nsNavHistoryResultTreeViewer;
#ifdef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULT_IID)
#else
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULT_IID)
#endif
nsresult PropertyBagFor(nsISupports* aObject,
nsIWritablePropertyBag** aBag);
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYRESULT
NS_DECL_BOOKMARK_HISTORY_OBSERVER
void AddEverythingObserver(nsNavHistoryQueryResultNode* aNode);
void AddBookmarkObserver(nsNavHistoryFolderResultNode* aNode, PRInt64 aFolder);
void RemoveEverythingObserver(nsNavHistoryQueryResultNode* aNode);
void RemoveBookmarkObserver(nsNavHistoryFolderResultNode* aNode, PRInt64 aFolder);
// returns the view. NOT-ADDREFED. May be NULL if there is no view
nsINavHistoryResultViewer* GetView() const
{ return mView; }
public:
// two-stage init, use NewHistoryResult to construct
nsNavHistoryResult(nsNavHistoryContainerResultNode* mRoot);
~nsNavHistoryResult();
nsresult Init(nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount,
nsNavHistoryQueryOptions *aOptions);
nsRefPtr<nsNavHistoryContainerResultNode> mRootNode;
nsCOMArray<nsINavHistoryQuery> mQueries;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
// One of nsNavHistoryQueryOptions.SORY_BY_* This is initialized to mOptions.sortingMode,
// but may be overridden if the user clicks on one of the columns.
PRUint32 mSortingMode;
nsCOMPtr<nsINavHistoryResultViewer> mView;
// property bags for all result nodes, see PropertyBagFor
nsInterfaceHashtable<nsISupportsHashKey, nsIWritablePropertyBag> mPropertyBags;
// node observers
PRBool mIsHistoryObserver;
PRBool mIsBookmarksObserver;
nsTArray<nsNavHistoryQueryResultNode*> mEverythingObservers;
typedef nsTArray<nsNavHistoryFolderResultNode*> FolderObserverList;
nsDataHashtable<nsTrimInt64HashKey, FolderObserverList* > mBookmarkObservers;
FolderObserverList* BookmarkObserversForId(PRInt64 aFolderId, PRBool aCreate);
void RecursiveExpandCollapse(nsNavHistoryContainerResultNode* aContainer,
PRBool aExpand);
void InvalidateTree();
};
// nsNavHistoryResultNode
//
// This is the base class for every node in a result set. The result itself
// is a node (nsNavHistoryResult inherits from this), as well as every
// leaf and branch on the tree.
#define NS_NAVHISTORYRESULTNODE_IID \
{0x54b61d38, 0x57c1, 0x11da, {0x95, 0xb8, 0x00, 0x13, 0x21, 0xc9, 0xf6, 0x9e}}
// These are all the simple getters, they can be used for the result node
// implementation and all subclasses. More complex are GetIcon, GetParent
// (which depends on the definition of container result node), and GetUri
// (which is overridded for lazy construction for some containers).
#define NS_IMPLEMENT_SIMPLE_RESULTNODE \
NS_IMETHOD GetTitle(nsACString& aTitle) \
{ aTitle = mTitle; return NS_OK; } \
NS_IMETHOD GetAccessCount(PRUint32* aAccessCount) \
{ *aAccessCount = mAccessCount; return NS_OK; } \
NS_IMETHOD GetTime(PRTime* aTime) \
{ *aTime = mTime; return NS_OK; } \
NS_IMETHOD GetIndentLevel(PRUint32* aIndentLevel) \
{ *aIndentLevel = mIndentLevel; return NS_OK; } \
NS_IMETHOD GetViewIndex(PRInt32* aViewIndex) \
{ *aViewIndex = mViewIndex; return NS_OK; } \
NS_IMETHOD SetViewIndex(PRInt32 aViewIndex) \
{ mViewIndex = aViewIndex; return NS_OK; } \
NS_IMETHOD GetBookmarkIndex(PRInt32* aIndex) \
{ *aIndex = mBookmarkIndex; return NS_OK; }
// This is used by the base classes instead of
// NS_FORWARD_NSINAVHISTORYRESULTNODE(nsNavHistoryResultNode) because they
// need to redefine GetType and GetUri rather than forwarding them. This
// implements all the simple getters instead of forwarding because they are so
// short and we can save a virtual function call.
//
// (GetUri is redefined only by QueryResultNode and FolderResultNode because
// the queries might not necessarily be parsed. The rest just return the node's
// buffer.)
#define NS_FORWARD_COMMON_RESULTNODE_TO_BASE \
NS_IMPLEMENT_SIMPLE_RESULTNODE \
NS_IMETHOD GetIcon(nsIURI** aIcon) \
{ return nsNavHistoryResultNode::GetIcon(aIcon); } \
NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) \
{ return nsNavHistoryResultNode::GetParent(aParent); } \
NS_IMETHOD GetPropertyBag(nsIWritablePropertyBag** aBag) \
{ return nsNavHistoryResultNode::GetPropertyBag(aBag); }
class nsNavHistoryResultNode : public nsINavHistoryResultNode
{
public:
nsNavHistoryResultNode(const nsACString& aURI, const nsACString& aTitle,
PRUint32 aAccessCount, PRTime aTime,
const nsACString& aIconURI);
virtual ~nsNavHistoryResultNode() {}
#ifdef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULTNODE_IID)
#else
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULTNODE_IID)
#endif
NS_DECL_ISUPPORTS
NS_IMPLEMENT_SIMPLE_RESULTNODE
NS_IMETHOD GetIcon(nsIURI** aIcon);
NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent);
NS_IMETHOD GetPropertyBag(nsIWritablePropertyBag** aBag);
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsNavHistoryResultNode::RESULT_TYPE_URI; return NS_OK; }
NS_IMETHOD GetUri(nsACString& aURI)
{ aURI = mURI; return NS_OK; }
virtual void OnRemoving();
public:
nsNavHistoryResult* GetResult();
nsNavHistoryQueryOptions* GetGeneratingOptions();
// These functions test the type. We don't use a virtual function since that
// would take a vtable slot for every one of (potentially very many) nodes.
// Note that GetType() already has a vtable slot because its on the iface.
PRBool IsTypeContainer(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_HOST ||
type == nsINavHistoryResultNode::RESULT_TYPE_REMOTE_CONTAINER ||
type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER);
}
PRBool IsContainer() {
PRUint32 type;
GetType(&type);
return IsTypeContainer(type);
}
static PRBool IsTypeQuerySubcontainer(PRUint32 type) {
// Tests containers that are inside queries that really belong to the query
// itself, and is used when recursively updating a query. This currently
// includes only host containers, but may be extended to support things
// like days or other criteria. It doesn't include other queries and folders.
return (type == nsINavHistoryResultNode::RESULT_TYPE_HOST);
}
PRBool IsQuerySubcontainer() {
PRUint32 type;
GetType(&type);
return IsTypeQuerySubcontainer(type);
}
static PRBool IsTypeURI(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_URI ||
type == nsINavHistoryResultNode::RESULT_TYPE_VISIT ||
type == nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT);
}
PRBool IsURI() {
PRUint32 type;
GetType(&type);
return IsTypeURI(type);
}
static PRBool IsTypeVisit(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_VISIT ||
type == nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT);
}
PRBool IsVisit() {
PRUint32 type;
GetType(&type);
return IsTypeVisit(type);
}
static PRBool IsTypeFolder(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER);
}
PRBool IsFolder() {
PRUint32 type;
GetType(&type);
return IsTypeFolder(type);
}
static PRBool IsTypeQuery(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_QUERY);
}
PRBool IsQuery() {
PRUint32 type;
GetType(&type);
return IsTypeQuery(type);
}
PRBool IsSeparator() {
PRUint32 type;
GetType(&type);
return (type == nsINavHistoryResultNode::RESULT_TYPE_SEPARATOR);
}
nsNavHistoryContainerResultNode* GetAsContainer() {
NS_ASSERTION(IsContainer(), "Not a container");
return NS_REINTERPRET_CAST(nsNavHistoryContainerResultNode*, this);
}
nsNavHistoryVisitResultNode* GetAsVisit() {
NS_ASSERTION(IsVisit(), "Not a visit");
return NS_REINTERPRET_CAST(nsNavHistoryVisitResultNode*, this);
}
nsNavHistoryFolderResultNode* GetAsFolder() {
NS_ASSERTION(IsFolder(), "Not a folder");
return NS_REINTERPRET_CAST(nsNavHistoryFolderResultNode*, this);
}
nsNavHistoryQueryResultNode* GetAsQuery() {
NS_ASSERTION(IsQuery(), "Not a query");
return NS_REINTERPRET_CAST(nsNavHistoryQueryResultNode*, this);
}
nsNavHistoryContainerResultNode* mParent;
nsCString mURI; // not necessarily valid for containers, call GetUri
nsCString mTitle;
PRUint32 mAccessCount;
PRInt64 mTime;
nsCString mFaviconURI;
PRInt32 mBookmarkIndex;
// The indent level of this node. The root node will have a value of -1. The
// root's children will have a value of 0, and so on.
PRInt32 mIndentLevel;
// Value used by the view for whatever it wants. For the built-in tree view,
// this is the index into the result's mVisibleElements list of this element.
// This is -1 if it is invalid. For items, >= 0 can be used to determine if
// the node is visible in the list or not. For folders, call IsVisible, since
// they can be the root node which is not itself visible, but its children
// are.
PRInt32 mViewIndex;
};
#ifndef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResultNode, NS_NAVHISTORYRESULTNODE_IID)
#endif
// nsNavHistoryVisitResultNode
#define NS_IMPLEMENT_VISITRESULT \
NS_IMETHOD GetUri(nsACString& aURI) { aURI = mURI; return NS_OK; } \
NS_IMETHOD GetSessionId(PRInt64* aSessionId) \
{ *aSessionId = mSessionId; return NS_OK; }
class nsNavHistoryVisitResultNode : public nsNavHistoryResultNode,
public nsINavHistoryVisitResultNode
{
public:
nsNavHistoryVisitResultNode(const nsACString& aURI, const nsACString& aTitle,
PRUint32 aAccessCount, PRTime aTime,
const nsACString& aIconURI, PRInt64 aSession);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_COMMON_RESULTNODE_TO_BASE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsNavHistoryResultNode::RESULT_TYPE_VISIT; return NS_OK; }
NS_IMPLEMENT_VISITRESULT
public:
PRInt64 mSessionId;
};
// nsNavHistoryFullVisitResultNode
#define NS_IMPLEMENT_FULLVISITRESULT \
NS_IMPLEMENT_VISITRESULT \
NS_IMETHOD GetVisitId(PRInt64 *aVisitId) \
{ *aVisitId = mVisitId; return NS_OK; } \
NS_IMETHOD GetReferringVisitId(PRInt64 *aReferringVisitId) \
{ *aReferringVisitId = mReferringVisitId; return NS_OK; } \
NS_IMETHOD GetTransitionType(PRInt32 *aTransitionType) \
{ *aTransitionType = mTransitionType; return NS_OK; }
class nsNavHistoryFullVisitResultNode : public nsNavHistoryVisitResultNode,
public nsINavHistoryFullVisitResultNode
{
public:
nsNavHistoryFullVisitResultNode(
const nsACString& aURI, const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI, PRInt64 aSession,
PRInt64 aVisitId, PRInt64 aReferringVisitId, PRInt32 aTransitionType);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_COMMON_RESULTNODE_TO_BASE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsNavHistoryResultNode::RESULT_TYPE_FULL_VISIT; return NS_OK; }
NS_IMPLEMENT_FULLVISITRESULT
public:
PRInt64 mVisitId;
PRInt64 mReferringVisitId;
PRInt32 mTransitionType;
};
// nsNavHistoryContainerResultNode
//
// This is the base class for all nodes that can have children. It is
// overridden for nodes that are dynamically populated such as queries and
// folders. It is used directly for simple containers such as host groups
// in history views.
// derived classes each provide their own implementation of has children and
// forward the rest to us using this macro
#define NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN_AND_READONLY \
NS_IMETHOD GetContainerOpen(PRBool *aContainerOpen) \
{ return nsNavHistoryContainerResultNode::GetContainerOpen(aContainerOpen); } \
NS_IMETHOD SetContainerOpen(PRBool aContainerOpen) \
{ return nsNavHistoryContainerResultNode::SetContainerOpen(aContainerOpen); } \
NS_IMETHOD GetChildCount(PRUint32 *aChildCount) \
{ return nsNavHistoryContainerResultNode::GetChildCount(aChildCount); } \
NS_IMETHOD GetChild(PRUint32 index, nsINavHistoryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::GetChild(index, _retval); } \
NS_IMETHOD GetRemoteContainerType(nsACString& aRemoteContainerType) \
{ return nsNavHistoryContainerResultNode::GetRemoteContainerType(aRemoteContainerType); }
/* Untested container API functions
NS_IMETHOD AppendURINode(const nsACString& aURI, const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString& aIconURI, nsINavHistoryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendURINode(aURI, aTitle, aAccessCount, aTime, aIconURI, _retval); } \
NS_IMETHOD AppendVisitNode(const nsACString& aURI, const nsACString & aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString & aIconURI, PRInt64 aSession, nsINavHistoryVisitResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendVisitNode(aURI, aTitle, aAccessCount, aTime, aIconURI, aSession, _retval); } \
NS_IMETHOD AppendFullVisitNode(const nsACString& aURI, const nsACString & aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString & aIconURI, PRInt64 aSession, PRInt64 aVisitId, PRInt64 aReferringVisitId, PRInt32 aTransitionType, nsINavHistoryFullVisitResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendFullVisitNode(aURI, aTitle, aAccessCount, aTime, aIconURI, aSession, aVisitId, aReferringVisitId, aTransitionType, _retval); } \
NS_IMETHOD AppendContainerNode(const nsACString & aTitle, const nsACString & aIconURI, PRUint32 aContainerType, const nsACString & aRemoteContainerType, nsINavHistoryContainerResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendContainerNode(aTitle, aIconURI, aContainerType, aRemoteContainerType, _retval); } \
NS_IMETHOD AppendQueryNode(const nsACString& aQueryURI, const nsACString & aTitle, const nsACString & aIconURI, nsINavHistoryQueryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendQueryNode(aQueryURI, aTitle, aIconURI, _retval); } \
NS_IMETHOD AppendFolderNode(PRInt64 aFolderId, nsINavHistoryFolderResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendFolderNode(aFolderId, _retval); } \
NS_IMETHOD ClearContents() \
{ return nsNavHistoryContainerResultNode::ClearContents(); }
*/
#define NS_NAVHISTORYCONTAINERRESULTNODE_IID \
{ 0x6e3bf8d3, 0x22aa, 0x4065, { 0x86, 0xbc, 0x37, 0x46, 0xb5, 0xb3, 0x2c, 0xe8 } }
class nsNavHistoryContainerResultNode : public nsNavHistoryResultNode,
public nsINavHistoryContainerResultNode
{
public:
nsNavHistoryContainerResultNode(
const nsACString& aURI, const nsACString& aTitle,
const nsACString& aIconURI, PRUint32 aContainerType,
PRBool aReadOnly, const nsACString& aRemoteContainerType);
#ifdef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(NS_NAVHISTORYCONTAINERRESULTNODE_IID)
#else
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYCONTAINERRESULTNODE_IID)
#endif
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_COMMON_RESULTNODE_TO_BASE
NS_IMETHOD GetType(PRUint32* type)
{ *type = mContainerType; return NS_OK; }
NS_IMETHOD GetUri(nsACString& aURI)
{ aURI = mURI; return NS_OK; }
NS_DECL_NSINAVHISTORYCONTAINERRESULTNODE
public:
virtual void OnRemoving();
PRBool AreChildrenVisible();
// overridded by descendents to populate
virtual nsresult OpenContainer();
nsresult CloseContainer(PRBool aUpdateView = PR_TRUE);
// this points to the result that owns this container. All containers have
// their result pointer set so we can quickly get to the result without having
// to walk the tree. Yet, this also saves us from storing a million pointers
// for every leaf node to the result.
nsNavHistoryResult* mResult;
// for example, RESULT_TYPE_HOST. Query and Folder results override GetType
// so this is not used, but is still kept in sync.
PRUint32 mContainerType;
// when there are children, this stores the open state in the tree
// this is set to the default in the constructor
PRBool mExpanded;
// Filled in by the result type generator in nsNavHistory
nsCOMArray<nsNavHistoryResultNode> mChildren;
PRBool mChildrenReadOnly;
// ID of a remote container interface that we can use GetService to get.
// This is empty to indicate there is no remote container service for this
// container (the common case).
nsCString mRemoteContainerType;
void FillStats();
void ReverseUpdateStats(PRInt32 aAccessCountChange);
// sorting
typedef nsCOMArray<nsNavHistoryResultNode>::nsCOMArrayComparatorFunc SortComparator;
virtual PRUint32 GetSortType();
static SortComparator GetSortingComparator(PRUint32 aSortType);
virtual void RecursiveSort(nsICollation* aCollation,
SortComparator aComparator);
PRUint32 FindInsertionPoint(nsNavHistoryResultNode* aNode, SortComparator aComparator);
PRBool DoesChildNeedResorting(PRUint32 aIndex, SortComparator aComparator);
PR_STATIC_CALLBACK(int) SortComparison_Bookmark(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_TitleLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_TitleGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_DateLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_DateGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_URILess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_URIGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_VisitCountLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_VisitCountGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
// finding children: THESE DO NOT ADDREF
nsNavHistoryResultNode* FindChildURI(nsIURI* aURI, PRUint32* aNodeIndex)
{
nsCAutoString spec;
if (NS_FAILED(aURI->GetSpec(spec)))
return PR_FALSE;
return FindChildURI(spec, aNodeIndex);
}
nsNavHistoryResultNode* FindChildURI(const nsACString& aSpec,
PRUint32* aNodeIndex);
nsNavHistoryFolderResultNode* FindChildFolder(PRInt64 aFolderId,
PRUint32* aNodeIndex);
nsNavHistoryContainerResultNode* FindChildContainerByName(const nsACString& aTitle,
PRUint32* aNodeIndex);
// returns the index of the given node, -1 if not found
PRInt32 FindChild(nsNavHistoryResultNode* aNode)
{ return mChildren.IndexOf(aNode); }
nsresult InsertChildAt(nsNavHistoryResultNode* aNode, PRInt32 aIndex,
PRBool aIsTemporary = PR_FALSE);
nsresult InsertSortedChild(nsNavHistoryResultNode* aNode,
PRBool aIsTemporary = PR_FALSE);
void MergeResults(nsCOMArray<nsNavHistoryResultNode>* aNodes);
nsresult ReplaceChildURIAt(PRUint32 aIndex, nsNavHistoryResultNode* aNode);
nsresult RemoveChildAt(PRInt32 aIndex, PRBool aIsTemporary = PR_FALSE);
PRBool CanRemoteContainersChange();
void RecursiveFindURIs(PRBool aOnlyOne,
nsNavHistoryContainerResultNode* aContainer,
const nsCString& aSpec,
nsCOMArray<nsNavHistoryResultNode>* aMatches);
void UpdateURIs(PRBool aRecursive, PRBool aOnlyOne, PRBool aUpdateSort,
const nsCString& aSpec,
void (*aCallback)(nsNavHistoryResultNode*,void*),
void* aClosure);
nsresult ChangeTitles(nsIURI* aURI, const nsACString& aNewTitle,
PRBool aRecursive, PRBool aOnlyOne);
};
// nsNavHistoryQueryResultNode
//
// Overridden container type for complex queries over history and/or
// bookmarks. This keeps itself in sync by listening to history and
// bookmark notifications.
class nsNavHistoryQueryResultNode : public nsNavHistoryContainerResultNode,
public nsINavHistoryQueryResultNode
{
public:
nsNavHistoryQueryResultNode(const nsACString& aQueryURI,
const nsACString& aTitle,
const nsACString& aIconURI);
nsNavHistoryQueryResultNode(const nsACString& aTitle,
const nsACString& aIconURI,
const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_COMMON_RESULTNODE_TO_BASE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsNavHistoryResultNode::RESULT_TYPE_QUERY; return NS_OK; }
NS_IMETHOD GetUri(nsACString& aURI); // does special lazy creation
NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN_AND_READONLY
NS_IMETHOD GetHasChildren(PRBool* aHasChildren);
NS_IMETHOD GetChildrenReadOnly(PRBool *aChildrenReadOnly)
{ return nsNavHistoryContainerResultNode::GetChildrenReadOnly(aChildrenReadOnly); }
NS_DECL_NSINAVHISTORYQUERYRESULTNODE
PRBool CanExpand();
virtual nsresult OpenContainer();
NS_DECL_BOOKMARK_HISTORY_OBSERVER
virtual void OnRemoving();
public:
// this constructs lazily mURI from mQueries and mOptions, call
// VerifyQueriesSerialized either this or mQueries/mOptions should be valid
nsresult VerifyQueriesSerialized();
// these may be constructed lazily from mURI, call VerifyQueriesParsed
// either this or mURI should be valid
nsCOMArray<nsNavHistoryQuery> mQueries;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
PRUint32 mLiveUpdate; // one of QUERYUPDATE_* in nsNavHistory.h
PRBool mHasSearchTerms;
nsresult VerifyQueriesParsed();
// this indicates whether the query contents are valid, they don't go away
// after the container is closed until a notification comes in
PRBool mContentsValid;
PRBool mBatchInProgress;
nsresult FillChildren();
void ClearChildren(PRBool unregister);
nsresult Refresh();
virtual PRUint32 GetSortType();
};
// nsNavHistoryFolderResultNode
//
// Overridden container type for bookmark folders. It will keep the contents
// of the folder in sync with the bookmark service.
class nsNavHistoryFolderResultNode : public nsNavHistoryContainerResultNode,
public nsINavHistoryFolderResultNode
{
public:
nsNavHistoryFolderResultNode(const nsACString& aTitle,
nsNavHistoryQueryOptions* options,
PRInt64 aFolderId,
const nsACString& aRemoteContainerType);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_COMMON_RESULTNODE_TO_BASE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER; return NS_OK; }
NS_IMETHOD GetUri(nsACString& aURI);
NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN_AND_READONLY
NS_IMETHOD GetHasChildren(PRBool* aHasChildren);
NS_IMETHOD GetChildrenReadOnly(PRBool *aChildrenReadOnly);
NS_DECL_NSINAVHISTORYQUERYRESULTNODE
NS_IMETHOD GetFolderId(PRInt64* aFolderId)
{ *aFolderId = mFolderId; return NS_OK; }
virtual nsresult OpenContainer();
// This object implements a bookmark observer interface without deriving from
// the bookmark observers. This is called from the result's actual observer
// and it knows all observers are FolderResultNodes
NS_DECL_NSINAVBOOKMARKOBSERVER
virtual void OnRemoving();
public:
// this indicates whether the folder contents are valid, they don't go away
// after the container is closed until a notification comes in
PRBool mContentsValid;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
PRInt64 mFolderId;
nsresult FillChildren();
void ClearChildren(PRBool aUnregister);
nsresult Refresh();
PRBool StartIncrementalUpdate();
void ReindexRange(PRInt32 aStartIndex, PRInt32 aEndIndex, PRInt32 aDelta);
};
// nsNavHistorySeparatorResultNode
//
// Separator result nodes do not hold any data.
class nsNavHistorySeparatorResultNode : public nsNavHistoryResultNode
{
public:
nsNavHistorySeparatorResultNode();
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsNavHistoryResultNode::RESULT_TYPE_SEPARATOR; return NS_OK; }
};
// nsNavHistoryResultTreeViewer
//
class nsNavHistoryResultTreeViewer : public nsINavHistoryResultTreeViewer,
public nsITreeView
{
public:
nsNavHistoryResultTreeViewer();
virtual ~nsNavHistoryResultTreeViewer() {}
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYRESULTVIEWER
NS_DECL_NSINAVHISTORYRESULTTREEVIEWER
NS_DECL_NSITREEVIEW
protected:
nsRefPtr<nsNavHistoryResult> mResult;
nsCOMPtr<nsITreeBoxObject> mTree; // will be null when no tree attached
nsCOMPtr<nsITreeSelection> mSelection; // may be null
PRBool mCollapseDuplicates;
// This value indicates whether we should try to compute session boundaries.
// It is cached so we don't have to compute it every time we want to get a
// row style.
PRBool mShowSessions;
void ComputeShowSessions();
enum SessionStatus { Session_None, Session_Start, Session_Continue };
SessionStatus GetRowSessionStatus(PRInt32 row);
// This list is used to map rows to nodes.
typedef nsTArray< nsCOMPtr<nsNavHistoryResultNode> > VisibleList;
VisibleList mVisibleElements;
nsresult BuildVisibleList();
nsresult BuildVisibleSection(nsNavHistoryContainerResultNode* aContainer,
VisibleList* aVisible,
PRUint32 aVisibleStartIndex);
PRUint32 CountVisibleRowsForItem(nsNavHistoryResultNode* aNode);
nsresult RefreshVisibleSection(nsNavHistoryContainerResultNode* aContainer);
PRBool CanCollapseDuplicates(nsNavHistoryResultNode* aTop,
nsNavHistoryResultNode* aNext,
PRUint32* aShowThisOne);
// external observers
nsMaybeWeakPtrArray<nsINavHistoryResultViewObserver> mObservers;
nsresult FinishInit();
// columns
enum ColumnType { Column_Unknown = -1, Column_Title, Column_URI, Column_Date,
Column_VisitCount };
ColumnType GetColumnType(nsITreeColumn* col);
ColumnType SortTypeToColumnType(PRUint32 aSortType,
PRBool* aDescending = nsnull);
nsresult FormatFriendlyTime(PRTime aTime, nsAString& aResult);
};
#endif // nsNavHistoryResult_h_