Bug 1101100 - Multiprocess-enable nsWebBrowserPersist. r=billm

The high-level overview is that the parts of nsWebBrowserPersist which
access the DOM have been factored out (as WebBrowserPersistLocalDocument)
and abstracted (nsIWebBrowserPersistDocument) such that they can be
implemented in the cross-process case using IPC.
This commit is contained in:
Jed Davis 2015-08-05 14:25:39 -07:00
parent 26afedea6c
commit 68210f3fab
38 changed files with 3820 additions and 1654 deletions

View File

@ -22,7 +22,7 @@
<command id="cmd_newNavigatorTab" oncommand="BrowserOpenNewTabOrWindow(event);" reserved="true"/>
<command id="Browser:OpenFile" oncommand="BrowserOpenFileWindow();"/>
<command id="Browser:SavePage" oncommand="saveDocument(gBrowser.selectedBrowser.contentDocumentAsCPOW);"/>
<command id="Browser:SavePage" oncommand="saveBrowser(gBrowser.selectedBrowser);"/>
<command id="Browser:SendLink"
oncommand="MailIntegration.sendLinkForBrowser(gBrowser.selectedBrowser);"/>

View File

@ -1796,7 +1796,7 @@ function HandleAppCommandEvent(evt) {
gBrowser.selectedBrowser);
break;
case "Save":
saveDocument(gBrowser.selectedBrowser.contentDocumentAsCPOW);
saveBrowser(gBrowser.selectedBrowser);
break;
case "SendMail":
MailIntegration.sendLinkForBrowser(gBrowser.selectedBrowser);

View File

@ -1670,7 +1670,7 @@ nsContextMenu.prototype = {
},
savePageAs: function CM_savePageAs() {
saveDocument(this.browser.contentDocumentAsCPOW);
saveBrowser(this.browser);
},
saveLinkToPocket: function CM_saveLinkToPocket() {

View File

@ -315,8 +315,8 @@ const CustomizableWidgets = [
let win = aEvent.target &&
aEvent.target.ownerDocument &&
aEvent.target.ownerDocument.defaultView;
if (win && typeof win.saveDocument == "function") {
win.saveDocument(win.gBrowser.selectedBrowser.contentDocumentAsCPOW);
if (win && typeof win.saveBrowser == "function") {
win.saveBrowser(win.gBrowser.selectedBrowser);
}
}
}, {

View File

@ -93,6 +93,7 @@
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/dom/StructuredCloneUtils.h"
#include "mozilla/WebBrowserPersistLocalDocument.h"
#ifdef MOZ_XUL
#include "nsXULPopupManager.h"
@ -130,6 +131,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFrameLoader)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersistable)
NS_INTERFACE_MAP_END
nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
@ -2847,3 +2849,20 @@ nsFrameLoader::InitializeBrowserAPI()
}
}
}
NS_IMETHODIMP
nsFrameLoader::StartPersistence(nsIWebBrowserPersistDocumentReceiver* aRecv)
{
if (mRemoteBrowser) {
return mRemoteBrowser->StartPersistence(aRecv);
}
if (mDocShell) {
nsCOMPtr<nsIDocument> doc = do_GetInterface(mDocShell);
NS_ENSURE_STATE(doc);
nsCOMPtr<nsIWebBrowserPersistDocument> pdoc =
new mozilla::WebBrowserPersistLocalDocument(doc);
aRecv->OnDocumentReady(pdoc);
return NS_OK;
}
return NS_ERROR_NO_CONTENT;
}

View File

@ -24,6 +24,7 @@
#include "mozilla/Attributes.h"
#include "nsStubMutationObserver.h"
#include "Units.h"
#include "nsIWebBrowserPersistable.h"
class nsIURI;
class nsSubDocumentFrame;
@ -53,6 +54,7 @@ typedef struct _GtkWidget GtkWidget;
#endif
class nsFrameLoader final : public nsIFrameLoader,
public nsIWebBrowserPersistable,
public nsStubMutationObserver,
public mozilla::dom::ipc::MessageManagerCallback
{
@ -69,6 +71,7 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader)
NS_DECL_NSIFRAMELOADER
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
NS_DECL_NSIWEBBROWSERPERSISTABLE
nsresult CheckForRecursiveLoad(nsIURI* aURI);
nsresult ReallyStartLoading();
void StartDestroy();

View File

@ -15,6 +15,7 @@ include protocol PFilePicker;
include protocol PIndexedDBPermissionRequest;
include protocol PRenderFrame;
include protocol PPluginWidget;
include protocol PWebBrowserPersistDocument;
include DOMTypes;
include JavaScriptTypes;
include URIParams;
@ -108,6 +109,7 @@ prio(normal upto urgent) sync protocol PBrowser
manages PIndexedDBPermissionRequest;
manages PRenderFrame;
manages PPluginWidget;
manages PWebBrowserPersistDocument;
both:
AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows,
@ -119,6 +121,8 @@ both:
*/
PRenderFrame();
PWebBrowserPersistDocument();
parent:
/**
* Tell the parent process a new accessible document has been created.

View File

@ -35,6 +35,7 @@
#include "mozilla/layout/RenderFrameChild.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/PWebBrowserPersistDocumentChild.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/TextEvents.h"
@ -98,6 +99,7 @@
#include "nsIScriptError.h"
#include "mozilla/EventForwards.h"
#include "nsDeviceContext.h"
#include "mozilla/WebBrowserPersistDocumentChild.h"
#define BROWSER_ELEMENT_CHILD_SCRIPT \
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
@ -3106,3 +3108,23 @@ TabChildGlobal::GetGlobalJSObject()
return ref->GetJSObject();
}
PWebBrowserPersistDocumentChild*
TabChild::AllocPWebBrowserPersistDocumentChild()
{
return new WebBrowserPersistDocumentChild();
}
bool
TabChild::RecvPWebBrowserPersistDocumentConstructor(PWebBrowserPersistDocumentChild *aActor)
{
nsCOMPtr<nsIDocument> doc = GetDocument();
static_cast<WebBrowserPersistDocumentChild*>(aActor)->Start(doc);
return true;
}
bool
TabChild::DeallocPWebBrowserPersistDocumentChild(PWebBrowserPersistDocumentChild* aActor)
{
delete aActor;
return true;
}

View File

@ -494,6 +494,10 @@ public:
virtual ScreenIntSize GetInnerSize() override;
virtual PWebBrowserPersistDocumentChild* AllocPWebBrowserPersistDocumentChild() override;
virtual bool RecvPWebBrowserPersistDocumentConstructor(PWebBrowserPersistDocumentChild *aActor) override;
virtual bool DeallocPWebBrowserPersistDocumentChild(PWebBrowserPersistDocumentChild* aActor) override;
protected:
virtual ~TabChild();

View File

@ -95,6 +95,7 @@
#include "ImageOps.h"
#include "UnitTransforms.h"
#include <algorithm>
#include "mozilla/WebBrowserPersistDocumentParent.h"
using namespace mozilla::dom;
using namespace mozilla::ipc;
@ -256,7 +257,8 @@ NS_IMPL_ISUPPORTS(TabParent,
nsITabParent,
nsIAuthPromptProvider,
nsISecureBrowserUI,
nsISupportsWeakReference)
nsISupportsWeakReference,
nsIWebBrowserPersistable)
TabParent::TabParent(nsIContentParent* aManager,
const TabId& aTabId,
@ -3345,6 +3347,29 @@ TabParent::AsyncPanZoomEnabled() const
return widget && widget->AsyncPanZoomEnabled();
}
PWebBrowserPersistDocumentParent*
TabParent::AllocPWebBrowserPersistDocumentParent()
{
return new WebBrowserPersistDocumentParent();
}
bool
TabParent::DeallocPWebBrowserPersistDocumentParent(PWebBrowserPersistDocumentParent* aActor)
{
delete aActor;
return true;
}
NS_IMETHODIMP
TabParent::StartPersistence(nsIWebBrowserPersistDocumentReceiver* aRecv)
{
auto* actor = new WebBrowserPersistDocumentParent();
actor->SetOnReady(aRecv);
return SendPWebBrowserPersistDocumentConstructor(actor)
? NS_OK : NS_ERROR_FAILURE;
// (The actor will be destroyed on constructor failure.)
}
NS_IMETHODIMP
FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
{

View File

@ -22,6 +22,7 @@
#include "nsIDOMEventListener.h"
#include "nsISecureBrowserUI.h"
#include "nsITabParent.h"
#include "nsIWebBrowserPersistable.h"
#include "nsIXULBrowserWindow.h"
#include "nsRefreshDriver.h"
#include "nsWeakReference.h"
@ -76,6 +77,7 @@ class TabParent final : public PBrowserParent
, public nsSupportsWeakReference
, public TabContext
, public nsAPostRefreshObserver
, public nsIWebBrowserPersistable
{
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer;
@ -368,6 +370,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIAUTHPROMPTPROVIDER
NS_DECL_NSISECUREBROWSERUI
NS_DECL_NSIWEBBROWSERPERSISTABLE
bool HandleQueryContentEvent(mozilla::WidgetQueryContentEvent& aEvent);
bool SendCompositionEvent(mozilla::WidgetCompositionEvent& event);
@ -430,6 +433,10 @@ public:
void TakeDragVisualization(RefPtr<mozilla::gfx::SourceSurface>& aSurface,
int32_t& aDragAreaX, int32_t& aDragAreaY);
layout::RenderFrameParent* GetRenderFrame();
virtual PWebBrowserPersistDocumentParent* AllocPWebBrowserPersistDocumentParent() override;
virtual bool DeallocPWebBrowserPersistDocumentParent(PWebBrowserPersistDocumentParent* aActor) override;
protected:
bool ReceiveMessage(const nsString& aMessage,
bool aSync,

View File

@ -1065,7 +1065,7 @@ nsWebBrowser::SaveChannel(nsIChannel* aChannel, nsISupports* aFile)
}
NS_IMETHODIMP
nsWebBrowser::SaveDocument(nsIDOMDocument* aDocument,
nsWebBrowser::SaveDocument(nsISupports* aDocumentish,
nsISupports* aFile,
nsISupports* aDataPath,
const char* aOutputContentType,
@ -1086,11 +1086,13 @@ nsWebBrowser::SaveDocument(nsIDOMDocument* aDocument,
// Use the specified DOM document, or if none is specified, the one
// attached to the web browser.
nsCOMPtr<nsIDOMDocument> doc;
if (aDocument) {
doc = do_QueryInterface(aDocument);
nsCOMPtr<nsISupports> doc;
if (aDocumentish) {
doc = aDocumentish;
} else {
GetDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc;
GetDocument(getter_AddRefs(domDoc));
doc = domDoc.forget();
}
if (!doc) {
return NS_ERROR_FAILURE;

View File

@ -0,0 +1,90 @@
/* -*- Mode: IDL; tab-width: 8; 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/. */
include protocol PBrowser;
include protocol PWebBrowserPersistResources;
include protocol PWebBrowserPersistSerialize;
include InputStreamParams;
namespace mozilla {
// nsIWebBrowserPersistDocument has attributes which can be read
// synchronously. To avoid using sync IPC for them, the actor sends
// this structure from the child to the parent before the parent actor
// is exposed to XPCOM.
struct WebBrowserPersistDocumentAttrs {
bool isPrivate;
nsCString documentURI;
nsCString baseURI;
nsCString contentType;
nsCString characterSet;
nsString title;
nsString referrer;
nsString contentDisposition;
uint32_t cacheKey;
uint32_t persistFlags;
};
// IPDL doesn't have tuples, so this gives the pair of strings from
// nsIWebBrowserPersistURIMap::getURIMapping a name.
struct WebBrowserPersistURIMapEntry {
nsCString mapFrom;
nsCString mapTo;
};
// nsIWebBrowserPersistURIMap is just copied over IPC as one of these,
// not proxied, to simplify the protocol.
struct WebBrowserPersistURIMap {
WebBrowserPersistURIMapEntry[] mapURIs;
nsCString targetBaseURI;
};
// This remotes nsIWebBrowserPersistDocument and its visitors. The
// lifecycle is a little complicated: the initial document is
// constructed parent->child, but subdocuments are constructed
// child->parent and then passed back. Subdocuments aren't subactors,
// because that would impose a lifetime relationship that doesn't
// exist in the XPIDL; instead they're all managed by the enclosing
// PBrowser (== TabParent/TabChild).
protocol PWebBrowserPersistDocument {
manager PBrowser;
manages PWebBrowserPersistResources;
manages PWebBrowserPersistSerialize;
parent:
// The actor isn't exposed to XPCOM until after it gets one of these
// two messages; see also the state transition rules. The message
// is either a response to the constructor (if it was parent->child)
// or sent after it (if it was child->parent).
Attributes(WebBrowserPersistDocumentAttrs aAttrs,
OptionalInputStreamParams postData,
FileDescriptor[] postFiles);
InitFailure(nsresult aStatus);
child:
SetPersistFlags(uint32_t aNewFlags);
PWebBrowserPersistResources();
PWebBrowserPersistSerialize(WebBrowserPersistURIMap aMap,
nsCString aRequestedContentType,
uint32_t aEncoderFlags,
uint32_t aWrapColumn);
__delete__();
state START:
recv Attributes goto MAIN;
recv InitFailure goto FAILED;
state MAIN:
send SetPersistFlags goto MAIN;
send PWebBrowserPersistResources goto MAIN;
send PWebBrowserPersistSerialize goto MAIN;
send __delete__;
state FAILED:
send __delete__;
};
} // namespace mozilla

View File

@ -0,0 +1,26 @@
/* -*- Mode: IDL; tab-width: 8; 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/. */
include protocol PWebBrowserPersistDocument;
namespace mozilla {
// == nsIWebBrowserPersistResourceVisitor
protocol PWebBrowserPersistResources {
manager PWebBrowserPersistDocument;
parent:
VisitResource(nsCString aURI);
// The actor sent here is in the START state; the parent-side
// receiver will have to wait for it to enter the MAIN state
// before exposing it with a visitDocument call.
VisitDocument(PWebBrowserPersistDocument aSubDocument);
// This reflects the endVisit method.
__delete__(nsresult aStatus);
};
} // namespace mozilla

View File

@ -0,0 +1,29 @@
/* -*- Mode: IDL; tab-width: 8; 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/. */
include protocol PWebBrowserPersistDocument;
namespace mozilla {
// This actor represents both an nsIWebBrowserPersistWriteCompletion
// and the nsIOutputStream passed with it to the writeContent method.
protocol PWebBrowserPersistSerialize {
manager PWebBrowserPersistDocument;
parent:
// This sends the data with no flow control, so the parent could
// wind up buffering an arbitrarily large amount of data... but
// it's a serialized DOM that's already in memory as DOM nodes, so
// this is at worst just a constant-factor increase in memory usage.
// Also, Chromium does the same thing; see
// content::RenderViewImpl::didSerializeDataForFrame.
WriteData(uint8_t[] aData);
// This is the onFinish method.
__delete__(nsCString aContentType,
nsresult aStatus);
};
} // namespace mozilla

View File

@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 "WebBrowserPersistDocumentChild.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsIDocument.h"
#include "nsIInputStream.h"
#include "WebBrowserPersistLocalDocument.h"
#include "WebBrowserPersistResourcesChild.h"
#include "WebBrowserPersistSerializeChild.h"
namespace mozilla {
WebBrowserPersistDocumentChild::WebBrowserPersistDocumentChild()
{
}
WebBrowserPersistDocumentChild::~WebBrowserPersistDocumentChild()
{
}
void
WebBrowserPersistDocumentChild::Start(nsIDocument* aDocument)
{
nsRefPtr<WebBrowserPersistLocalDocument> doc;
if (aDocument) {
doc = new WebBrowserPersistLocalDocument(aDocument);
}
Start(doc);
}
void
WebBrowserPersistDocumentChild::Start(nsIWebBrowserPersistDocument* aDocument)
{
MOZ_ASSERT(!mDocument);
if (!aDocument) {
SendInitFailure(NS_ERROR_FAILURE);
return;
}
WebBrowserPersistDocumentAttrs attrs;
nsCOMPtr<nsIInputStream> postDataStream;
OptionalInputStreamParams postData;
nsTArray<FileDescriptor> postFiles;
#define ENSURE(e) do { \
nsresult rv = (e); \
if (NS_FAILED(rv)) { \
SendInitFailure(rv); \
return; \
} \
} while(0)
ENSURE(aDocument->GetIsPrivate(&(attrs.isPrivate())));
ENSURE(aDocument->GetDocumentURI(attrs.documentURI()));
ENSURE(aDocument->GetBaseURI(attrs.baseURI()));
ENSURE(aDocument->GetContentType(attrs.contentType()));
ENSURE(aDocument->GetCharacterSet(attrs.characterSet()));
ENSURE(aDocument->GetTitle(attrs.title()));
ENSURE(aDocument->GetReferrer(attrs.referrer()));
ENSURE(aDocument->GetContentDisposition(attrs.contentDisposition()));
ENSURE(aDocument->GetCacheKey(&(attrs.cacheKey())));
ENSURE(aDocument->GetPersistFlags(&(attrs.persistFlags())));
ENSURE(aDocument->GetPostData(getter_AddRefs(postDataStream)));
ipc::SerializeInputStream(postDataStream,
postData,
postFiles);
#undef ENSURE
mDocument = aDocument;
SendAttributes(attrs, postData, postFiles);
}
bool
WebBrowserPersistDocumentChild::RecvSetPersistFlags(const uint32_t& aNewFlags)
{
mDocument->SetPersistFlags(aNewFlags);
return true;
}
PWebBrowserPersistResourcesChild*
WebBrowserPersistDocumentChild::AllocPWebBrowserPersistResourcesChild()
{
auto* actor = new WebBrowserPersistResourcesChild();
NS_ADDREF(actor);
return actor;
}
bool
WebBrowserPersistDocumentChild::RecvPWebBrowserPersistResourcesConstructor(PWebBrowserPersistResourcesChild* aActor)
{
nsRefPtr<WebBrowserPersistResourcesChild> visitor =
static_cast<WebBrowserPersistResourcesChild*>(aActor);
nsresult rv = mDocument->ReadResources(visitor);
if (NS_FAILED(rv)) {
visitor->EndVisit(mDocument, rv);
}
return true;
}
bool
WebBrowserPersistDocumentChild::DeallocPWebBrowserPersistResourcesChild(PWebBrowserPersistResourcesChild* aActor)
{
auto* castActor =
static_cast<WebBrowserPersistResourcesChild*>(aActor);
NS_RELEASE(castActor);
return true;
}
PWebBrowserPersistSerializeChild*
WebBrowserPersistDocumentChild::AllocPWebBrowserPersistSerializeChild(
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn)
{
auto* actor = new WebBrowserPersistSerializeChild(aMap);
NS_ADDREF(actor);
return actor;
}
bool
WebBrowserPersistDocumentChild::RecvPWebBrowserPersistSerializeConstructor(
PWebBrowserPersistSerializeChild* aActor,
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn)
{
auto* castActor =
static_cast<WebBrowserPersistSerializeChild*>(aActor);
// This actor performs the roles of: completion, URI map, and output stream.
nsresult rv = mDocument->WriteContent(castActor,
castActor,
aRequestedContentType,
aEncoderFlags,
aWrapColumn,
castActor);
if (NS_FAILED(rv)) {
castActor->OnFinish(mDocument, castActor, aRequestedContentType, rv);
}
return true;
}
bool
WebBrowserPersistDocumentChild::DeallocPWebBrowserPersistSerializeChild(PWebBrowserPersistSerializeChild* aActor)
{
auto* castActor =
static_cast<WebBrowserPersistSerializeChild*>(aActor);
NS_RELEASE(castActor);
return true;
}
} // namespace mozilla

View File

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef WebBrowserPersistDocumentChild_h__
#define WebBrowserPersistDocumentChild_h__
#include "mozilla/PWebBrowserPersistDocumentChild.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
class nsIDocument;
namespace mozilla {
class WebBrowserPersistDocumentChild final
: public PWebBrowserPersistDocumentChild
{
public:
WebBrowserPersistDocumentChild();
~WebBrowserPersistDocumentChild();
// This sends either Attributes or InitFailure and thereby causes
// the actor to leave the START state.
void Start(nsIWebBrowserPersistDocument* aDocument);
void Start(nsIDocument* aDocument);
virtual bool
RecvSetPersistFlags(const uint32_t& aNewFlags) override;
virtual PWebBrowserPersistResourcesChild*
AllocPWebBrowserPersistResourcesChild() override;
virtual bool
RecvPWebBrowserPersistResourcesConstructor(PWebBrowserPersistResourcesChild* aActor) override;
virtual bool
DeallocPWebBrowserPersistResourcesChild(PWebBrowserPersistResourcesChild* aActor) override;
virtual PWebBrowserPersistSerializeChild*
AllocPWebBrowserPersistSerializeChild(
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn) override;
virtual bool
RecvPWebBrowserPersistSerializeConstructor(
PWebBrowserPersistSerializeChild* aActor,
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn) override;
virtual bool
DeallocPWebBrowserPersistSerializeChild(PWebBrowserPersistSerializeChild* aActor) override;
private:
nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
};
} // namespace mozilla
#endif // WebBrowserPersistDocumentChild_h__

View File

@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 "WebBrowserPersistDocumentParent.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsIInputStream.h"
#include "nsThreadUtils.h"
#include "WebBrowserPersistResourcesParent.h"
#include "WebBrowserPersistSerializeParent.h"
#include "WebBrowserPersistRemoteDocument.h"
namespace mozilla {
WebBrowserPersistDocumentParent::WebBrowserPersistDocumentParent()
: mReflection(nullptr)
{
}
void
WebBrowserPersistDocumentParent::SetOnReady(nsIWebBrowserPersistDocumentReceiver* aOnReady)
{
MOZ_ASSERT(aOnReady);
MOZ_ASSERT(!mOnReady);
MOZ_ASSERT(!mReflection);
mOnReady = aOnReady;
}
void
WebBrowserPersistDocumentParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (mReflection) {
mReflection->ActorDestroy();
mReflection = nullptr;
}
if (mOnReady) {
mOnReady->OnError(NS_ERROR_FAILURE);
mOnReady = nullptr;
}
}
WebBrowserPersistDocumentParent::~WebBrowserPersistDocumentParent()
{
MOZ_RELEASE_ASSERT(!mReflection);
MOZ_ASSERT(!mOnReady);
}
bool
WebBrowserPersistDocumentParent::RecvAttributes(const Attrs& aAttrs,
const OptionalInputStreamParams& aPostData,
nsTArray<FileDescriptor>&& aPostFiles)
{
// Deserialize the postData unconditionally so that fds aren't leaked.
nsCOMPtr<nsIInputStream> postData =
ipc::DeserializeInputStream(aPostData, aPostFiles);
if (!mOnReady || mReflection) {
return false;
}
mReflection = new WebBrowserPersistRemoteDocument(this, aAttrs, postData);
nsRefPtr<WebBrowserPersistRemoteDocument> reflection = mReflection;
mOnReady->OnDocumentReady(reflection);
mOnReady = nullptr;
return true;
}
bool
WebBrowserPersistDocumentParent::RecvInitFailure(const nsresult& aFailure)
{
if (!mOnReady || mReflection) {
return false;
}
mOnReady->OnError(aFailure);
mOnReady = nullptr;
// Warning: Send__delete__ deallocates this object.
return Send__delete__(this);
}
PWebBrowserPersistResourcesParent*
WebBrowserPersistDocumentParent::AllocPWebBrowserPersistResourcesParent()
{
MOZ_CRASH("Don't use this; construct the actor directly and AddRef.");
return nullptr;
}
bool
WebBrowserPersistDocumentParent::DeallocPWebBrowserPersistResourcesParent(PWebBrowserPersistResourcesParent* aActor)
{
// Turn the ref held by IPC back into an nsRefPtr.
nsRefPtr<WebBrowserPersistResourcesParent> actor =
already_AddRefed<WebBrowserPersistResourcesParent>(
static_cast<WebBrowserPersistResourcesParent*>(aActor));
return true;
}
PWebBrowserPersistSerializeParent*
WebBrowserPersistDocumentParent::AllocPWebBrowserPersistSerializeParent(
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn)
{
MOZ_CRASH("Don't use this; construct the actor directly.");
return nullptr;
}
bool
WebBrowserPersistDocumentParent::DeallocPWebBrowserPersistSerializeParent(PWebBrowserPersistSerializeParent* aActor)
{
delete aActor;
return true;
}
} // namespace mozilla

View File

@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef WebBrowserPersistDocumentParent_h__
#define WebBrowserPersistDocumentParent_h__
#include "mozilla/Maybe.h"
#include "mozilla/PWebBrowserPersistDocumentParent.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
// This class is the IPC half of the glue between the
// nsIWebBrowserPersistDocument interface and a remote document. When
// (and if) it receives the Attributes message it constructs an
// WebBrowserPersistRemoteDocument and releases it into the XPCOM
// universe; otherwise, it invokes the document receiver's error
// callback.
//
// This object's lifetime is the normal IPC lifetime; on destruction,
// it calls its XPCOM reflection (if it exists yet) to remove that
// reference. Normal deletion occurs when the XPCOM object is being
// destroyed or after an InitFailure is received and handled.
//
// See also: TabParent::StartPersistence.
namespace mozilla {
class WebBrowserPersistRemoteDocument;
class WebBrowserPersistDocumentParent final
: public PWebBrowserPersistDocumentParent
{
public:
WebBrowserPersistDocumentParent();
virtual ~WebBrowserPersistDocumentParent();
// Set a callback to be invoked when the actor leaves the START
// state. This method must be called exactly once while the actor
// is still in the START state (or is unconstructed).
void SetOnReady(nsIWebBrowserPersistDocumentReceiver* aOnReady);
using Attrs = WebBrowserPersistDocumentAttrs;
// IPDL methods:
virtual bool
RecvAttributes(const Attrs& aAttrs,
const OptionalInputStreamParams& aPostData,
nsTArray<FileDescriptor>&& aPostFiles) override;
virtual bool
RecvInitFailure(const nsresult& aFailure) override;
virtual PWebBrowserPersistResourcesParent*
AllocPWebBrowserPersistResourcesParent() override;
virtual bool
DeallocPWebBrowserPersistResourcesParent(PWebBrowserPersistResourcesParent* aActor) override;
virtual PWebBrowserPersistSerializeParent*
AllocPWebBrowserPersistSerializeParent(
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn) override;
virtual bool
DeallocPWebBrowserPersistSerializeParent(PWebBrowserPersistSerializeParent* aActor) override;
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
private:
// This is reset to nullptr when the callback is invoked.
nsCOMPtr<nsIWebBrowserPersistDocumentReceiver> mOnReady;
WebBrowserPersistRemoteDocument* mReflection;
};
} // namespace mozilla
#endif // WebBrowserPersistDocumentParent_h__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef WebBrowserPersistLocalDocument_h__
#define WebBrowserPersistLocalDocument_h__
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDocument.h"
#include "nsIURI.h"
#include "nsIWebBrowserPersistDocument.h"
class nsIDocumentEncoder;
class nsISHEntry;
namespace mozilla {
class WebBrowserPersistLocalDocument final
: public nsIWebBrowserPersistDocument
{
public:
explicit WebBrowserPersistLocalDocument(nsIDocument* aDocument);
const nsCString& GetCharacterSet() const;
uint32_t GetPersistFlags() const;
already_AddRefed<nsIURI> GetBaseURI() const;
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIWEBBROWSERPERSISTDOCUMENT
NS_DECL_CYCLE_COLLECTION_CLASS(WebBrowserPersistLocalDocument)
private:
nsCOMPtr<nsIDocument> mDocument;
uint32_t mPersistFlags;
void DecideContentType(nsACString& aContentType);
nsresult GetDocEncoder(const nsACString& aContentType,
uint32_t aEncoderFlags,
nsIDocumentEncoder** aEncoder);
nsresult GetHistory(nsISHEntry** aHistory);
virtual ~WebBrowserPersistLocalDocument();
};
} // namespace mozilla
#endif // WebBrowserPersistLocalDocument_h__

View File

@ -0,0 +1,186 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 "WebBrowserPersistRemoteDocument.h"
#include "WebBrowserPersistDocumentParent.h"
#include "WebBrowserPersistResourcesParent.h"
#include "WebBrowserPersistSerializeParent.h"
#include "mozilla/unused.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistRemoteDocument,
nsIWebBrowserPersistDocument)
WebBrowserPersistRemoteDocument
::WebBrowserPersistRemoteDocument(WebBrowserPersistDocumentParent* aActor,
const Attrs& aAttrs,
nsIInputStream* aPostData)
: mActor(aActor)
, mAttrs(aAttrs)
, mPostData(aPostData)
{
}
WebBrowserPersistRemoteDocument::~WebBrowserPersistRemoteDocument()
{
if (mActor) {
unused << mActor->Send__delete__(mActor);
// That will call mActor->ActorDestroy, which calls this->ActorDestroy
// (whether or not the IPC send succeeds).
}
MOZ_ASSERT(!mActor);
}
void
WebBrowserPersistRemoteDocument::ActorDestroy(void)
{
mActor = nullptr;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetIsPrivate(bool* aIsPrivate)
{
*aIsPrivate = mAttrs.isPrivate();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetDocumentURI(nsACString& aURISpec)
{
aURISpec = mAttrs.documentURI();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetBaseURI(nsACString& aURISpec)
{
aURISpec = mAttrs.baseURI();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetContentType(nsACString& aContentType)
{
aContentType = mAttrs.contentType();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetCharacterSet(nsACString& aCharSet)
{
aCharSet = mAttrs.characterSet();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetTitle(nsAString& aTitle)
{
aTitle = mAttrs.title();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetReferrer(nsAString& aReferrer)
{
aReferrer = mAttrs.referrer();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetContentDisposition(nsAString& aDisp)
{
aDisp = mAttrs.contentDisposition();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetCacheKey(uint32_t* aCacheKey)
{
*aCacheKey = mAttrs.cacheKey();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetPersistFlags(uint32_t* aFlags)
{
*aFlags = mAttrs.persistFlags();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::SetPersistFlags(uint32_t aFlags)
{
if (!mActor) {
return NS_ERROR_FAILURE;
}
if (!mActor->SendSetPersistFlags(aFlags)) {
return NS_ERROR_FAILURE;
}
mAttrs.persistFlags() = aFlags;
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetPostData(nsIInputStream** aStream)
{
nsCOMPtr<nsIInputStream> stream = mPostData;
stream.forget(aStream);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::ReadResources(nsIWebBrowserPersistResourceVisitor* aVisitor)
{
if (!mActor) {
return NS_ERROR_FAILURE;
}
nsRefPtr<WebBrowserPersistResourcesParent> subActor =
new WebBrowserPersistResourcesParent(this, aVisitor);
return mActor->SendPWebBrowserPersistResourcesConstructor(
subActor.forget().take())
? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::WriteContent(
nsIOutputStream* aStream,
nsIWebBrowserPersistURIMap* aMap,
const nsACString& aRequestedContentType,
uint32_t aEncoderFlags,
uint32_t aWrapColumn,
nsIWebBrowserPersistWriteCompletion* aCompletion)
{
if (!mActor) {
return NS_ERROR_FAILURE;
}
nsresult rv;
WebBrowserPersistURIMap map;
uint32_t numMappedURIs;
if (aMap) {
rv = aMap->GetTargetBaseURI(map.targetBaseURI());
NS_ENSURE_SUCCESS(rv, rv);
rv = aMap->GetNumMappedURIs(&numMappedURIs);
NS_ENSURE_SUCCESS(rv, rv);
for (uint32_t i = 0; i < numMappedURIs; ++i) {
WebBrowserPersistURIMapEntry& nextEntry =
*(map.mapURIs().AppendElement());
rv = aMap->GetURIMapping(i, nextEntry.mapFrom(), nextEntry.mapTo());
NS_ENSURE_SUCCESS(rv, rv);
}
}
auto* subActor = new WebBrowserPersistSerializeParent(this,
aStream,
aCompletion);
nsCString requestedContentType(aRequestedContentType); // Sigh.
return mActor->SendPWebBrowserPersistSerializeConstructor(
subActor, map, requestedContentType, aEncoderFlags, aWrapColumn)
? NS_OK : NS_ERROR_FAILURE;
}
} // namespace mozilla

View File

@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef WebBrowserPersistRemoteDocument_h__
#define WebBrowserPersistRemoteDocument_h__
#include "mozilla/Maybe.h"
#include "mozilla/PWebBrowserPersistDocumentParent.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
#include "nsIInputStream.h"
// This class is the XPCOM half of the glue between the
// nsIWebBrowserPersistDocument interface and a remote document; it is
// created by WebBrowserPersistDocumentParent when (and if) it
// receives the information needed to populate the interface's
// properties.
//
// This object has a normal refcounted lifetime. The corresponding
// IPC actor holds a weak reference to this class; when the last
// strong reference is released, it sends an IPC delete message and
// thereby removes that reference.
namespace mozilla {
class WebBrowserPersistDocumentParent;
class WebBrowserPersistRemoteDocument final
: public nsIWebBrowserPersistDocument
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBBROWSERPERSISTDOCUMENT
private:
using Attrs = WebBrowserPersistDocumentAttrs;
WebBrowserPersistDocumentParent* mActor;
Attrs mAttrs;
nsCOMPtr<nsIInputStream> mPostData;
friend class WebBrowserPersistDocumentParent;
WebBrowserPersistRemoteDocument(WebBrowserPersistDocumentParent* aActor,
const Attrs& aAttrs,
nsIInputStream* aPostData);
~WebBrowserPersistRemoteDocument();
void ActorDestroy(void);
};
} // namespace mozilla
#endif // WebBrowserPersistRemoteDocument_h__

View File

@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 "WebBrowserPersistResourcesChild.h"
#include "WebBrowserPersistDocumentChild.h"
#include "mozilla/dom/PBrowserChild.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistResourcesChild,
nsIWebBrowserPersistResourceVisitor)
WebBrowserPersistResourcesChild::WebBrowserPersistResourcesChild()
{
}
WebBrowserPersistResourcesChild::~WebBrowserPersistResourcesChild()
{
}
NS_IMETHODIMP
WebBrowserPersistResourcesChild::VisitResource(nsIWebBrowserPersistDocument *aDocument,
const nsACString& aURI)
{
nsCString copiedURI(aURI); // Yay, XPIDL/IPDL mismatch.
SendVisitResource(copiedURI);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistResourcesChild::VisitDocument(nsIWebBrowserPersistDocument* aDocument,
nsIWebBrowserPersistDocument* aSubDocument)
{
auto* subActor = new WebBrowserPersistDocumentChild();
dom::PBrowserChild* grandManager = Manager()->Manager();
if (!grandManager->SendPWebBrowserPersistDocumentConstructor(subActor)) {
// NOTE: subActor is freed at this point.
return NS_ERROR_FAILURE;
}
// ...but here, IPC won't free subActor until after this returns
// to the event loop.
// The order of these two messages will be preserved, because
// they're the same toplevel protocol and priority.
//
// With this ordering, it's always the transition out of START
// state that causes a document's parent actor to be exposed to
// XPCOM (for both parent->child and child->parent construction),
// which simplifies the lifetime management.
SendVisitDocument(subActor);
subActor->Start(aSubDocument);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistResourcesChild::EndVisit(nsIWebBrowserPersistDocument *aDocument,
nsresult aStatus)
{
Send__delete__(this, aStatus);
return NS_OK;
}
} // namespace mozilla

View File

@ -0,0 +1,31 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef WebBrowserPersistResourcesChild_h__
#define WebBrowserPersistResourcesChild_h__
#include "mozilla/PWebBrowserPersistResourcesChild.h"
#include "nsIWebBrowserPersistDocument.h"
namespace mozilla {
class WebBrowserPersistResourcesChild final
: public PWebBrowserPersistResourcesChild
, public nsIWebBrowserPersistResourceVisitor
{
public:
WebBrowserPersistResourcesChild();
NS_DECL_NSIWEBBROWSERPERSISTRESOURCEVISITOR
NS_DECL_ISUPPORTS
private:
virtual ~WebBrowserPersistResourcesChild();
};
} // namespace mozilla
#endif // WebBrowserPersistDocumentChild_h__

View File

@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 "WebBrowserPersistResourcesParent.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistResourcesParent,
nsIWebBrowserPersistDocumentReceiver)
WebBrowserPersistResourcesParent::WebBrowserPersistResourcesParent(
nsIWebBrowserPersistDocument* aDocument,
nsIWebBrowserPersistResourceVisitor* aVisitor)
: mDocument(aDocument)
, mVisitor(aVisitor)
{
MOZ_ASSERT(aDocument);
MOZ_ASSERT(aVisitor);
}
WebBrowserPersistResourcesParent::~WebBrowserPersistResourcesParent()
{
}
void
WebBrowserPersistResourcesParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (aWhy != Deletion && mVisitor) {
mVisitor->EndVisit(mDocument, NS_ERROR_FAILURE);
}
mVisitor = nullptr;
}
bool
WebBrowserPersistResourcesParent::Recv__delete__(const nsresult& aStatus)
{
mVisitor->EndVisit(mDocument, aStatus);
mVisitor = nullptr;
return true;
}
bool
WebBrowserPersistResourcesParent::RecvVisitResource(const nsCString& aURI)
{
mVisitor->VisitResource(mDocument, aURI);
return true;
}
bool
WebBrowserPersistResourcesParent::RecvVisitDocument(PWebBrowserPersistDocumentParent* aSubDocument)
{
// Don't expose the subdocument to the visitor until it's ready
// (until the actor isn't in START state).
static_cast<WebBrowserPersistDocumentParent*>(aSubDocument)
->SetOnReady(this);
return true;
}
NS_IMETHODIMP
WebBrowserPersistResourcesParent::OnDocumentReady(nsIWebBrowserPersistDocument* aSubDocument)
{
if (!mVisitor) {
return NS_ERROR_FAILURE;
}
mVisitor->VisitDocument(mDocument, aSubDocument);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistResourcesParent::OnError(nsresult aFailure)
{
// Nothing useful to do but ignore the failed document.
return NS_OK;
}
} // namespace mozilla

View File

@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef WebBrowserPersistResourcesParent_h__
#define WebBrowserPersistResourcesParent_h__
#include "mozilla/PWebBrowserPersistResourcesParent.h"
#include "WebBrowserPersistDocumentParent.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
namespace mozilla {
class WebBrowserPersistResourcesParent final
: public PWebBrowserPersistResourcesParent
, public nsIWebBrowserPersistDocumentReceiver
{
public:
WebBrowserPersistResourcesParent(nsIWebBrowserPersistDocument* aDocument,
nsIWebBrowserPersistResourceVisitor* aVisitor);
virtual bool
RecvVisitResource(const nsCString& aURI) override;
virtual bool
RecvVisitDocument(PWebBrowserPersistDocumentParent* aSubDocument) override;
virtual bool
Recv__delete__(const nsresult& aStatus) override;
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
NS_DECL_NSIWEBBROWSERPERSISTDOCUMENTRECEIVER
NS_DECL_ISUPPORTS
private:
// Note: even if the XPIDL didn't need mDocument for visitor
// callbacks, this object still needs to hold a strong reference
// to it to defer actor subtree deletion until after the
// visitation is finished.
nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
nsCOMPtr<nsIWebBrowserPersistResourceVisitor> mVisitor;
virtual ~WebBrowserPersistResourcesParent();
};
} // namespace mozilla
#endif // WebBrowserPersistResourcesParent_h__

View File

@ -0,0 +1,145 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 "WebBrowserPersistSerializeChild.h"
#include <algorithm>
#include "nsThreadUtils.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistSerializeChild,
nsIWebBrowserPersistWriteCompletion,
nsIWebBrowserPersistURIMap,
nsIOutputStream)
WebBrowserPersistSerializeChild::WebBrowserPersistSerializeChild(const WebBrowserPersistURIMap& aMap)
: mMap(aMap)
{
}
WebBrowserPersistSerializeChild::~WebBrowserPersistSerializeChild()
{
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::OnFinish(nsIWebBrowserPersistDocument* aDocument,
nsIOutputStream* aStream,
const nsACString& aContentType,
nsresult aStatus)
{
MOZ_ASSERT(aStream == this);
nsCString contentType(aContentType);
Send__delete__(this, contentType, aStatus);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::GetNumMappedURIs(uint32_t* aNum)
{
*aNum = static_cast<uint32_t>(mMap.mapURIs().Length());
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::GetURIMapping(uint32_t aIndex,
nsACString& aMapFrom,
nsACString& aMapTo)
{
if (aIndex >= mMap.mapURIs().Length()) {
return NS_ERROR_INVALID_ARG;
}
aMapFrom = mMap.mapURIs()[aIndex].mapFrom();
aMapTo = mMap.mapURIs()[aIndex].mapTo();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::GetTargetBaseURI(nsACString& aURI)
{
aURI = mMap.targetBaseURI();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::Close()
{
NS_WARNING("WebBrowserPersistSerializeChild::Close()");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::Flush()
{
NS_WARNING("WebBrowserPersistSerializeChild::Flush()");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::Write(const char* aBuf, uint32_t aCount,
uint32_t* aWritten)
{
// Normally an nsIOutputStream would have to be thread-safe, but
// nsDocumentEncoder currently doesn't call this off the main
// thread (which also means it's difficult to test the
// thread-safety code this class doesn't yet have).
//
// This is *not* an NS_ERROR_NOT_IMPLEMENTED, because at this
// point we've probably already misused the non-thread-safe
// refcounting.
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Fix this class to be thread-safe.");
// Limit the size of an individual IPC message.
static const uint32_t kMaxWrite = 65536;
// Work around bug 1181433 by sending multiple messages if
// necessary to write the entire aCount bytes, even though
// nsIOutputStream.idl says we're allowed to do a short write.
const char* buf = aBuf;
uint32_t count = aCount;
*aWritten = 0;
while (count > 0) {
uint32_t toWrite = std::min(kMaxWrite, count);
nsTArray<uint8_t> arrayBuf;
// It would be nice if this extra copy could be avoided.
arrayBuf.AppendElements(buf, toWrite);
SendWriteData(Move(arrayBuf));
*aWritten += toWrite;
buf += toWrite;
count -= toWrite;
}
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::WriteFrom(nsIInputStream* aFrom,
uint32_t aCount,
uint32_t* aWritten)
{
NS_WARNING("WebBrowserPersistSerializeChild::WriteFrom()");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::WriteSegments(nsReadSegmentFun aFun,
void* aCtx,
uint32_t aCount,
uint32_t* aWritten)
{
NS_WARNING("WebBrowserPersistSerializeChild::WriteSegments()");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::IsNonBlocking(bool* aNonBlocking)
{
// Writes will never fail with NS_BASE_STREAM_WOULD_BLOCK, so:
*aNonBlocking = false;
return NS_OK;
}
} // namespace mozilla

View File

@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef WebBrowserPersistSerializeChild_h__
#define WebBrowserPersistSerializeChild_h__
#include "mozilla/PWebBrowserPersistSerializeChild.h"
#include "mozilla/PWebBrowserPersistDocument.h"
#include "nsIWebBrowserPersistDocument.h"
#include "nsIOutputStream.h"
namespace mozilla {
class WebBrowserPersistSerializeChild final
: public PWebBrowserPersistSerializeChild
, public nsIWebBrowserPersistWriteCompletion
, public nsIWebBrowserPersistURIMap
, public nsIOutputStream
{
public:
explicit WebBrowserPersistSerializeChild(const WebBrowserPersistURIMap& aMap);
NS_DECL_NSIWEBBROWSERPERSISTWRITECOMPLETION
NS_DECL_NSIWEBBROWSERPERSISTURIMAP
NS_DECL_NSIOUTPUTSTREAM
NS_DECL_ISUPPORTS
private:
WebBrowserPersistURIMap mMap;
virtual ~WebBrowserPersistSerializeChild();
};
} // namespace mozilla
#endif // WebBrowserPersistSerializeChild_h__

View File

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 "WebBrowserPersistSerializeParent.h"
#include "nsReadableUtils.h"
namespace mozilla {
WebBrowserPersistSerializeParent::WebBrowserPersistSerializeParent(
nsIWebBrowserPersistDocument* aDocument,
nsIOutputStream* aStream,
nsIWebBrowserPersistWriteCompletion* aFinish)
: mDocument(aDocument)
, mStream(aStream)
, mFinish(aFinish)
, mOutputError(NS_OK)
{
MOZ_ASSERT(aDocument);
MOZ_ASSERT(aStream);
MOZ_ASSERT(aFinish);
}
WebBrowserPersistSerializeParent::~WebBrowserPersistSerializeParent()
{
}
bool
WebBrowserPersistSerializeParent::RecvWriteData(nsTArray<uint8_t>&& aData)
{
if (NS_FAILED(mOutputError)) {
return true;
}
uint32_t written = 0;
static_assert(sizeof(char) == sizeof(uint8_t),
"char must be (at least?) 8 bits");
const char* data = reinterpret_cast<const char*>(aData.Elements());
// nsIOutputStream::Write is allowed to return short writes.
while (written < aData.Length()) {
uint32_t writeReturn;
nsresult rv = mStream->Write(data + written,
aData.Length() - written,
&writeReturn);
if (NS_FAILED(rv)) {
mOutputError = rv;
return true;
}
written += writeReturn;
}
return true;
}
bool
WebBrowserPersistSerializeParent::Recv__delete__(const nsCString& aContentType,
const nsresult& aStatus)
{
if (NS_SUCCEEDED(mOutputError)) {
mOutputError = aStatus;
}
mFinish->OnFinish(mDocument,
mStream,
aContentType,
mOutputError);
mFinish = nullptr;
return true;
}
void
WebBrowserPersistSerializeParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (mFinish) {
MOZ_ASSERT(aWhy != Deletion);
mFinish->OnFinish(mDocument, mStream, EmptyCString(), NS_ERROR_FAILURE);
mFinish = nullptr;
}
}
} // namespace mozilla

View File

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef WebBrowserPersistSerializeParent_h__
#define WebBrowserPersistSerializeParent_h__
#include "mozilla/PWebBrowserPersistSerializeParent.h"
#include "nsCOMPtr.h"
#include "nsIOutputStream.h"
#include "nsIWebBrowserPersistDocument.h"
namespace mozilla {
class WebBrowserPersistSerializeParent
: public PWebBrowserPersistSerializeParent
{
public:
WebBrowserPersistSerializeParent(
nsIWebBrowserPersistDocument* aDocument,
nsIOutputStream* aStream,
nsIWebBrowserPersistWriteCompletion* aFinish);
virtual ~WebBrowserPersistSerializeParent();
virtual bool
RecvWriteData(nsTArray<uint8_t>&& aData) override;
virtual bool
Recv__delete__(const nsCString& aContentType,
const nsresult& aStatus) override;
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
private:
// See also ...ReadParent::mDocument for the other reason this
// strong reference needs to be here.
nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
nsCOMPtr<nsIOutputStream> mStream;
nsCOMPtr<nsIWebBrowserPersistWriteCompletion> mFinish;
nsresult mOutputError;
};
} // namespace mozilla
#endif // WebBrowserPersistSerializeParent_h__

View File

@ -7,16 +7,40 @@
XPIDL_SOURCES += [
'nsCWebBrowserPersist.idl',
'nsIWebBrowserPersist.idl',
'nsIWebBrowserPersistable.idl',
'nsIWebBrowserPersistDocument.idl',
]
XPIDL_MODULE = 'webbrowserpersist'
IPDL_SOURCES += [
'PWebBrowserPersistDocument.ipdl',
'PWebBrowserPersistResources.ipdl',
'PWebBrowserPersistSerialize.ipdl',
]
SOURCES += [
'nsWebBrowserPersist.cpp',
'WebBrowserPersistDocumentChild.cpp',
'WebBrowserPersistDocumentParent.cpp',
'WebBrowserPersistLocalDocument.cpp',
'WebBrowserPersistRemoteDocument.cpp',
'WebBrowserPersistResourcesChild.cpp',
'WebBrowserPersistResourcesParent.cpp',
'WebBrowserPersistSerializeChild.cpp',
'WebBrowserPersistSerializeParent.cpp',
]
EXPORTS.mozilla += [
'WebBrowserPersistDocumentChild.h',
'WebBrowserPersistDocumentParent.h',
'WebBrowserPersistLocalDocument.h',
]
FAIL_ON_WARNINGS = True
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/dom/base',

View File

@ -17,7 +17,7 @@ interface nsILoadContext;
/**
* Interface for persisting DOM documents and URIs to local or remote storage.
*/
[scriptable, uuid(effe7374-5c7d-4b1e-a96f-27b283df189b)]
[scriptable, uuid(8cd752a4-60b1-42c3-a819-65c7a1138a28)]
interface nsIWebBrowserPersist : nsICancelable
{
/** No special persistence behaviour. */
@ -248,7 +248,8 @@ interface nsIWebBrowserPersist : nsICancelable
*
* @param aDocument Document to save to file. Some implementations of
* this interface may also support <CODE>nullptr</CODE>
* to imply the currently loaded document.
* to imply the currently loaded document. Can be an
* nsIWebBrowserPersistDocument or nsIDOMDocument.
* @param aFile Target local file. This may be a nsIFile object or an
* nsIURI object with a file scheme or a scheme that
* supports uploading (e.g. ftp).
@ -264,12 +265,14 @@ interface nsIWebBrowserPersist : nsICancelable
* wrap text at. Parameter is ignored if wrapping is not
* specified by the encoding flags.
*
* @see nsIWebBrowserPersistDocument
* @see nsIWebBrowserPersistable
* @see nsIFile
* @see nsIURI
*
* @throws NS_ERROR_INVALID_ARG One or more arguments was invalid.
*/
void saveDocument(in nsIDOMDocument aDocument,
void saveDocument(in nsISupports aDocument,
in nsISupports aFile, in nsISupports aDataPath,
in string aOutputContentType, in unsigned long aEncodingFlags,
in unsigned long aWrapColumn);

View File

@ -0,0 +1,197 @@
/* -*- Mode: IDL; 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/. */
#include "nsISupports.idl"
interface nsIDOMDocument;
interface nsIInputStream;
interface nsIOutputStream;
interface nsITabParent;
interface nsIWebBrowserPersistResourceVisitor;
interface nsIWebBrowserPersistWriteCompletion;
/**
* Interface for the URI-mapping information that can be supplied when
* serializing the DOM of an nsIWebBrowserPersistDocument.
*
* @see nsIWebBrowserPersistDocument
*/
[scriptable, uuid(d52e8b93-2771-45e8-a5b0-6e12b667046b)]
interface nsIWebBrowserPersistURIMap : nsISupports
{
/**
* The number of URI mappings.
*/
readonly attribute unsigned long numMappedURIs;
/**
* Obtain the URI mapping at the given index, which must be less than
* numMappedURIs, as a pair of URI spec strings.
*/
void getURIMapping(in unsigned long aIndex,
out AUTF8String aMapFrom,
out AUTF8String aMapTo);
/**
* The spec of the base URI that the document will have after it is
* serialized.
*/
readonly attribute AUTF8String targetBaseURI;
};
/**
* Interface representing a document that can be serialized with
* nsIWebBrowserPersist; it may or may not be in this process. Some
* information is exposed as attributes, which may or may not reflect
* changes made to the underlying document; most of these are
* self-explanatory from their names and types.
*/
[scriptable, uuid(74aa4918-5d15-46b6-9ccf-74f9696d721d)]
interface nsIWebBrowserPersistDocument : nsISupports
{
readonly attribute boolean isPrivate;
readonly attribute AUTF8String documentURI;
readonly attribute AUTF8String baseURI;
readonly attribute ACString contentType;
readonly attribute ACString characterSet;
readonly attribute AString title;
readonly attribute AString referrer;
readonly attribute AString contentDisposition;
readonly attribute nsIInputStream postData;
/**
* The cache key. Unlike in nsISHEntry, where it's wrapped in an
* nsISupportsPRUint32, this is just the integer.
*/
readonly attribute unsigned long cacheKey;
/**
* This attribute is set by nsIWebBrowserPersist implementations to
* propagate persist flags that apply to the DOM traversal and
* serialization (rather than to managing file I/O).
*/
attribute unsigned long persistFlags;
/**
* Walk the DOM searching for external resources needed to render it.
* The visitor callbacks may be called either before or after
* readResources returns.
*
* @see nsIWebBrowserPersistResourceVisitor
*/
void readResources(in nsIWebBrowserPersistResourceVisitor aVisitor);
/**
* Serialize the document's DOM.
*
* @param aStream The output stream to write the document to.
*
* @param aURIMap Optional; specifies URI rewriting to perform on
* external references (as read by readResources).
* If given, also causes relative hyperlinks to be
* converted to absolute in the written text.
*
* @param aRequestedContentType
* The desired MIME type to save the document as;
* optional and defaults to the document's type.
* (If no encoder exists for that type, "text/html"
* is used instead.)
*
* @param aEncoderFlags Flags to pass to the encoder.
*
* @param aWrapColumn Desired text width, ignored if wrapping is not
* specified by the encoding flags, or if 0.
*
* @param aCompletion Callback invoked when writing is complete.
* It may be called either before or after writeContent
* returns.
*
* @see nsIDocumentEncoder
*/
void writeContent(in nsIOutputStream aStream,
in nsIWebBrowserPersistURIMap aURIMap,
in ACString aRequestedContentType,
in unsigned long aEncoderFlags,
in unsigned long aWrapColumn,
in nsIWebBrowserPersistWriteCompletion aCompletion);
};
/**
* Asynchronous visitor that receives external resources linked by an
* nsIWebBrowserPersistDocument and which are needed to render the
* document.
*/
[scriptable, uuid(8ce37706-b7d3-481a-be68-54f174fc0d0a)]
interface nsIWebBrowserPersistResourceVisitor : nsISupports
{
/**
* Indicates a resource that is not a document; e.g., an image, script,
* or stylesheet.
*
* @param aDocument The document containing the reference.
* @param aURI The absolute URI spec for the referenced resource.
*/
void visitResource(in nsIWebBrowserPersistDocument aDocument,
in AUTF8String aURI);
/**
* Indicates a subdocument resource; e.g., a frame or iframe.
*
* @param aDocument The document containing the reference.
* @param aSubDocument The referenced document.
*/
void visitDocument(in nsIWebBrowserPersistDocument aDocument,
in nsIWebBrowserPersistDocument aSubDocument);
/**
* Indicates that the document traversal is complete.
*
* @param aDocument The document that was being traversed.
* @param aStatus Indicates whether the traversal encountered an error.
*/
void endVisit(in nsIWebBrowserPersistDocument aDocument,
in nsresult aStatus);
};
/**
* Asynchronous callback for when nsIWebBrowserPersistDocument is finished
* serializing the document's DOM.
*/
[scriptable, function, uuid(a07e6892-38ae-4207-8340-7fa6ec446ed6)]
interface nsIWebBrowserPersistWriteCompletion : nsISupports
{
/**
* Indicates that serialization is finished.
*
* @param aDocument The document that was being serialized.
*
* @param aStream The stream that was being written to. If it
* needs to be closed, the callback must do that;
* the serialization process leaves it open.
*
* @param aContentType The content type with which the document was
* actually serialized; this may be useful to set
* metadata on the result, or if uploading it.
*
* @param aStatus Indicates whether serialization encountered an error.
*/
void onFinish(in nsIWebBrowserPersistDocument aDocument,
in nsIOutputStream aStream,
in ACString aContentType,
in nsresult aStatus);
};
/**
* Asynchronous callback for creating a persistable document from some
* other object.
*
* @see nsIWebBrowserPersistable.
*/
[scriptable, uuid(321e3174-594f-4036-b7be-791b821bd376)]
interface nsIWebBrowserPersistDocumentReceiver : nsISupports
{
void onDocumentReady(in nsIWebBrowserPersistDocument aDocument);
void onError(in nsresult aFailure);
};

View File

@ -0,0 +1,30 @@
/* -*- Mode: IDL; 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/. */
#include "nsISupports.idl"
interface nsIWebBrowserPersistDocumentReceiver;
/**
* Interface for objects which represent a document that can be
* serialized with nsIWebBrowserPersist. This interface is
* asynchronous because the actual document can be in another process
* (e.g., if this object is an nsFrameLoader for an out-of-process
* frame).
*
* Warning: this is currently implemented only by nsFrameLoader, and
* may change in the future to become more frame-loader-specific or be
* merged into nsIFrameLoader. See bug 1101100 comment #34.
*
* @see nsIWebBrowserPersistDocumentReceiver
* @see nsIWebBrowserPersistDocument
* @see nsIWebBrowserPersist
*/
[scriptable, function, uuid(24d0dc9e-b970-4cca-898f-cbba03abaa73)]
interface nsIWebBrowserPersistable : nsISupports
{
void startPersistence(in nsIWebBrowserPersistDocumentReceiver aRecv);
};

File diff suppressed because it is too large Load Diff

View File

@ -22,27 +22,23 @@
#include "nsIProgressEventSink.h"
#include "nsIFile.h"
#include "nsIWebProgressListener2.h"
#include "nsIWebBrowserPersistDocument.h"
#include "mozilla/UniquePtr.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "nsTArray.h"
#include "nsCWebBrowserPersist.h"
class nsEncoderNodeFixup;
class nsIStorageStream;
class nsIWebBrowserPersistDocument;
struct CleanupData;
struct DocData;
struct OutputData;
struct UploadData;
struct URIData;
class nsWebBrowserPersist : public nsIInterfaceRequestor,
public nsIWebBrowserPersist,
public nsIStreamListener,
public nsIProgressEventSink,
public nsSupportsWeakReference
class nsWebBrowserPersist final : public nsIInterfaceRequestor,
public nsIWebBrowserPersist,
public nsIStreamListener,
public nsIProgressEventSink,
public nsSupportsWeakReference
{
friend class nsEncoderNodeFixup;
@ -58,11 +54,9 @@ public:
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIPROGRESSEVENTSINK
// Protected members
protected:
// Private members
private:
virtual ~nsWebBrowserPersist();
nsresult CloneNodeWithFixedUpAttributes(
nsIDOMNode *aNodeIn, bool *aSerializeCloneKids, nsIDOMNode **aNodeOut);
nsresult SaveURIInternal(
nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer,
uint32_t aReferrerPolicy, nsIInputStream *aPostData,
@ -71,22 +65,33 @@ protected:
nsresult SaveChannelInternal(
nsIChannel *aChannel, nsIURI *aFile, bool aCalcFileExt);
nsresult SaveDocumentInternal(
nsIDOMDocument *aDocument, nsIURI *aFile, nsIURI *aDataPath);
nsIWebBrowserPersistDocument *aDocument,
nsIURI *aFile,
nsIURI *aDataPath);
nsresult SaveDocuments();
nsresult GetDocEncoderContentType(
nsIDOMDocument *aDocument, const char16_t *aContentType,
char16_t **aRealContentType);
void FinishSaveDocumentInternal(nsIURI* aFile, nsIFile* aDataPath);
nsresult GetExtensionForContentType(
const char16_t *aContentType, char16_t **aExt);
nsresult GetDocumentExtension(nsIDOMDocument *aDocument, char16_t **aExt);
// Private members
private:
struct CleanupData;
struct DocData;
struct OutputData;
struct UploadData;
struct URIData;
struct WalkData;
class OnWalk;
class OnWrite;
class FlatURIMap;
friend class OnWalk;
friend class OnWrite;
nsresult SaveDocumentDeferred(mozilla::UniquePtr<WalkData>&& aData);
void Cleanup();
void CleanupLocalFiles();
nsresult GetValidURIFromObject(nsISupports *aObject, nsIURI **aURI) const;
nsresult GetLocalFileFromURI(nsIURI *aURI, nsIFile **aLocalFile) const;
nsresult AppendPathToURI(nsIURI *aURI, const nsAString & aPath) const;
static nsresult AppendPathToURI(nsIURI *aURI, const nsAString & aPath);
nsresult MakeAndStoreLocalFilenameInURIMap(
nsIURI *aURI, bool aNeedsPersisting, URIData **aData);
nsresult MakeOutputStream(
@ -112,46 +117,20 @@ private:
nsIURI *aURI,
bool aNeedsPersisting = true,
URIData **aData = nullptr);
nsresult StoreURIAttributeNS(
nsIDOMNode *aNode, const char *aNamespaceURI, const char *aAttribute,
bool aNeedsPersisting = true,
URIData **aData = nullptr);
nsresult StoreURIAttribute(
nsIDOMNode *aNode, const char *aAttribute,
bool aNeedsPersisting = true,
URIData **aData = nullptr)
{
return StoreURIAttributeNS(aNode, "", aAttribute, aNeedsPersisting, aData);
}
bool DocumentEncoderExists(const char16_t *aContentType);
bool DocumentEncoderExists(const char *aContentType);
nsresult GetNodeToFixup(nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut);
nsresult FixupURI(nsAString &aURI);
nsresult FixupNodeAttributeNS(nsIDOMNode *aNode, const char *aNamespaceURI, const char *aAttribute);
nsresult FixupNodeAttribute(nsIDOMNode *aNode, const char *aAttribute)
{
return FixupNodeAttributeNS(aNode, "", aAttribute);
}
nsresult FixupAnchor(nsIDOMNode *aNode);
nsresult FixupXMLStyleSheetLink(nsIDOMProcessingInstruction *aPI, const nsAString &aHref);
nsresult GetXMLStyleSheetLink(nsIDOMProcessingInstruction *aPI, nsAString &aHref);
nsresult StoreAndFixupStyleSheet(nsIStyleSheet *aStyleSheet);
nsresult SaveDocumentWithFixup(
nsIDOMDocument *pDocument,
nsIURI *aFile, bool aReplaceExisting, const nsACString &aFormatType,
const nsCString &aSaveCharset, uint32_t aFlags);
nsresult SaveSubframeContent(
nsIDOMDocument *aFrameContent, URIData *aData);
nsIWebBrowserPersistDocument *aFrameContent,
const nsCString& aURISpec,
URIData *aData);
nsresult SendErrorStatusChange(
bool aIsReadError, nsresult aResult, nsIRequest *aRequest, nsIURI *aURI);
nsresult OnWalkDOMNode(nsIDOMNode *aNode);
nsresult FixRedirectedChannelEntry(nsIChannel *aNewChannel);
void EndDownload(nsresult aResult = NS_OK);
nsresult SaveGatheredURIs(nsIURI *aFileAsURI);
bool SerializeNextFile();
void EndDownload(nsresult aResult);
void FinishDownload();
void SerializeNextFile();
void CalcTotalProgress();
void SetApplyConversionIfNeeded(nsIChannel *aChannel);
@ -171,6 +150,8 @@ private:
nsISupports *aKey, OutputData *aData, void* aClosure);
static PLDHashOperator EnumCountURIsToPersist(
const nsACString &aKey, URIData *aData, void* aClosure);
static PLDHashOperator EnumCopyURIsToFlatMap(
const nsACString &aKey, URIData *aData, void* aClosure);
nsCOMPtr<nsIURI> mCurrentDataPath;
bool mCurrentDataPathIsRelative;
@ -193,12 +174,14 @@ private:
nsClassHashtable<nsISupportsHashKey, OutputData> mOutputMap;
nsClassHashtable<nsISupportsHashKey, UploadData> mUploadList;
nsClassHashtable<nsCStringHashKey, URIData> mURIMap;
nsCOMPtr<nsIWebBrowserPersistURIMap> mFlatURIMap;
nsTArray<mozilla::UniquePtr<WalkData>> mWalkStack;
nsTArray<DocData*> mDocList;
nsTArray<CleanupData*> mCleanupList;
nsTArray<nsCString> mFilenameList;
bool mFirstAndOnlyUse;
bool mSavingDocument;
bool mCancel;
bool mJustStartedLoading;
bool mCompleted;
bool mStartSaving;
bool mReplaceExisting;
@ -213,19 +196,4 @@ private:
nsString mContentType;
};
// Helper class does node fixup during persistence
class nsEncoderNodeFixup : public nsIDocumentEncoderNodeFixup
{
public:
nsEncoderNodeFixup();
NS_DECL_ISUPPORTS
NS_IMETHOD FixupNode(nsIDOMNode *aNode, bool *aSerializeCloneKids, nsIDOMNode **aOutNode) override;
nsWebBrowserPersist *mWebBrowserPersist;
protected:
virtual ~nsEncoderNodeFixup();
};
#endif

View File

@ -126,46 +126,91 @@ function saveImageURL(aURL, aFileName, aFilePickerTitleKey, aShouldBypassCache,
aDoc, aSkipPrompt, null);
}
// This is like saveDocument, but takes any browser/frame-like element
// (nsIFrameLoaderOwner) and saves the current document inside it,
// whether in-process or out-of-process.
function saveBrowser(aBrowser, aSkipPrompt)
{
if (!aBrowser) {
throw "Must have a browser when calling saveBrowser";
}
let persistable = aBrowser.QueryInterface(Ci.nsIFrameLoaderOwner)
.frameLoader
.QueryInterface(Ci.nsIWebBrowserPersistable);
persistable.startPersistence({
onDocumentReady: function (document) {
saveDocument(document, aSkipPrompt);
}
// This interface also has an |onError| method which takes an
// nsresult, but in case of asynchronous failure there isn't
// really anything useful that can be done here.
});
}
// Saves a document; aDocument can be an nsIWebBrowserPersistDocument
// (see saveBrowser, above) or an nsIDOMDocument.
//
// aDocument can also be a CPOW for a remote nsIDOMDocument, in which
// case "save as" modes that serialize the document's DOM are
// unavailable. This is a temporary measure for the "Save Frame As"
// command (bug 1141337), and it's possible that there could be
// add-ons doing something similar.
function saveDocument(aDocument, aSkipPrompt)
{
const Ci = Components.interfaces;
if (!aDocument)
throw "Must have a document when calling saveDocument";
// We want to use cached data because the document is currently visible.
var ifreq =
aDocument.defaultView
.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
let contentDisposition = null;
let cacheKeyInt = null;
var contentDisposition = null;
try {
contentDisposition =
ifreq.getInterface(Components.interfaces.nsIDOMWindowUtils)
.getDocumentMetadata("content-disposition");
} catch (ex) {
// Failure to get a content-disposition is ok
if (aDocument instanceof Ci.nsIWebBrowserPersistDocument) {
// nsIWebBrowserPersistDocument exposes these directly.
contentDisposition = aDocument.contentDisposition;
cacheKeyInt = aDocument.cacheKey;
} else if (aDocument instanceof Ci.nsIDOMDocument) {
// Otherwise it's an actual nsDocument (and possibly a CPOW).
// We want to use cached data because the document is currently visible.
let ifreq =
aDocument.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor);
try {
contentDisposition =
ifreq.getInterface(Ci.nsIDOMWindowUtils)
.getDocumentMetadata("content-disposition");
} catch (ex) {
// Failure to get a content-disposition is ok
}
try {
let shEntry =
ifreq.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIWebPageDescriptor)
.currentDescriptor
.QueryInterface(Ci.nsISHEntry);
let cacheKey = shEntry.cacheKey
.QueryInterface(Ci.nsISupportsPRUint32)
.data;
// cacheKey might be a CPOW, which can't be passed to native
// code, but the data attribute is just a number.
cacheKeyInt = cacheKey.data;
} catch (ex) {
// We might not find it in the cache. Oh, well.
}
}
// Convert the cacheKey back into an XPCOM object.
let cacheKey = null;
try {
let shEntry =
ifreq.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIWebPageDescriptor)
.currentDescriptor
.QueryInterface(Components.interfaces.nsISHEntry);
shEntry.cacheKey.QueryInterface(Components.interfaces.nsISupportsPRUint32);
// In the event that the cacheKey is a CPOW, we cannot pass it to
// nsIWebBrowserPersist, so we create a new one and copy the value
// over. This is a workaround until bug 1101100 is fixed.
if (cacheKeyInt) {
cacheKey = Cc["@mozilla.org/supports-PRUint32;1"]
.createInstance(Ci.nsISupportsPRUint32);
cacheKey.data = shEntry.cacheKey.data;
} catch (ex) {
// We might not find it in the cache. Oh, well.
.createInstance(Ci.nsISupportsPRUint32);
cacheKey.data = cacheKeyInt;
}
internalSave(aDocument.location.href, aDocument, null, contentDisposition,
internalSave(aDocument.documentURI, aDocument, null, contentDisposition,
aDocument.contentType, false, null, null,
aDocument.referrer ? makeURI(aDocument.referrer) : null,
aDocument, aSkipPrompt, cacheKey);
@ -353,6 +398,13 @@ function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
let nonCPOWDocument =
aDocument && !Components.utils.isCrossProcessWrapper(aDocument);
let isPrivate = aIsContentWindowPrivate;
if (isPrivate === undefined) {
isPrivate = aInitiatingDocument instanceof Components.interfaces.nsIDOMDocument
? PrivateBrowsingUtils.isContentWindowPrivate(aInitiatingDocument.defaultView)
: aInitiatingDocument.isPrivate;
}
var persistArgs = {
sourceURI : sourceURI,
sourceReferrer : aReferrer,
@ -362,8 +414,7 @@ function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
sourceCacheKey : aCacheKey,
sourcePostData : nonCPOWDocument ? getPostData(aDocument) : null,
bypassCache : aShouldBypassCache,
initiatingWindow : aInitiatingDocument && aInitiatingDocument.defaultView,
isContentWindowPrivate : aIsContentWindowPrivate
isPrivate : isPrivate,
};
// Start the actual save process
@ -398,12 +449,8 @@ function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
* "text/plain" is meaningful.
* @param persistArgs.bypassCache
* If true, the document will always be refetched from the server
* @param persistArgs.initiatingWindow [optional]
* The window from which the save operation was initiated.
* If this is omitted then isContentWindowPrivate has to be provided.
* @param persistArgs.isContentWindowPrivate [optional]
* If present then isPrivate is set to this value without using
* persistArgs.initiatingWindow.
* @param persistArgs.isPrivate
* Indicates whether this is taking place in a private browsing context.
*/
function internalPersist(persistArgs)
{
@ -424,15 +471,10 @@ function internalPersist(persistArgs)
// Find the URI associated with the target file
var targetFileURL = makeFileURI(persistArgs.targetFile);
let isPrivate = persistArgs.isContentWindowPrivate;
if (isPrivate === undefined) {
isPrivate = PrivateBrowsingUtils.isContentWindowPrivate(persistArgs.initiatingWindow);
}
// Create download and initiate it (below)
var tr = Components.classes["@mozilla.org/transfer;1"].createInstance(Components.interfaces.nsITransfer);
tr.init(persistArgs.sourceURI,
targetFileURL, "", null, null, null, persist, isPrivate);
targetFileURL, "", null, null, null, persist, persistArgs.isPrivate);
persist.progressListener = new DownloadListener(window, tr);
if (persistArgs.sourceDocument) {
@ -471,7 +513,7 @@ function internalPersist(persistArgs)
persistArgs.sourcePostData,
null,
targetFileURL,
isPrivate);
persistArgs.isPrivate);
}
}
@ -828,17 +870,22 @@ function appendFiltersForContentType(aFilePicker, aContentType, aFileExtension,
function getPostData(aDocument)
{
const Ci = Components.interfaces;
if (aDocument instanceof Ci.nsIWebBrowserPersistDocument) {
return aDocument.postData;
}
try {
// Find the session history entry corresponding to the given document. In
// the current implementation, nsIWebPageDescriptor.currentDescriptor always
// returns a session history entry.
var sessionHistoryEntry =
let sessionHistoryEntry =
aDocument.defaultView
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIWebPageDescriptor)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIWebPageDescriptor)
.currentDescriptor
.QueryInterface(Components.interfaces.nsISHEntry);
.QueryInterface(Ci.nsISHEntry);
return sessionHistoryEntry.postData;
}
catch (e) {