Bug 1434768 - Part 1: Add Child/ParentSHistory classes which wrap nsISHistory, r=bz
authorNika Layzell <nika@thelayzells.com>
Thu, 01 Feb 2018 17:38:07 -0500
changeset 412753 47c477fefd3b83f5888a558b546a92d525d1cbd1
parent 412752 e1fab4fd5afa8e38eeac19caab7c3b2be0872148
child 412754 c1dc655523000be37d89f5231636c47d70f6d141
push id33818
push userapavel@mozilla.com
push dateWed, 11 Apr 2018 14:36:40 +0000
treeherdermozilla-central@cfe6399e142c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1434768
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1434768 - Part 1: Add Child/ParentSHistory classes which wrap nsISHistory, r=bz
docshell/shistory/ChildSHistory.cpp
docshell/shistory/ChildSHistory.h
docshell/shistory/ParentSHistory.cpp
docshell/shistory/ParentSHistory.h
docshell/shistory/moz.build
docshell/shistory/nsSHistory.h
dom/bindings/Bindings.conf
dom/webidl/ChildSHistory.webidl
dom/webidl/ParentSHistory.webidl
dom/webidl/moz.build
ipc/chromium/src/base/process_util.h
new file mode 100644
--- /dev/null
+++ b/docshell/shistory/ChildSHistory.cpp
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/ChildSHistory.h"
+#include "mozilla/dom/ChildSHistoryBinding.h"
+#include "nsIMessageManager.h"
+#include "nsComponentManagerUtils.h"
+#include "nsSHistory.h"
+#include "nsDocShell.h"
+#include "nsISHEntry.h"
+#include "nsXULAppAPI.h"
+
+namespace mozilla {
+namespace dom {
+
+ChildSHistory::ChildSHistory(nsDocShell* aDocShell)
+  : mDocShell(aDocShell)
+  , mHistory(new nsSHistory())
+{
+  mHistory->SetRootDocShell(mDocShell);
+}
+
+ChildSHistory::~ChildSHistory()
+{
+}
+
+int32_t
+ChildSHistory::Count()
+{
+  int32_t count;
+  mHistory->GetCount(&count);
+  return count;
+}
+
+int32_t
+ChildSHistory::Index()
+{
+  int32_t index;
+  mHistory->GetIndex(&index);
+  return index;
+}
+
+void
+ChildSHistory::Reload(uint32_t aReloadFlags, ErrorResult& aRv)
+{
+  aRv = mHistory->Reload(aReloadFlags);
+}
+
+bool
+ChildSHistory::CanGo(int32_t aOffset)
+{
+  CheckedInt<int32_t> index = Index();
+  index += aOffset;
+  if (!index.isValid()) {
+    return false;
+  }
+  return index.value() < Count() && index.value() >= 0;
+}
+
+void
+ChildSHistory::Go(int32_t aOffset, ErrorResult& aRv)
+{
+  // XXX(nika): Should we turn Go(-1) and Go(1) to call GoForward and GoBack?
+  // They technically fire different change events but I couldn't find anyone
+  // who cares, so I'm inclined not to.
+  CheckedInt<int32_t> index = Index();
+  index += aOffset;
+  if (!index.isValid()) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+  aRv = mHistory->GotoIndex(index.value());
+}
+
+nsISHistory*
+ChildSHistory::LegacySHistory()
+{
+  return mHistory;
+}
+
+nsISHistoryInternal*
+ChildSHistory::LegacySHistoryInternal()
+{
+  return mHistory;
+}
+
+nsIWebNavigation*
+ChildSHistory::LegacySHistoryWebNav()
+{
+  return mHistory;
+}
+
+ParentSHistory*
+ChildSHistory::GetParentIfSameProcess()
+{
+  if (XRE_IsContentProcess()) {
+    return nullptr;
+  }
+
+  MOZ_CRASH("Unimplemented!");
+}
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChildSHistory)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ChildSHistory)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ChildSHistory)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ChildSHistory,
+                                      mDocShell,
+                                      mHistory)
+
+JSObject*
+ChildSHistory::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
+{
+  return ChildSHistoryBinding::Wrap(cx, this, aGivenProto);
+}
+
+nsISupports*
+ChildSHistory::GetParentObject() const
+{
+  // We want to get the TabChildGlobal, which is the
+  // nsIContentFrameMessageManager on mDocShell.
+  nsCOMPtr<nsIContentFrameMessageManager> mm =
+    do_GetInterface(static_cast<nsIDocShell*>(mDocShell));
+  return mm;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/docshell/shistory/ChildSHistory.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * ChildSHistory represents a view of session history from a child process. It
+ * exposes getters for some cached history state, and mutators which are
+ * implemented by communicating with the actual history storage in
+ * ParentSHistory.
+ *
+ * NOTE: Currently session history is in transition, meaning that we're still
+ * using the legacy nsSHistory class internally. The API exposed from this class
+ * should be only the API which we expect to expose when this transition is
+ * complete, and special cases will need to call through the LegacySHistory()
+ * getters.
+ */
+
+#ifndef mozilla_dom_ChildSHistory_h
+#define mozilla_dom_ChildSHistory_h
+
+#include "nsCOMPtr.h"
+#include "mozilla/ErrorResult.h"
+#include "nsWrapperCache.h"
+
+class nsSHistory;
+class nsDocShell;
+class nsISHistory;
+class nsISHistoryInternal;
+class nsIWebNavigation;
+class nsIGlobalObject;
+
+namespace mozilla {
+namespace dom {
+
+class ParentSHistory;
+
+class ChildSHistory
+  : public nsISupports
+  , public nsWrapperCache
+{
+public:
+  friend class ParentSHistory;
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ChildSHistory)
+  nsISupports* GetParentObject() const;
+  JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
+
+  explicit ChildSHistory(nsDocShell* aDocShell);
+
+  int32_t Count();
+  int32_t Index();
+
+  /**
+   * Reload the current entry in the session history.
+   */
+  void Reload(uint32_t aReloadFlags, ErrorResult& aRv);
+
+  /**
+   * The CanGo and Go methods are called with an offset from the current index.
+   * Positive numbers go forward in history, while negative numbers go
+   * backwards.
+   */
+  bool CanGo(int32_t aOffset);
+  void Go(int32_t aOffset, ErrorResult& aRv);
+
+  nsISHistory* LegacySHistory();
+  nsISHistoryInternal* LegacySHistoryInternal();
+  nsIWebNavigation* LegacySHistoryWebNav();
+
+  ParentSHistory* GetParentIfSameProcess();
+
+private:
+  virtual ~ChildSHistory();
+
+  RefPtr<nsDocShell> mDocShell;
+  RefPtr<nsSHistory> mHistory;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif /* mozilla_dom_ChildSHistory_h */
new file mode 100644
--- /dev/null
+++ b/docshell/shistory/ParentSHistory.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/ParentSHistory.h"
+#include "mozilla/dom/ParentSHistoryBinding.h"
+#include "mozilla/dom/TabParent.h"
+#include "nsDocShell.h"
+#include "nsFrameLoader.h"
+#include "nsXULAppAPI.h"
+
+namespace mozilla {
+namespace dom {
+
+ParentSHistory::ParentSHistory(nsFrameLoader* aFrameLoader)
+  : mFrameLoader(aFrameLoader)
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+}
+
+ParentSHistory::~ParentSHistory()
+{
+}
+
+nsDocShell*
+ParentSHistory::GetDocShell()
+{
+  return nsDocShell::Cast(mFrameLoader->GetExistingDocShell());
+}
+
+TabParent*
+ParentSHistory::GetTabParent()
+{
+  return static_cast<TabParent*>(mFrameLoader->GetRemoteBrowser());
+}
+
+already_AddRefed<ChildSHistory>
+ParentSHistory::GetChildIfSameProcess()
+{
+  if (XRE_IsContentProcess()) {
+    MOZ_ASSERT(!mDocShell);
+    return nullptr;
+  }
+
+  MOZ_CRASH("Unimplemented!");
+}
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ParentSHistory)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ParentSHistory)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ParentSHistory)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ParentSHistory,
+                                      mFrameLoader)
+
+JSObject*
+ParentSHistory::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
+{
+  return ParentSHistoryBinding::Wrap(cx, this, aGivenProto);
+}
+
+nsISupports*
+ParentSHistory::GetParentObject() const
+{
+  return static_cast<nsIFrameLoader*>(mFrameLoader);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/docshell/shistory/ParentSHistory.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * ParentSHistory is the ultimate source of truth for a browsing session's
+ * history. It lives in the parent process and stores the complete view of
+ * session history.
+ *
+ * NOTE: Currently session history is in transition, meaning that we're still
+ * using the legacy nsSHistory class internally. This means that currently the
+ * session history state lives in the content process, rather than in this
+ * class.
+ */
+
+#ifndef mozilla_dom_ParentSHistory_h
+#define mozilla_dom_ParentSHistory_h
+
+#include "nsCOMPtr.h"
+#include "mozilla/RefPtr.h"
+#include "nsISHistory.h"
+#include "mozilla/ErrorResult.h"
+#include "nsWrapperCache.h"
+
+class nsDocShell;
+
+namespace mozilla {
+namespace dom {
+
+class TabParent;
+class ChildSHistory;
+
+class ParentSHistory
+  : public nsISupports
+  , public nsWrapperCache
+{
+public:
+  friend class ChildSHistory;
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ParentSHistory)
+  nsISupports* GetParentObject() const;
+  JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
+
+  explicit ParentSHistory(nsFrameLoader* aFrameLoader);
+
+  // XXX(nika): Implement
+  int32_t Count() { return 0; }
+  int32_t Index() { return 0; }
+
+private:
+  nsDocShell* GetDocShell();
+  TabParent* GetTabParent();
+
+  already_AddRefed<ChildSHistory> GetChildIfSameProcess();
+
+  virtual ~ParentSHistory();
+
+  RefPtr<nsFrameLoader> mFrameLoader;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif /* mozilla_dom_ParentSHistory_h */
--- a/docshell/shistory/moz.build
+++ b/docshell/shistory/moz.build
@@ -15,23 +15,33 @@ XPIDL_SOURCES += [
 ]
 
 XPIDL_MODULE = 'shistory'
 
 EXPORTS += [
     'nsSHEntryShared.h',
 ]
 
+EXPORTS.mozilla.dom += [
+    'ChildSHistory.h',
+    'ParentSHistory.h',
+]
+
 UNIFIED_SOURCES += [
+    'ChildSHistory.cpp',
     'nsSHEntry.cpp',
     'nsSHEntryShared.cpp',
     'nsSHistory.cpp',
     'nsSHTransaction.cpp',
+    'ParentSHistory.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/docshell/base',
+    '/dom/base',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
+
+include('/ipc/chromium/chromium-config.mozbuild')
--- a/docshell/shistory/nsSHistory.h
+++ b/docshell/shistory/nsSHistory.h
@@ -16,16 +16,17 @@
 #include "nsSHEntryShared.h"
 #include "nsTObserverArray.h"
 #include "nsWeakReference.h"
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/UniquePtr.h"
 
 class nsIDocShell;
+class nsDocShell;
 class nsSHEnumerator;
 class nsSHistoryObserver;
 class nsISHEntry;
 class nsISHTransaction;
 
 class nsSHistory final : public mozilla::LinkedListElement<nsSHistory>,
                          public nsISHistory,
                          public nsISHistoryInternal,
@@ -203,9 +204,15 @@ protected:
   friend class nsSHistory;
   virtual ~nsSHEnumerator();
 
 private:
   int32_t mIndex;
   nsSHistory* mSHistory;
 };
 
+inline nsISupports*
+ToSupports(nsSHistory* aObj)
+{
+  return static_cast<nsISHistory*>(aObj);
+}
+
 #endif /* nsSHistory */
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1755,8 +1755,9 @@ addExternalIface('TabParent', nativeType
                  notflattened=True)
 addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
                  notflattened=True)
 addExternalIface('XULCommandDispatcher', notflattened=True)
 addExternalIface('XULTemplateResult', nativeType='nsIXULTemplateResult',
                  notflattened=True)
 addExternalIface('XULTemplateRuleFilter', nativeType='nsIXULTemplateRuleFilter',
                  notflattened=True)
+addExternalIface('nsISHistory', nativeType='nsISHistory', notflattened=True)
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ChildSHistory.webidl
@@ -0,0 +1,39 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+interface nsISHistory;
+
+/**
+ * The ChildSHistory interface represents the child side of a browsing
+ * context's session history.
+ */
+[ChromeOnly]
+interface ChildSHistory {
+  [Pure]
+  readonly attribute long count;
+  [Pure]
+  readonly attribute long index;
+
+  boolean canGo(long aOffset);
+  [Throws]
+  void go(long aOffset);
+
+  /**
+   * Reload the current entry. The flags which should be passed to this
+   * function are documented and defined in nsIWebNavigation.idl
+   */
+  [Throws]
+  void reload(unsigned long aReloadFlags);
+
+  /**
+   * Getter for the legacy nsISHistory implementation.
+   *
+   * This getter _will be going away_, but is needed while we finish
+   * implementing all of the APIs which we will need in the content
+   * process on ChildSHistory.
+   */
+  readonly attribute nsISHistory legacySHistory;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ParentSHistory.webidl
@@ -0,0 +1,18 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/**
+ * The ParentSHistory interface represents the parent side of a browsing
+ * context's session history. Theoretically this object manages all session
+ * history state for the browsing context.
+ */
+[ChromeOnly]
+interface ParentSHistory {
+  [Pure]
+  readonly attribute long count;
+  [Pure]
+  readonly attribute long index;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -406,16 +406,17 @@ WEBIDL_FILES = [
     'CanvasRenderingContext2D.webidl',
     'CaretPosition.webidl',
     'CDATASection.webidl',
     'ChannelMergerNode.webidl',
     'ChannelSplitterNode.webidl',
     'CharacterData.webidl',
     'CheckerboardReportService.webidl',
     'ChildNode.webidl',
+    'ChildSHistory.webidl',
     'ChromeNodeList.webidl',
     'Client.webidl',
     'Clients.webidl',
     'ClipboardEvent.webidl',
     'CommandEvent.webidl',
     'Comment.webidl',
     'CompositionEvent.webidl',
     'Console.webidl',
@@ -693,16 +694,17 @@ WEBIDL_FILES = [
     'OfflineResourceList.webidl',
     'OffscreenCanvas.webidl',
     'OscillatorNode.webidl',
     'PaintRequest.webidl',
     'PaintRequestList.webidl',
     'PaintWorkletGlobalScope.webidl',
     'PannerNode.webidl',
     'ParentNode.webidl',
+    'ParentSHistory.webidl',
     'PaymentAddress.webidl',
     'PaymentRequest.webidl',
     'PaymentRequestUpdateEvent.webidl',
     'PaymentResponse.webidl',
     'Performance.webidl',
     'PerformanceEntry.webidl',
     'PerformanceMark.webidl',
     'PerformanceMeasure.webidl',
--- a/ipc/chromium/src/base/process_util.h
+++ b/ipc/chromium/src/base/process_util.h
@@ -243,11 +243,13 @@ private:
 
 #if defined(OS_WIN)
 // Undo the windows.h damage
 #undef GetMessage
 #undef CreateEvent
 #undef GetClassName
 #undef GetBinaryType
 #undef RemoveDirectory
+#undef LoadImage
+#undef LoadIcon
 #endif
 
 #endif  // BASE_PROCESS_UTIL_H_