Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions | Variables
nsGlobalHistory.cpp File Reference
#include "nsNetUtil.h"
#include "nsGlobalHistory.h"
#include "nsCRT.h"
#include "nsIEnumerator.h"
#include "nsIServiceManager.h"
#include "nsEnumeratorUtils.h"
#include "nsRDFCID.h"
#include "nsIDirectoryService.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsXPIDLString.h"
#include "plhash.h"
#include "plstr.h"
#include "prprf.h"
#include "prtime.h"
#include "rdf.h"
#include "nsQuickSort.h"
#include "nsIIOService.h"
#include "nsILocalFile.h"
#include "nsIURL.h"
#include "nsNetCID.h"
#include "nsInt64.h"
#include "nsMorkCID.h"
#include "nsIMdbFactoryFactory.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch2.h"
#include "nsIObserverService.h"
#include "nsITextToSubURI.h"

Go to the source code of this file.


struct  matchExpiration_t
struct  matchHost_t
struct  matchSearchTerm_t
struct  matchQuery_t
class  tokenPair
class  searchTerm
struct  searchQuery


#define PREF_BRANCH_BASE   "browser."
#define PREF_BROWSER_HISTORY_EXPIRE_DAYS   "history_expire_days"
#define PREF_AUTOCOMPLETE_ONLY_TYPED   "urlbar.matchOnlyTyped"
#define PREF_AUTOCOMPLETE_ENABLED   "urlbar.autocomplete.enabled"
#define FIND_BY_AGEINDAYS_PREFIX   "find:datasource=history&match=AgeInDays&method="
#define HISTORY_URI_LENGTH_MAX   65536


static PRBool HasCell (nsIMdbEnv *aEnv, nsIMdbRow *aRow, mdb_column aCol)
static PRBool matchAgeInDaysCallback (nsIMdbRow *row, void *aClosure)
static PRBool matchExpirationCallback (nsIMdbRow *row, void *aClosure)
static PRBool matchAllCallback (nsIMdbRow *row, void *aClosure)
static PRBool matchHostCallback (nsIMdbRow *row, void *aClosure)
static PRBool matchQueryCallback (nsIMdbRow *row, void *aClosure)
 NS_IMPL_ISUPPORTS7 (nsGlobalHistory, nsIGlobalHistory2, nsIBrowserHistory, nsIObserver, nsISupportsWeakReference, nsIRDFDataSource, nsIRDFRemoteDataSource, nsIAutoCompleteSession) NS_IMETHODIMP nsGlobalHistory


static const PRInt64 MSECS_PER_DAY = LL_INIT(20, 500654080)

Class Documentation

struct matchExpiration_t

Definition at line 138 of file nsGlobalHistory.cpp.

Collaboration diagram for matchExpiration_t:
Class Members
PRTime * expirationDate
nsGlobalHistory * history
struct matchHost_t

Definition at line 143 of file nsGlobalHistory.cpp.

Collaboration diagram for matchHost_t:
Class Members
PRBool entireDomain
nsGlobalHistory * history
const char * host
struct matchSearchTerm_t

Definition at line 149 of file nsGlobalHistory.cpp.

Collaboration diagram for matchSearchTerm_t:
Class Members
nsIMdbEnv * env
nsGlobalHistory * globalHist
PRBool haveClosure
PRInt32 intValue
PRTime now
nsIMdbStore * store
searchTerm * term
struct matchQuery_t

Definition at line 159 of file nsGlobalHistory.cpp.

Collaboration diagram for matchQuery_t:
Class Members
nsGlobalHistory * history
searchQuery * query
struct searchQuery

Definition at line 207 of file nsGlobalHistory.cpp.

Class Members
mdb_column groupBy
nsVoidArray terms

Define Documentation

#define FIND_BY_AGEINDAYS_PREFIX   "find:datasource=history&match=AgeInDays&method="

Definition at line 112 of file nsGlobalHistory.cpp.

Definition at line 124 of file nsGlobalHistory.cpp.

Definition at line 120 of file nsGlobalHistory.cpp.

Definition at line 117 of file nsGlobalHistory.cpp.

Definition at line 116 of file nsGlobalHistory.cpp.

#define PREF_AUTOCOMPLETE_ENABLED   "urlbar.autocomplete.enabled"

Definition at line 110 of file nsGlobalHistory.cpp.

#define PREF_AUTOCOMPLETE_ONLY_TYPED   "urlbar.matchOnlyTyped"

Definition at line 109 of file nsGlobalHistory.cpp.

#define PREF_BRANCH_BASE   "browser."

Definition at line 107 of file nsGlobalHistory.cpp.

#define PREF_BROWSER_HISTORY_EXPIRE_DAYS   "history_expire_days"

Definition at line 108 of file nsGlobalHistory.cpp.

Function Documentation

static PRBool HasCell ( nsIMdbEnv aEnv,
nsIMdbRow aRow,
mdb_column  aCol 
) [static]

Definition at line 210 of file nsGlobalHistory.cpp.

  mdbYarn yarn;
  mdb_err err = aRow->AliasCellYarn(aEnv, aCol, &yarn);

  // no cell
  if (err != 0)
    return PR_FALSE;

  // if we have the cell, make sure it has a value??
  return (yarn.mYarn_Fill != 0);

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool matchAgeInDaysCallback ( nsIMdbRow row,
void aClosure 
) [static]

Definition at line 280 of file nsGlobalHistory.cpp.

  matchSearchTerm_t *matchSearchTerm = (matchSearchTerm_t*)aClosure;
  const searchTerm *term = matchSearchTerm->term;
  nsIMdbEnv *env = matchSearchTerm->env;
  nsIMdbStore *store = matchSearchTerm->store;
  // fill in the rest of the closure if it's not filled in yet
  // this saves us from recalculating this stuff on every row
  if (!matchSearchTerm->haveClosure) {
    PRInt32 err;
    // Need to create an nsAutoString to use ToInteger
    matchSearchTerm->intValue =  nsAutoString(term->text).ToInteger(&err);
    if (err != 0) return PR_FALSE;
    matchSearchTerm->haveClosure = PR_TRUE;
  // XXX convert the property to a column, get the column value

  mdb_column column;
  mdb_err err = store->StringToToken(env, "LastVisitDate", &column);
  if (err != 0) return PR_FALSE;

  mdbYarn yarn;
  err = row->AliasCellYarn(env, column, &yarn);
  if (err != 0) return PR_FALSE;
  PRTime rowDate;
  PR_sscanf((const char*)yarn.mYarn_Buf, "%lld", &rowDate);

  PRInt32 days = matchSearchTerm->globalHist->GetAgeInDays(rowDate);
  if (term->method.Equals("is"))
    return (days == matchSearchTerm->intValue);
  else if (term->method.Equals("isgreater"))
    return (days >  matchSearchTerm->intValue);
  else if (term->method.Equals("isless"))
    return (days <  matchSearchTerm->intValue);
  return PR_FALSE;

Here is the call graph for this function:

static PRBool matchAllCallback ( nsIMdbRow row,
void aClosure 
) [static]

Definition at line 330 of file nsGlobalHistory.cpp.

  return PR_TRUE;
static PRBool matchExpirationCallback ( nsIMdbRow row,
void aClosure 
) [static]

Definition at line 323 of file nsGlobalHistory.cpp.

  matchExpiration_t *expires = (matchExpiration_t*)aClosure;
  return expires->history->MatchExpiration(row, expires->expirationDate);

Here is the call graph for this function:

static PRBool matchHostCallback ( nsIMdbRow row,
void aClosure 
) [static]

Definition at line 336 of file nsGlobalHistory.cpp.

  matchHost_t *hostInfo = (matchHost_t*)aClosure;
  return hostInfo->history->MatchHost(row, hostInfo);

Here is the call graph for this function:

static PRBool matchQueryCallback ( nsIMdbRow row,
void aClosure 
) [static]

Definition at line 343 of file nsGlobalHistory.cpp.

  matchQuery_t *query = (matchQuery_t*)aClosure;
  return query->history->RowMatches(row, query->query);

Here is the call graph for this function:

static NS_DEFINE_CID ( kRDFServiceCID  ,
) [static]
static NS_DEFINE_CID ( kStringBundleServiceCID  ,
) [static]

Definition at line 531 of file nsGlobalHistory.cpp.

  nsresult rv;

  // If history is set to expire after 0 days,
  // then it's technically disabled. Don't even
  // bother adding the page
  if (mExpireDays == 0)
    return NS_OK;

  // filter out unwanted URIs such as chrome: mailbox: etc
  // The model is really if we don't know differently then add which basically
  // means we are suppose to try all the things we know not to allow in and
  // then if we don't bail go on and allow it in.  But here lets compare
  // against the most common case we know to allow in and go on and say yes
  // to it.


  NS_ENSURE_SUCCESS(rv = aURI->SchemeIs("http", &isHTTP), rv);
  NS_ENSURE_SUCCESS(rv = aURI->SchemeIs("https", &isHTTPS), rv);

  if (!isHTTP && !isHTTPS) {
    PRBool isAbout, isImap, isNews, isMailbox, isViewSource, isChrome, isData;

    rv = aURI->SchemeIs("about", &isAbout);
    rv |= aURI->SchemeIs("imap", &isImap);
    rv |= aURI->SchemeIs("news", &isNews);
    rv |= aURI->SchemeIs("mailbox", &isMailbox);
    rv |= aURI->SchemeIs("view-source", &isViewSource);
    rv |= aURI->SchemeIs("chrome", &isChrome);
    rv |= aURI->SchemeIs("data", &isData);

    if (isAbout || isImap || isNews || isMailbox || isViewSource || isChrome || isData) {
      return NS_OK;

  rv = OpenDB();

  nsCAutoString URISpec;
  rv = aURI->GetSpec(URISpec);

  if (URISpec.Length() > HISTORY_URI_LENGTH_MAX)
     return NS_OK;

  nsCAutoString referrerSpec;
  if (aReferrer) {
    rv = aReferrer->GetSpec(referrerSpec);
    NS_ENSURE_SUCCESS(rv, rv);

  PRTime now = GetNow();

  // For notifying observers, later...
  nsCOMPtr<nsIRDFResource> url;
  rv = gRDFService->GetResource(URISpec, getter_AddRefs(url));
  if (NS_FAILED(rv)) return rv;

  nsCOMPtr<nsIRDFDate> date;
  rv = gRDFService->GetDateLiteral(now, getter_AddRefs(date));
  if (NS_FAILED(rv)) return rv;

  PRBool isJavascript;
  rv = aURI->SchemeIs("javascript", &isJavascript);

  nsCOMPtr<nsIMdbRow> row;
  rv = FindRow(kToken_URLColumn, URISpec.get(), getter_AddRefs(row));

  if (NS_SUCCEEDED(rv)) {

    // If this is not a JS url, not a redirected URI and not in a frame, 
    // unhide it since URIs are added hidden if they are redirected, in a 
    // frame or typed.
    PRBool wasTyped = HasCell(mEnv, row, kToken_TypedColumn);
    if (wasTyped) {
    if ((!isJavascript && !aRedirect && aTopLevel) || wasTyped) {
      row->CutColumn(mEnv, kToken_HiddenColumn);

    // update the database, and get the old info back
    PRTime oldDate;
    PRInt32 oldCount;
    rv = AddExistingPageToDatabase(row, now, referrerSpec.get(), &oldDate, &oldCount);
    NS_ASSERTION(NS_SUCCEEDED(rv), "AddExistingPageToDatabase failed; see bug 88961");
    if (NS_FAILED(rv)) return rv;
    // Notify observers
    // visit date
    nsCOMPtr<nsIRDFDate> oldDateLiteral;
    rv = gRDFService->GetDateLiteral(oldDate, getter_AddRefs(oldDateLiteral));
    if (NS_FAILED(rv)) return rv;
    rv = NotifyChange(url, kNC_Date, oldDateLiteral, date);
    if (NS_FAILED(rv)) return rv;

    // visit count
    nsCOMPtr<nsIRDFInt> oldCountLiteral;
    rv = gRDFService->GetIntLiteral(oldCount, getter_AddRefs(oldCountLiteral));
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIRDFInt> newCountLiteral;
    rv = gRDFService->GetIntLiteral(oldCount+1,
    if (NS_FAILED(rv)) return rv;

    rv = NotifyChange(url, kNC_VisitCount, oldCountLiteral, newCountLiteral);
    if (NS_FAILED(rv)) return rv;
  else {
    rv = AddNewPageToDatabase(URISpec.get(), now, referrerSpec.get(), getter_AddRefs(row));
    NS_ASSERTION(NS_SUCCEEDED(rv), "AddNewPageToDatabase failed; see bug 88961");
    if (NS_FAILED(rv)) return rv;
    if (isJavascript || aRedirect || !aTopLevel) {
      // if this is a JS url, or a redirected URI or in a frame, hide it in
      // global history so that it doesn't show up in the autocomplete
      // dropdown. We'll unhide non-JS urls later if we visit the URI not as 
      // part of a redirect and not in a frame. See bug 197127, bug 161531 and
      // bug 322106 for details.
      rv = SetRowValue(row, kToken_HiddenColumn, 1);
      NS_ENSURE_SUCCESS(rv, rv);
    else {
      // Notify observers
      rv = NotifyAssert(url, kNC_Date, date);
      if (NS_FAILED(rv)) return rv;

      rv = NotifyAssert(kNC_HistoryRoot, kNC_child, url);
      if (NS_FAILED(rv)) return rv;
      NotifyFindAssertions(url, row);

  // Store last visited page if we have the pref set accordingly
  if (aTopLevel) {
    PRInt32 choice = 0;
    if (NS_SUCCEEDED(gPrefBranch->GetIntPref("", &choice))) {
      if (choice != 2) {
        if (NS_SUCCEEDED(gPrefBranch->GetIntPref("windows.loadOnNewWindow", &choice))) {
          if (choice != 2) {
            gPrefBranch->GetIntPref("tabs.loadOnNewTab", &choice);
    if (choice == 2) {

      SetRowValue(mMetaRow, kToken_LastPageVisited, URISpec.get());
  return NS_OK;

Here is the call graph for this function:

Variable Documentation

const PRInt64 MSECS_PER_DAY = LL_INIT(20, 500654080) [static]

Definition at line 126 of file nsGlobalHistory.cpp.