Bug 835698 - 'Pre-open() and send the fd for app process's application.zip'. r=jduell.

This commit is contained in:
Ben Turner 2013-02-07 13:06:58 +00:00
parent b5a78ecd74
commit 8aa8c1b752
8 changed files with 60 additions and 89 deletions

View File

@ -21,6 +21,7 @@
#include "nsHTMLDNSPrefetch.h"
#include "nsIAppsService.h"
#include "nsEscape.h"
#include "RemoteOpenFileParent.h"
using mozilla::dom::TabParent;
using mozilla::net::PTCPSocketParent;
@ -403,6 +404,14 @@ NeckoParent::AllocPRemoteOpenFile(const URIParams& aURI,
return parent;
}
bool
NeckoParent::RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
const URIParams& aFileURI,
PBrowserParent* aBrowser)
{
return static_cast<RemoteOpenFileParent*>(aActor)->OpenSendCloseDelete();
}
bool
NeckoParent::DeallocPRemoteOpenFile(PRemoteOpenFileParent* actor)
{
@ -428,4 +437,3 @@ NeckoParent::RecvCancelHTMLDNSPrefetch(const nsString& hostname,
}
}} // mozilla::net

View File

@ -69,10 +69,16 @@ protected:
const bool& useSSL,
const nsString& aBinaryType,
PBrowserParent* aBrowser);
virtual PRemoteOpenFileParent* AllocPRemoteOpenFile(
const URIParams& fileuri,
PBrowserParent* browser);
virtual bool DeallocPRemoteOpenFile(PRemoteOpenFileParent* actor);
virtual PRemoteOpenFileParent* AllocPRemoteOpenFile(const URIParams& aFileURI,
PBrowserParent* aBrowser)
MOZ_OVERRIDE;
virtual bool RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
const URIParams& aFileURI,
PBrowserParent* aBrowser)
MOZ_OVERRIDE;
virtual bool DeallocPRemoteOpenFile(PRemoteOpenFileParent* aActor)
MOZ_OVERRIDE;
virtual bool RecvPTCPSocketConstructor(PTCPSocketParent*,
const nsString& aHost,

View File

@ -47,6 +47,8 @@ parent:
PWebSocket(PBrowser browser, SerializedLoadContext loadContext);
PTCPSocket(nsString host, uint16_t port, bool useSSL, nsString binaryType,
nullable PBrowser browser);
// Request that the parent open a file.
PRemoteOpenFile(URIParams fileuri, nullable PBrowser browser);
HTMLDNSPrefetch(nsString hostname, uint16_t flags);

View File

@ -18,18 +18,9 @@ protocol PRemoteOpenFile
{
manager PNecko;
parent:
// Tell parent to open file. URI to open was passed and vetted for security in
// IPDL constructor: see NeckoParent::AllocPRemoteOpenFile()
AsyncOpenFile();
__delete__();
child:
// Your file handle is ready, Sir...
FileOpened(FileDescriptor fd);
// Trying to send invalid fd crashes, so we need separate method for failure
FileDidNotOpen();
__delete__(FileDescriptor fd);
};

View File

@ -186,11 +186,7 @@ RemoteOpenFileChild::AsyncRemoteFileOpen(int32_t aFlags,
gNeckoChild->SendPRemoteOpenFileConstructor(this, uri, mTabChild);
// Can't seem to reply from within IPDL Parent constructor, so send open as
// separate message
SendAsyncOpenFile();
// The chrome process now has a logical ref to us until we call Send__delete
// The chrome process now has a logical ref to us until it calls Send__delete.
AddIPDLReference();
mListener = aListener;
@ -216,13 +212,13 @@ RemoteOpenFileChild::OnCachedFileDescriptor(const nsAString& aPath,
}
#endif
HandleFileDescriptorAndNotifyListener(aFD, /* aFromRecvFileOpened */ false);
HandleFileDescriptorAndNotifyListener(aFD, /* aFromRecvDelete */ false);
}
void
RemoteOpenFileChild::HandleFileDescriptorAndNotifyListener(
const FileDescriptor& aFD,
bool aFromRecvFileOpened)
bool aFromRecvDelete)
{
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
MOZ_NOT_REACHED("OS X and Windows shouldn't be doing IPDL here");
@ -243,9 +239,11 @@ RemoteOpenFileChild::HandleFileDescriptorAndNotifyListener(
nsRefPtr<TabChild> tabChild;
mTabChild.swap(tabChild);
// If there is a pending callback and we're being called from IPDL then we
// need to cancel it.
if (tabChild && aFromRecvFileOpened) {
// If RemoteOpenFile reply (Recv__delete__) for app's application.zip comes
// back sooner than the parent-pushed fd (TabChild::RecvCacheFileDescriptor())
// have TabChild cancel running callbacks, since we'll call them in
// NotifyListener.
if (tabChild && aFromRecvDelete) {
nsString path;
if (NS_FAILED(mFile->GetPath(path))) {
MOZ_NOT_REACHED("Couldn't get path from file!");
@ -285,33 +283,12 @@ RemoteOpenFileChild::NotifyListener(nsresult aResult)
//-----------------------------------------------------------------------------
bool
RemoteOpenFileChild::RecvFileOpened(const FileDescriptor& aFD)
RemoteOpenFileChild::Recv__delete__(const FileDescriptor& aFD)
{
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
NS_NOTREACHED("OS X and Windows shouldn't be doing IPDL here");
#else
HandleFileDescriptorAndNotifyListener(aFD, /* aFromRecvFileOpened */ true);
// This calls NeckoChild::DeallocPRemoteOpenFile(), which deletes |this| if
// IPDL holds the last reference. Don't rely on |this| existing after here!
Send__delete__(this);
#endif
return true;
}
bool
RemoteOpenFileChild::RecvFileDidNotOpen()
{
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
NS_NOTREACHED("OS X and Windows shouldn't be doing IPDL here");
#else
HandleFileDescriptorAndNotifyListener(FileDescriptor(),
/* aFromRecvFileOpened */ true);
// This calls NeckoChild::DeallocPRemoteOpenFile(), which deletes |this| if
// IPDL holds the last reference. Don't rely on |this| existing after here!
Send__delete__(this);
HandleFileDescriptorAndNotifyListener(aFD, /* aFromRecvDelete */ true);
#endif
return true;

View File

@ -7,6 +7,7 @@
#ifndef _RemoteOpenFileChild_h
#define _RemoteOpenFileChild_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/net/PRemoteOpenFileChild.h"
#include "nsICachedFileDescriptorListener.h"
@ -86,14 +87,13 @@ protected:
AddRef();
}
virtual bool RecvFileOpened(const FileDescriptor&);
virtual bool RecvFileDidNotOpen();
virtual bool Recv__delete__(const FileDescriptor&) MOZ_OVERRIDE;
virtual void OnCachedFileDescriptor(const nsAString& aPath,
const FileDescriptor& aFD) MOZ_OVERRIDE;
void HandleFileDescriptorAndNotifyListener(const FileDescriptor&,
bool aFromRecvFileOpened);
bool aFromRecvDelete);
void NotifyListener(nsresult aResult);

View File

@ -17,51 +17,42 @@
namespace mozilla {
namespace net {
RemoteOpenFileParent::RemoteOpenFileParent(nsIFileURL *aURI)
: mURI(aURI)
#if !defined(XP_WIN) && !defined(MOZ_WIDGET_COCOA)
, mFd(-1)
#endif
{}
RemoteOpenFileParent::~RemoteOpenFileParent()
{
#if !defined(XP_WIN) && !defined(MOZ_WIDGET_COCOA)
if (mFd != -1) {
// close file handle now that other process has it open, else we'll leak
// file handles in parent process
close(mFd);
}
#endif
}
bool
RemoteOpenFileParent::RecvAsyncOpenFile()
RemoteOpenFileParent::OpenSendCloseDelete()
{
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
NS_NOTREACHED("osX and Windows shouldn't be doing IPDL here");
MOZ_NOT_REACHED("OS X and Windows shouldn't be doing IPDL here");
#else
// TODO: make this async!
FileDescriptor fileDescriptor;
nsAutoCString path;
nsresult rv = mURI->GetFilePath(path);
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "GetFilePath failed!");
NS_UnescapeURL(path);
if (NS_SUCCEEDED(rv)) {
int fd = open(path.get(), O_RDONLY);
if (fd != -1) {
unused << SendFileOpened(FileDescriptor(fd));
// file handle needs to stay open until it's shared with child (and IPDL
// is async, so hasn't happened yet). Close in destructor.
mFd = fd;
return true;
if (fd == -1) {
printf_stderr("RemoteOpenFileParent: file '%s' was not found!\n",
path.get());
} else {
fileDescriptor = FileDescriptor(fd);
}
}
// Note: sending an invalid file descriptor currently kills the child process:
// but that's ok for our use case (failing to open application.jar).
printf_stderr("RemoteOpenFileParent: file '%s' was not found!\n", path.get());
unused << SendFileDidNotOpen();
// Sending a potentially invalid file descriptor is just fine.
unused << Send__delete__(this, fileDescriptor);
if (fileDescriptor.IsValid()) {
// close file now that other process has it open, else we'll leak fds in the
// parent process.
close(fileDescriptor.PlatformHandle());
}
#endif // OS_TYPE
return true;

View File

@ -18,18 +18,14 @@ namespace net {
class RemoteOpenFileParent : public PRemoteOpenFileParent
{
public:
RemoteOpenFileParent(nsIFileURL* aURI);
RemoteOpenFileParent(nsIFileURL* aURI)
: mURI(aURI)
{}
~RemoteOpenFileParent();
virtual bool RecvAsyncOpenFile();
bool OpenSendCloseDelete();
private:
nsCOMPtr<nsIFileURL> mURI;
#if !defined(XP_WIN) && !defined(MOZ_WIDGET_COCOA)
int mFd;
#endif
};
} // namespace net