Bug 516728 - Remote link-visited information. r=sdwilsh, sr=bz
authorDoug Turner <dougt@dougt.org>
Fri, 02 Jul 2010 08:50:41 -0700
changeset 48297 9ebd1145c98ae09287bfb80f7b07a24c37d3229b
parent 48296 f9214514d547d172141f4c5ee4ae975b83b70488
child 48298 da160d0117e718de1c2e9b4e580e7f461c8164ff
push idunknown
push userunknown
push dateunknown
reviewerssdwilsh, bz
bugs516728
milestone2.0b3pre
Bug 516728 - Remote link-visited information. r=sdwilsh, sr=bz
docshell/base/IHistory.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/Makefile.in
dom/ipc/PContent.ipdl
toolkit/components/places/src/History.cpp
toolkit/components/places/src/Makefile.in
--- a/docshell/base/IHistory.h
+++ b/docshell/base/IHistory.h
@@ -47,17 +47,17 @@ class nsString;
 
 namespace mozilla {
 
     namespace dom {
         class Link;
     }
 
 #define IHISTORY_IID \
-  {0x6f736049, 0x6370, 0x4376, {0xb7, 0x17, 0xfa, 0xfc, 0x0b, 0x4f, 0xd0, 0xf1}}
+  {0x6f733924, 0x6321, 0x4384, {0x01, 0xee, 0x8e, 0x7d, 0xfb, 0xde, 0xe7, 0xa8}}
 
 class IHistory : public nsISupports
 {
 public:
     NS_DECLARE_STATIC_IID_ACCESSOR(IHISTORY_IID)
 
     /**
      * Registers the Link for notifications about the visited-ness of aURI.
@@ -66,17 +66,17 @@ public:
      * SetLinkState called on themselves.  This function is guaranteed to run to
      * completion before aLink is notified.  After the node is notified, it will
      * be unregistered.
      *
      * @note SetLinkState must not call RegisterVisitedCallback or
      *       UnregisterVisitedCallback.
      *
      * @pre aURI must not be null.
-     * @pre aLink must not be null.
+     * @pre aLink may be null only in the MOZ_IPC parent process.
      *
      * @param aURI
      *        The URI to check.
      * @param aLink
      *        The link to update whenever the history status changes.  The
      *        implementation will only hold onto a raw pointer, so if this
      *        object should be destroyed, be sure to call
      *        UnregisterVistedCallback first.
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -49,24 +49,29 @@
 #include "nsTObserverArray.h"
 #include "nsIObserver.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXULAppAPI.h"
 #include "nsWeakReference.h"
 
+#include "History.h"
+#include "nsDocShellCID.h"
+#include "nsNetUtil.h"
+
 #include "base/message_loop.h"
 #include "base/task.h"
 
 #include "nsChromeRegistryContent.h"
 #include "mozilla/chrome/RegistryMessageUtils.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::net;
+using namespace mozilla::places;
 
 namespace mozilla {
 namespace dom {
 
 class PrefObserver
 {
 public:
     /**
@@ -338,10 +343,18 @@ ContentChild::RecvNotifyRemotePrefObserv
             mPrefObservers.RemoveElementAt(i);
             continue;
         }
         ++i;
     }
     return true;
 }
 
+bool
+ContentChild::RecvNotifyVisited(const IPC::URI& aURI)
+{
+    nsCOMPtr<nsIURI> newURI = aURI;
+    History::GetService()->NotifyVisited(newURI);
+    return true;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -83,16 +83,18 @@ public:
     virtual bool DeallocPNecko(PNeckoChild*);
 
     virtual bool RecvRegisterChrome(const nsTArray<ChromePackage>& packages,
                                     const nsTArray<ResourceMapping>& resources,
                                     const nsTArray<OverrideMapping>& overrides);
 
     virtual bool RecvSetOffline(const PRBool& offline);
 
+    virtual bool RecvNotifyVisited(const IPC::URI& aURI);
+
     /**
      * Notify |aObserver| of changes to |aPrefRoot|.|aDomain|.  If
      * |aHoldWeak|, only a weak reference to |aObserver| is held.
      */
     nsresult AddRemotePrefObserver(const nsCString& aDomain, 
                                    const nsCString& aPrefRoot, 
                                    nsIObserver* aObserver, PRBool aHoldWeak);
     nsresult RemoveRemotePrefObserver(const nsCString& aDomain, 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -35,31 +35,33 @@
  * 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 "ContentParent.h"
 
 #include "TabParent.h"
+#include "History.h"
 #include "mozilla/ipc/TestShellParent.h"
 #include "mozilla/net/NeckoParent.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefBranch2.h"
 #include "nsIPrefLocalizedString.h"
 #include "nsIObserverService.h"
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsChromeRegistryChrome.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::net;
+using namespace mozilla::places;
 using mozilla::MonitorAutoEnter;
 
 namespace mozilla {
 namespace dom {
 
 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
 
 ContentParent* ContentParent::gSingleton;
@@ -425,16 +427,25 @@ ContentParent::RequestRunToCompletion()
         printf("Running to completion...\n");
 #endif
         mRunToCompletionDepth = 1;
         mShouldCallUnblockChild = true;
     }
     return !!mRunToCompletionDepth;
 }
 
+bool
+ContentParent::RecvStartVisitedQuery(const IPC::URI& aURI)
+{
+    nsCOMPtr<nsIURI> newURI = aURI;
+    IHistory *history = nsContentUtils::GetHistory(); 
+    history->RegisterVisitedCallback(newURI, nsnull);
+    return true;
+}
+
 /* void onDispatchedEvent (in nsIThreadInternal thread); */
 NS_IMETHODIMP
 ContentParent::OnDispatchedEvent(nsIThreadInternal *thread)
 {
     if (mOldObserver)
         return mOldObserver->OnDispatchedEvent(thread);
 
     return NS_OK;
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -140,16 +140,18 @@ private:
     virtual bool RecvTestPermission(const IPC::URI&  aUri,
                                     const nsCString& aType,
                                     const PRBool&    aExact,
                                     PRUint32*        retValue);
 
     void EnsurePrefService();
     void EnsurePermissionService();
 
+    virtual bool RecvStartVisitedQuery(const IPC::URI& uri);
+
     mozilla::Monitor mMonitor;
 
     GeckoChildProcessHost* mSubprocess;
 
     int mRunToCompletionDepth;
     bool mShouldCallUnblockChild;
     nsCOMPtr<nsIThreadObserver> mOldObserver;
 
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -74,15 +74,16 @@ CPPSRCS = \
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
 		-I$(srcdir)/../../content/base/src \
 		-I$(srcdir)/../../content/events/src \
+		-I$(srcdir)/../../toolkit/components/places/src \
 		-I$(srcdir)/../src/geolocation \
 		-I$(topsrcdir)/chrome/src \
 		$(NULL)
 
 CXXFLAGS += $(TK_CFLAGS)
 
 DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -63,23 +63,27 @@ child:
 
     PTestShell();
 
     RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
                    OverrideMapping[] overrides);
 
     async SetOffline(PRBool offline);
 
+    async NotifyVisited(URI uri);
+
     NotifyRemotePrefObserver(nsCString aDomain);
 
 parent:
     PNecko();
 
     // Services remoting
 
+    async StartVisitedQuery(URI uri);
+
     // PrefService messages
     sync GetPrefType(nsCString prefName) returns (PRInt32 retValue, nsresult rv);
     sync GetBoolPref(nsCString prefName) returns (PRBool retValue, nsresult rv);
     sync GetIntPref(nsCString prefName)  returns (PRInt32 retValue, nsresult rv);
     sync GetCharPref(nsCString prefName) returns (nsCString retValue, nsresult rv);
     sync GetPrefLocalizedString(nsCString prefName) returns (nsString retValue, nsresult rv);
     sync PrefHasUserValue(nsCString prefName) returns (PRBool retValue, nsresult rv);
     sync PrefIsLocked(nsCString prefName) returns (PRBool retValue, nsresult rv);
--- a/toolkit/components/places/src/History.cpp
+++ b/toolkit/components/places/src/History.cpp
@@ -32,16 +32,22 @@
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentParent.h"
+#include "nsXULAppAPI.h"
+#endif
+
 #include "History.h"
 #include "nsNavHistory.h"
 #include "nsNavBookmarks.h"
 #include "Helpers.h"
 
 #include "mozilla/storage.h"
 #include "mozilla/dom/Link.h"
 #include "nsDocShellCID.h"
@@ -150,16 +156,28 @@ class VisitedQuery : public mozIStorageS
 {
 public:
   NS_DECL_ISUPPORTS
 
   static nsresult Start(nsIURI* aURI)
   {
     NS_PRECONDITION(aURI, "Null URI");
 
+#ifdef MOZ_IPC
+  // If we are a content process, always remote the request to the
+  // parent process.
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    mozilla::dom::ContentChild * cpc = 
+      mozilla::dom::ContentChild::GetSingleton();
+    NS_ASSERTION(cpc, "Content Protocol is NULL!");
+    (void)cpc->SendStartVisitedQuery(IPC::URI(aURI));
+    return NS_OK;
+  }
+#endif
+
     nsNavHistory* navHist = nsNavHistory::GetHistoryService();
     NS_ENSURE_TRUE(navHist, NS_ERROR_FAILURE);
     mozIStorageStatement* stmt = navHist->GetStatementById(DB_IS_PAGE_VISITED);
     NS_ENSURE_STATE(stmt);
 
     // Bind by index for performance.
     nsresult rv = URIBinder::Bind(stmt, 0, aURI);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -951,16 +969,25 @@ History::CurrentTaskFinished()
   StartNextTask();
 }
 
 void
 History::NotifyVisited(nsIURI* aURI)
 {
   NS_ASSERTION(aURI, "Ruh-roh!  A NULL URI was passed to us!");
 
+#ifdef MOZ_IPC
+  if (XRE_GetProcessType() == GeckoProcessType_Default) {
+    mozilla::dom::ContentParent* cpp = 
+      mozilla::dom::ContentParent::GetSingleton(PR_FALSE);
+    if (cpp)
+      (void)cpp->SendNotifyVisited(IPC::URI(aURI));
+  }
+#endif
+
   // If the hash table has not been initialized, then we have nothing to notify
   // about.
   if (!mObservers.IsInitialized()) {
     return;
   }
 
   // Additionally, if we have no observers for this URI, we have nothing to
   // notify about.
@@ -1130,17 +1157,24 @@ History::VisitURI(nsIURI* aURI,
   return NS_OK;
 }
 
 NS_IMETHODIMP
 History::RegisterVisitedCallback(nsIURI* aURI,
                                  Link* aLink)
 {
   NS_ASSERTION(aURI, "Must pass a non-null URI!");
-  NS_ASSERTION(aLink, "Must pass a non-null Link object!");
+#ifdef MOZ_IPC
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    NS_PRECONDITION(aLink, "Must pass a non-null URI!");
+  }
+#else
+  NS_PRECONDITION(aLink, "Must pass a non-null URI!");
+#endif
+
 
   // First, ensure that our hash table is setup.
   if (!mObservers.IsInitialized()) {
     NS_ENSURE_TRUE(mObservers.Init(), NS_ERROR_OUT_OF_MEMORY);
   }
 
   // Obtain our array of observers for this URI.
 #ifdef DEBUG
@@ -1153,17 +1187,17 @@ History::RegisterVisitedCallback(nsIURI*
   if (observers.IsEmpty()) {
     NS_ASSERTION(!keyAlreadyExists,
                  "An empty key was kept around in our hashtable!");
 
     // We are the first Link node to ask about this URI, or there are no pending
     // Links wanting to know about this URI.  Therefore, we should query the
     // database now.
     nsresult rv = VisitedQuery::Start(aURI);
-    if (NS_FAILED(rv)) {
+    if (NS_FAILED(rv) || !aLink) {
       // Remove our array from the hashtable so we don't keep it around.
       mObservers.RemoveEntry(aURI);
       return rv;
     }
   }
 
   // Sanity check that Links are not registered more than once for a given URI.
   // This will not catch a case where it is registered for two different URIs.
--- a/toolkit/components/places/src/Makefile.in
+++ b/toolkit/components/places/src/Makefile.in
@@ -45,16 +45,21 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE = places
 LIBRARY_NAME  = places
 LIBXUL_LIBRARY = 1
 EXPORT_LIBRARY = 1
 MODULE_NAME = nsPlacesModule
 IS_COMPONENT = 1
 
+EXPORTS_NAMESPACES = mozilla/places
+
+EXPORTS_mozilla/places = \
+  History.h \
+  $(NULL)
 
 CPPSRCS = \
           nsAnnoProtocolHandler.cpp \
           nsAnnotationService.cpp \
           nsFaviconService.cpp \
           nsNavHistory.cpp \
           nsNavHistoryQuery.cpp \
           nsNavHistoryResult.cpp \