зеркало из https://github.com/mozilla/gecko-dev.git
Bug 321219 - separate places backend into toolkit, removing old files which now live in toolkit/components/places, r=beng
This commit is contained in:
Родитель
4322a32cc4
Коммит
f5cace86f0
|
@ -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_
|
Загрузка…
Ссылка в новой задаче