author | Ryan VanderMeulen <ryanvm@gmail.com> |
Fri, 09 Nov 2012 20:14:40 -0500 | |
changeset 112905 | 5dc1c0530b009ac3f893daa77d70bc9ce482074f |
parent 112904 | 5eb2472d835d834df4a3965a96a898494e56cf9e |
child 112906 | e9c6c3ac7a762d18e3b0947021915b2d5859e928 |
push id | 17824 |
push user | ryanvm@gmail.com |
push date | Sat, 10 Nov 2012 01:14:44 +0000 |
treeherder | mozilla-inbound@5dc1c0530b00 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 806127, 802366, 806168 |
milestone | 19.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
|
--- a/caps/idl/nsIPrincipal.idl +++ b/caps/idl/nsIPrincipal.idl @@ -16,17 +16,17 @@ struct JSPrincipals; interface nsIURI; interface nsIContentSecurityPolicy; [ptr] native JSContext(JSContext); [ptr] native JSPrincipals(JSPrincipals); [ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >); -[scriptable, builtinclass, uuid(011966C0-8564-438D-B37A-08D7E1195E5A)] +[scriptable, uuid(3a283dc9-f733-4618-a36f-e2b68c280ab7)] interface nsIPrincipal : nsISerializable { /** * Returns whether the other principal is equivalent to this principal. * Principals are considered equal if they are the same principal, or * they have the same origin. */ boolean equals(in nsIPrincipal other); @@ -154,76 +154,88 @@ interface nsIPrincipal : nsISerializable readonly attribute AUTF8String extendedOrigin; const short APP_STATUS_NOT_INSTALLED = 0; const short APP_STATUS_INSTALLED = 1; const short APP_STATUS_PRIVILEGED = 2; const short APP_STATUS_CERTIFIED = 3; /** - * Gets the principal's app status, which indicates whether the principal - * corresponds to "app code", and if it does, how privileged that code is. - * This method returns one of the APP_STATUS constants above. - * - * Note that a principal may have - * - * appId != nsIScriptSecurityManager::NO_APP_ID && - * appId != nsIScriptSecurityManager::UNKNOWN_APP_ID - * - * and still have appStatus == APP_STATUS_NOT_INSTALLED. That's because - * appId identifies the app that contains this principal, but a window - * might be contained in an app and not be running code that the app has - * vouched for. For example, the window might be inside an <iframe - * mozbrowser>, or the window's origin might not match the app's origin. - * - * If you're doing a check to determine "does this principal correspond to - * app code?", you must check appStatus; checking appId != NO_APP_ID is not - * sufficient. + * Shows the status of the app. + * Can be: APP_STATUS_NOT_INSTALLED, APP_STATUS_INSTALLED, + * APP_STATUS_PRIVILEGED or APP_STATUS_CERTIFIED. */ - [infallible] readonly attribute unsigned short appStatus; + readonly attribute unsigned short appStatus; + + %{C++ + uint16_t GetAppStatus() + { + uint16_t appStatus; + nsresult rv = GetAppStatus(&appStatus); + if (NS_FAILED(rv)) { + return APP_STATUS_NOT_INSTALLED; + } + return appStatus; + } + %} /** - * Gets the id of the app this principal is inside. If this principal is - * not inside an app, returns nsIScriptSecurityManager::NO_APP_ID. - * - * Note that this principal does not necessarily have the permissions of - * the app identified by appId. For example, this principal might - * correspond to an iframe whose origin differs from that of the app frame - * containing it. In this case, the iframe will have the appId of its - * containing app frame, but the iframe must not run with the app's - * permissions. - * - * Similarly, this principal might correspond to an <iframe mozbrowser> - * inside an app frame; in this case, the content inside the iframe should - * not have any of the app's permissions, even if the iframe is at the same - * origin as the app. - * - * If you're doing a security check based on appId, you must check - * appStatus as well. + * Returns the app id the principal is in, or returns + * nsIScriptSecurityManager::NO_APP_ID if this principal isn't part of an + * app. */ - [infallible] readonly attribute unsigned long appId; + readonly attribute unsigned long appId; + + %{C++ + uint32_t GetAppId() + { + uint32_t appId; + mozilla::DebugOnly<nsresult> rv = GetAppId(&appId); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return appId; + } + %} /** - * Returns true iff the principal is inside a browser element. (<iframe - * mozbrowser mozapp> does not count as a browser element.) + * Returns true iif the principal is inside a browser element. */ - [infallible] readonly attribute boolean isInBrowserElement; + readonly attribute boolean isInBrowserElement; + + %{C++ + bool GetIsInBrowserElement() + { + bool isInBrowserElement; + mozilla::DebugOnly<nsresult> rv = GetIsInBrowserElement(&isInBrowserElement); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return isInBrowserElement; + } + %} /** * Returns true if this principal has an unknown appId. This shouldn't * generally be used. We only expose it due to not providing the correct * appId everywhere where we construct principals. */ - [infallible] readonly attribute boolean unknownAppId; + readonly attribute boolean unknownAppId; + + %{C++ + bool GetUnknownAppId() + { + bool unkwnownAppId; + mozilla::DebugOnly<nsresult> rv = GetUnknownAppId(&unkwnownAppId); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return unkwnownAppId; + } + %} /** * Returns true iff this principal is a null principal (corresponding to an * unknown, hence assumed minimally privileged, security context). */ - [infallible] readonly attribute boolean isNullPrincipal; + readonly attribute boolean isNullPrincipal; }; /** * If nsSystemPrincipal is too risky to use, but we want a principal to access * more than one origin, nsExpandedPrincipals letting us define an array of * principals it subsumes. So script with an nsExpandedPrincipals will gain * same origin access when at least one of its principals it contains gained * sameorigin acccess. An nsExpandedPrincipal will be subsumed by the system
--- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -330,25 +330,29 @@ nsScriptSecurityManager::GetChannelPrinc } // OK, get the principal from the URI. Make sure this does the same thing // as nsDocument::Reset and nsXULDocument::StartDocumentLoad. nsCOMPtr<nsIURI> uri; nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); + uint32_t appId = UNKNOWN_APP_ID; + bool isInBrowserElement = false; + nsCOMPtr<nsIDocShell> docShell; NS_QueryNotificationCallbacks(aChannel, docShell); if (docShell) { - return GetDocShellCodebasePrincipal(uri, docShell, aPrincipal); + docShell->GetAppId(&appId); + docShell->GetIsInBrowserElement(&isInBrowserElement); } - return GetCodebasePrincipalInternal(uri, UNKNOWN_APP_ID, - /* isInBrowserElement */ false, aPrincipal); + return GetCodebasePrincipalInternal(uri, appId, isInBrowserElement, + aPrincipal); } NS_IMETHODIMP nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal, bool* aIsSystem) { *aIsSystem = (aPrincipal == mSystemPrincipal); return NS_OK; @@ -1894,19 +1898,24 @@ nsScriptSecurityManager::GetAppCodebaseP return GetCodebasePrincipalInternal(aURI, aAppId, aInMozBrowser, aPrincipal); } NS_IMETHODIMP nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI, nsIDocShell* aDocShell, nsIPrincipal** aPrincipal) { - return GetCodebasePrincipalInternal(aURI, - aDocShell->GetAppId(), - aDocShell->GetIsInBrowserElement(), + MOZ_ASSERT(aDocShell); + + uint32_t appId; + bool isInBrowserElement; + aDocShell->GetAppId(&appId); + aDocShell->GetIsInBrowserElement(&isInBrowserElement); + + return GetCodebasePrincipalInternal(aURI, appId, isInBrowserElement, aPrincipal); } nsresult nsScriptSecurityManager::GetCodebasePrincipalInternal(nsIURI *aURI, uint32_t aAppId, bool aInMozBrowser, nsIPrincipal **result)
--- a/content/base/src/ThirdPartyUtil.cpp +++ b/content/base/src/ThirdPartyUtil.cpp @@ -110,19 +110,17 @@ ThirdPartyUtil::IsThirdPartyWindow(nsIDO *aResult = true; return NS_OK; } } nsCOMPtr<nsIDOMWindow> current = aWindow, parent; nsCOMPtr<nsIURI> parentURI; do { - // We use GetScriptableParent rather than GetParent because we consider - // <iframe mozbrowser/mozapp> to be a top-level frame. - rv = current->GetScriptableParent(getter_AddRefs(parent)); + rv = current->GetParent(getter_AddRefs(parent)); NS_ENSURE_SUCCESS(rv, rv); if (SameCOMIdentity(parent, current)) { // We're at the topmost content window. We already know the answer. *aResult = false; return NS_OK; } @@ -207,19 +205,17 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIC // If there is no window, the consumer kicking off the load didn't provide one // to the channel. This is limited to loads of certain types of resources. If // those loads require cookies, the forceAllowThirdPartyCookie property should // be set on the channel. nsCOMPtr<nsIDOMWindow> ourWin, parentWin; ctx->GetAssociatedWindow(getter_AddRefs(ourWin)); if (!ourWin) return NS_ERROR_INVALID_ARG; - // We use GetScriptableParent rather than GetParent because we consider - // <iframe mozbrowser/mozapp> to be a top-level frame. - ourWin->GetScriptableParent(getter_AddRefs(parentWin)); + ourWin->GetParent(getter_AddRefs(parentWin)); NS_ENSURE_TRUE(parentWin, NS_ERROR_INVALID_ARG); // Check whether this is the document channel for this window (representing a // load of a new page). In that situation we want to avoid comparing // channelURI to ourWin, since what's in ourWin right now will be replaced as // the channel loads. This covers the case of a freshly kicked-off load // (e.g. the user typing something in the location bar, or clicking on a // bookmark), where the window's URI hasn't yet been set, and will be bogus.
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -8354,17 +8354,17 @@ HasCrossProcessParent(nsIDocument* aDocu nsPIDOMWindow* win = aDocument->GetWindow(); if (!win) { return false; } nsCOMPtr<nsIDocShell> docShell = win->GetDocShell(); if (!docShell) { return false; } - return docShell->GetIsBrowserOrApp(); + return docShell->GetIsContentBoundary(); } static bool ResetFullScreen(nsIDocument* aDocument, void* aData) { if (aDocument->IsFullScreenDoc()) { static_cast<nsDocument*>(aDocument)->CleanupFullscreenState(); NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
--- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -939,17 +939,17 @@ nsFrameLoader::ShowRemoteFrame(const nsI } mRemoteBrowser->Show(size); mRemoteBrowserShown = true; EnsureMessageManager(); nsCOMPtr<nsIObserverService> os = services::GetObserverService(); - if (OwnerIsBrowserOrAppFrame() && os && !mRemoteBrowserInitialized) { + if (OwnerIsBrowserFrame() && os && !mRemoteBrowserInitialized) { os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this), "remote-browser-frame-shown", NULL); mRemoteBrowserInitialized = true; } } else { nsRect dimensions; NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false); mRemoteBrowser->UpdateDimensions(dimensions, size); @@ -1388,114 +1388,72 @@ nsFrameLoader::SetOwnerContent(Element* } mOwnerContent = aContent; if (RenderFrameParent* rfp = GetCurrentRemoteFrame()) { rfp->OwnerContentChanged(aContent); } } bool -nsFrameLoader::OwnerIsBrowserOrAppFrame() +nsFrameLoader::OwnerIsBrowserFrame() { nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent); - return browserFrame ? browserFrame->GetReallyIsBrowserOrApp() : false; + bool isBrowser = false; + if (browserFrame) { + browserFrame->GetReallyIsBrowser(&isBrowser); + } + return isBrowser; } bool nsFrameLoader::OwnerIsAppFrame() { nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent); - return browserFrame ? browserFrame->GetReallyIsApp() : false; -} - -bool -nsFrameLoader::OwnerIsBrowserFrame() -{ - return OwnerIsBrowserOrAppFrame() && !OwnerIsAppFrame(); + bool isApp = false; + if (browserFrame) { + browserFrame->GetReallyIsApp(&isApp); + } + return isApp; } void nsFrameLoader::GetOwnerAppManifestURL(nsAString& aOut) { aOut.Truncate(); nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent); if (browserFrame) { browserFrame->GetAppManifestURL(aOut); } } -already_AddRefed<mozIApplication> -nsFrameLoader::GetOwnApp() -{ - nsAutoString manifest; - GetOwnerAppManifestURL(manifest); - if (manifest.IsEmpty()) { - return nullptr; - } - - nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(appsService, nullptr); - - nsCOMPtr<mozIDOMApplication> domApp; - appsService->GetAppByManifestURL(manifest, getter_AddRefs(domApp)); - - nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp); - MOZ_ASSERT_IF(domApp, app); - return app.forget(); -} - -already_AddRefed<mozIApplication> -nsFrameLoader::GetContainingApp() -{ - // See if our owner content's principal has an associated app. - uint32_t appId = mOwnerContent->NodePrincipal()->GetAppId(); - MOZ_ASSERT(appId != nsIScriptSecurityManager::UNKNOWN_APP_ID); - - if (appId == nsIScriptSecurityManager::NO_APP_ID || - appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) { - return nullptr; - } - - nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(appsService, nullptr); - - nsCOMPtr<mozIDOMApplication> domApp; - appsService->GetAppByLocalId(appId, getter_AddRefs(domApp)); - MOZ_ASSERT(domApp); - - nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp); - MOZ_ASSERT_IF(domApp, app); - return app.forget(); -} - bool nsFrameLoader::ShouldUseRemoteProcess() { if (PR_GetEnv("MOZ_DISABLE_OOP_TABS") || Preferences::GetBool("dom.ipc.tabs.disabled", false)) { return false; } // If we're inside a content process, don't use a remote process for this // frame; it won't work properly until bug 761935 is fixed. if (XRE_GetProcessType() == GeckoProcessType_Content) { return false; } // If we're an <iframe mozbrowser> and we don't have a "remote" attribute, // fall back to the default. - if (OwnerIsBrowserOrAppFrame() && + if (OwnerIsBrowserFrame() && !mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::Remote)) { return Preferences::GetBool("dom.ipc.browser_frames.oop_by_default", false); } // Otherwise, we're remote if we have "remote=true" and we're either a // browser frame or a XUL element. - return (OwnerIsBrowserOrAppFrame() || + return (OwnerIsBrowserFrame() || mOwnerContent->GetNameSpaceID() == kNameSpaceID_XUL) && mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote, nsGkAtoms::_true, eCaseMatters); } nsresult @@ -1532,16 +1490,34 @@ nsFrameLoader::MaybeCreateDocShell() doc->GetContainer(); nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(container); NS_ENSURE_STATE(parentAsWebNav); // Create the docshell... mDocShell = do_CreateInstance("@mozilla.org/docshell;1"); NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + if (OwnerIsBrowserFrame()) { + nsAutoString manifest; + GetOwnerAppManifestURL(manifest); + if (!manifest.IsEmpty()) { + nsCOMPtr<nsIAppsService> appsService = + do_GetService(APPS_SERVICE_CONTRACTID); + if (!appsService) { + NS_ERROR("Apps Service is not available!"); + return NS_ERROR_FAILURE; + } + + uint32_t appId; + appsService->GetAppLocalIdByManifestURL(manifest, &appId); + + mDocShell->SetAppId(appId); + } + } + if (!mNetworkCreated) { nsCOMPtr<nsIDocShellHistory> history = do_QueryInterface(mDocShell); if (history) { history->SetCreatedDynamically(true); } } // Get the frame name and tell the docshell about it. @@ -1633,48 +1609,23 @@ nsFrameLoader::MaybeCreateDocShell() if (NS_FAILED(base_win->Create()) || !win_private) { // Do not call Destroy() here. See bug 472312. NS_WARNING("Something wrong when creating the docshell for a frameloader!"); return NS_ERROR_FAILURE; } EnsureMessageManager(); - if (OwnerIsAppFrame()) { - // You can't be both an app and a browser frame. - MOZ_ASSERT(!OwnerIsBrowserFrame()); - - nsCOMPtr<mozIApplication> ownApp = GetOwnApp(); - MOZ_ASSERT(ownApp); - uint32_t ownAppId = nsIScriptSecurityManager::NO_APP_ID; - if (ownApp) { - NS_ENSURE_SUCCESS(ownApp->GetLocalId(&ownAppId), NS_ERROR_FAILURE); - } - - mDocShell->SetIsApp(ownAppId); - } + if (OwnerIsBrowserFrame()) { + mDocShell->SetIsBrowserElement(); - if (OwnerIsBrowserFrame()) { - // You can't be both a browser and an app frame. - MOZ_ASSERT(!OwnerIsAppFrame()); - - nsCOMPtr<mozIApplication> containingApp = GetContainingApp(); - uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID; - if (containingApp) { - NS_ENSURE_SUCCESS(containingApp->GetLocalId(&containingAppId), - NS_ERROR_FAILURE); - } - mDocShell->SetIsBrowserInsideApp(containingAppId); - } - - if (OwnerIsBrowserOrAppFrame()) { nsCOMPtr<nsIObserverService> os = services::GetObserverService(); if (os) { os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this), - "in-process-browser-or-app-frame-shown", NULL); + "in-process-browser-frame-shown", NULL); } if (mMessageManager) { mMessageManager->LoadFrameScript( NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js"), /* allowDelayedLoad = */ true); } } @@ -1992,17 +1943,17 @@ nsFrameLoader::TryRemoteBrowser() if (!parentAsWebNav) { return false; } nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(parentAsWebNav)); // <iframe mozbrowser> gets to skip these checks. - if (!OwnerIsBrowserOrAppFrame()) { + if (!OwnerIsBrowserFrame()) { int32_t parentType; parentAsItem->GetItemType(&parentType); if (parentType != nsIDocShellTreeItem::typeChrome) { return false; } if (!mOwnerContent->IsXUL()) { @@ -2028,28 +1979,45 @@ nsFrameLoader::TryRemoteBrowser() nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner)); if (!window) { return false; } if (NS_FAILED(window->GetChromeFlags(&chromeFlags))) { return false; } - MutableTabContext context; - nsCOMPtr<mozIApplication> ownApp = GetOwnApp(); - nsCOMPtr<mozIApplication> containingApp = GetContainingApp(); - if (ownApp) { - context.SetTabContextForAppFrame(ownApp, containingApp); - } else if (OwnerIsBrowserFrame()) { - // The |else| above is unnecessary; OwnerIsBrowserFrame() implies !ownApp. - context.SetTabContextForBrowserFrame(containingApp); + bool isBrowserElement = false; + nsCOMPtr<mozIApplication> app; + if (OwnerIsBrowserFrame()) { + isBrowserElement = true; + + nsAutoString manifest; + GetOwnerAppManifestURL(manifest); + if (!manifest.IsEmpty()) { + nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); + if (!appsService) { + NS_ERROR("Apps Service is not available!"); + return false; + } + + nsCOMPtr<mozIDOMApplication> domApp; + appsService->GetAppByManifestURL(manifest, getter_AddRefs(domApp)); + // If the frame is actually an app, we should not mark it as a + // browser. This is to identify the data store: since <app>s + // and <browser>s-within-<app>s have different stores, we want + // to ensure the <app> uses its store, not the one for its + // <browser>s. + app = do_QueryInterface(domApp); + if (app) { + isBrowserElement = false; + } + } } - mRemoteBrowser = ContentParent::CreateBrowserOrApp(context); - if (mRemoteBrowser) { + if ((mRemoteBrowser = ContentParent::CreateBrowser(app, isBrowserElement))) { nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent); mRemoteBrowser->SetOwnerElement(element); nsCOMPtr<nsIDocShellTreeItem> rootItem; parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem)); nsCOMPtr<nsIDOMWindow> rootWin = do_GetInterface(rootItem); nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin); NS_ABORT_IF_FALSE(rootChromeWin, "How did we not get a chrome window here?"); @@ -2349,17 +2317,17 @@ nsFrameLoader::EnsureMessageManager() { NS_ENSURE_STATE(mOwnerContent); nsresult rv = MaybeCreateDocShell(); if (NS_FAILED(rv)) { return rv; } - if (!mIsTopLevelContent && !OwnerIsBrowserOrAppFrame() && !mRemoteFrame) { + if (!mIsTopLevelContent && !OwnerIsBrowserFrame() && !mRemoteFrame) { return NS_OK; } if (mMessageManager) { if (ShouldUseRemoteProcess()) { mMessageManager->SetCallback(mRemoteBrowserShown ? this : nullptr); } return NS_OK;
--- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -28,17 +28,16 @@ class nsIURI; class nsSubDocumentFrame; class nsIView; class nsIInProcessContentFrameMessageManager; class AutoResetInShow; class nsITabParent; class nsIDocShellTreeItem; class nsIDocShellTreeOwner; class nsIDocShellTreeNode; -class mozIApplication; namespace mozilla { namespace dom { class PBrowserParent; class TabParent; struct StructuredCloneData; } @@ -309,50 +308,33 @@ private: void SetOwnerContent(mozilla::dom::Element* aContent); bool ShouldUseRemoteProcess(); /** * Is this a frameloader for a bona fide <iframe mozbrowser> or * <iframe mozapp>? (I.e., does the frame return true for - * nsIMozBrowserFrame::GetReallyIsBrowserOrApp()?) + * nsIMozBrowserFrame::GetReallyIsBrowser()?) */ - bool OwnerIsBrowserOrAppFrame(); + bool OwnerIsBrowserFrame(); /** * Is this a frameloader for a bona fide <iframe mozapp>? (I.e., does the * frame return true for nsIMozBrowserFrame::GetReallyIsApp()?) */ bool OwnerIsAppFrame(); /** - * Is this a frame loader for a bona fide <iframe mozbrowser>? - */ - bool OwnerIsBrowserFrame(); - - /** * Get our owning element's app manifest URL, or return the empty string if * our owning element doesn't have an app manifest URL. */ void GetOwnerAppManifestURL(nsAString& aOut); /** - * Get the app for our frame. This is the app whose manifest is returned by - * GetOwnerAppManifestURL. - */ - already_AddRefed<mozIApplication> GetOwnApp(); - - /** - * Get the app which contains this frame. This is the app associated with - * the frame element's principal. - */ - already_AddRefed<mozIApplication> GetContainingApp(); - - /** * If we are an IPC frame, set mRemoteFrame. Otherwise, create and * initialize mDocShell. */ nsresult MaybeCreateDocShell(); nsresult EnsureMessageManager(); NS_HIDDEN_(void) GetURL(nsString& aURL); // Properly retrieves documentSize of any subdocument type.
--- a/content/base/src/nsInProcessTabChildGlobal.cpp +++ b/content/base/src/nsInProcessTabChildGlobal.cpp @@ -92,25 +92,24 @@ nsInProcessTabChildGlobal::DoSendAsyncMe nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner, nsFrameMessageManager* aChrome) : mDocShell(aShell), mInitialized(false), mLoadingScript(false), mDelayedDisconnect(false), mOwner(aOwner), mChromeMessageManager(aChrome) { - // If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll - // have to tweak our PreHandleEvent implementation. + // If owner corresponds to an <iframe mozbrowser>, we'll have to tweak our + // PreHandleEvent implementation. nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner); + bool isBrowser = false; if (browserFrame) { - mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp(); + browserFrame->GetReallyIsBrowser(&isBrowser); } - else { - mIsBrowserOrAppFrame = false; - } + mIsBrowserFrame = isBrowser; } nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal() { NS_ASSERTION(!mCx, "Couldn't release JSContext?!?"); } /* [notxpcom] boolean markForCC (); */ @@ -264,17 +263,17 @@ nsInProcessTabChildGlobal::GetOwnerConte return mOwner; } nsresult nsInProcessTabChildGlobal::PreHandleEvent(nsEventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = true; - if (mIsBrowserOrAppFrame && + if (mIsBrowserFrame && (!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) { if (mOwner) { nsPIDOMWindow* innerWindow = mOwner->OwnerDoc()->GetInnerWindow(); if (innerWindow) { aVisitor.mParentTarget = innerWindow->GetParentTarget(); } } } else {
--- a/content/base/src/nsInProcessTabChildGlobal.h +++ b/content/base/src/nsInProcessTabChildGlobal.h @@ -117,19 +117,18 @@ protected: nsresult Init(); nsresult InitTabChildGlobal(); nsCOMPtr<nsIContentFrameMessageManager> mMessageManager; nsCOMPtr<nsIDocShell> mDocShell; bool mInitialized; bool mLoadingScript; bool mDelayedDisconnect; - // Is this the message manager for an in-process <iframe mozbrowser> or - // <iframe mozapp>? This affects where events get sent, so it affects - // PreHandleEvent. - bool mIsBrowserOrAppFrame; + // Is this the message manager for an in-process <iframe mozbrowser>? This + // affects where events get sent, so it affects PreHandleEvent. + bool mIsBrowserFrame; public: nsIContent* mOwner; nsFrameMessageManager* mChromeMessageManager; nsTArray<nsCOMPtr<nsIRunnable> > mASyncMessages; }; #endif
--- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -1565,20 +1565,24 @@ nsEventStateManager::IsRemoteTarget(nsIC if ((target->Tag() == nsGkAtoms::browser || target->Tag() == nsGkAtoms::iframe) && target->IsXUL() && target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote, nsGkAtoms::_true, eIgnoreCase)) { return true; } - // <frame/iframe mozbrowser/mozapp> + // <frame/iframe mozbrowser> nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(target); - if (browserFrame && browserFrame->GetReallyIsBrowserOrApp()) { - return !!TabParent::GetFrom(target); + if (browserFrame) { + bool isBrowser = false; + browserFrame->GetReallyIsBrowser(&isBrowser); + if (isBrowser) { + return !!TabParent::GetFrom(target); + } } return false; } /*static*/ void nsEventStateManager::MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoader, nsEvent* aEvent)
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp +++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp @@ -273,71 +273,73 @@ nsGenericHTMLFrameElement::IsHTMLFocusab return false; } /** * Return true if this frame element really is a mozbrowser or mozapp. (It * needs to have the right attributes, and its creator must have the right * permissions.) */ -/* [infallible] */ nsresult -nsGenericHTMLFrameElement::GetReallyIsBrowserOrApp(bool *aOut) +nsresult +nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aOut) { *aOut = false; // Fail if browser frames are globally disabled. if (!Preferences::GetBool("dom.mozBrowserFramesEnabled")) { return NS_OK; } // Fail if this frame doesn't have the mozbrowser attribute. - bool hasMozbrowser = false; - GetMozbrowser(&hasMozbrowser); - if (!hasMozbrowser) { + bool isBrowser = false; + GetMozbrowser(&isBrowser); + if (!isBrowser) { return NS_OK; } // Fail if the node principal isn't trusted. nsIPrincipal *principal = NodePrincipal(); nsCOMPtr<nsIPermissionManager> permMgr = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); - NS_ENSURE_TRUE(permMgr, NS_OK); + NS_ENSURE_STATE(permMgr); uint32_t permission = nsIPermissionManager::DENY_ACTION; nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission); NS_ENSURE_SUCCESS(rv, NS_OK); *aOut = permission == nsIPermissionManager::ALLOW_ACTION; return NS_OK; } -/* [infallible] */ NS_IMETHODIMP +NS_IMETHODIMP nsGenericHTMLFrameElement::GetReallyIsApp(bool *aOut) { nsAutoString manifestURL; GetAppManifestURL(manifestURL); *aOut = !manifestURL.IsEmpty(); return NS_OK; } NS_IMETHODIMP nsGenericHTMLFrameElement::GetAppManifestURL(nsAString& aOut) { aOut.Truncate(); // At the moment, you can't be an app without being a browser. - if (!nsIMozBrowserFrame::GetReallyIsBrowserOrApp()) { + bool isBrowser = false; + GetReallyIsBrowser(&isBrowser); + if (!isBrowser) { return NS_OK; } // Check permission. nsIPrincipal *principal = NodePrincipal(); nsCOMPtr<nsIPermissionManager> permMgr = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); - NS_ENSURE_TRUE(permMgr, NS_OK); + NS_ENSURE_STATE(permMgr); uint32_t permission = nsIPermissionManager::DENY_ACTION; nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "embed-apps", &permission); NS_ENSURE_SUCCESS(rv, NS_OK); if (permission != nsIPermissionManager::ALLOW_ACTION) { return NS_OK; @@ -345,20 +347,21 @@ nsGenericHTMLFrameElement::GetAppManifes nsAutoString manifestURL; GetAttr(kNameSpaceID_None, nsGkAtoms::mozapp, manifestURL); if (manifestURL.IsEmpty()) { return NS_OK; } nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(appsService, NS_OK); + NS_ENSURE_STATE(appsService); nsCOMPtr<mozIDOMApplication> app; appsService->GetAppByManifestURL(manifestURL, getter_AddRefs(app)); + if (app) { aOut.Assign(manifestURL); } return NS_OK; } NS_IMETHODIMP
--- a/docshell/base/nsDSURIContentListener.cpp +++ b/docshell/base/nsDSURIContentListener.cpp @@ -321,17 +321,17 @@ bool nsDSURIContentListener::CheckOneFra // Traverse up the parent chain and stop when we see a docshell whose // parent has a system principal, or a docshell corresponding to // <iframe mozbrowser>. while (NS_SUCCEEDED(curDocShellItem->GetParent(getter_AddRefs(parentDocShellItem))) && parentDocShellItem) { nsCOMPtr<nsIDocShell> curDocShell = do_QueryInterface(curDocShellItem); - if (curDocShell && curDocShell->GetIsBrowserOrApp()) { + if (curDocShell && curDocShell->GetIsContentBoundary()) { break; } bool system = false; topDoc = do_GetInterface(parentDocShellItem); if (topDoc) { if (NS_SUCCEEDED(ssm->IsSystemPrincipal(topDoc->NodePrincipal(), &system)) && system) {
--- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -725,17 +725,16 @@ static uint64_t gDocshellIDCounter = 0; nsDocShell::nsDocShell(): nsDocLoader(), mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto), mTreeOwner(nullptr), mChromeEventHandler(nullptr), mCharsetReloadState(eCharsetReloadInit), mChildOffset(0), mBusyFlags(BUSY_FLAGS_NONE), - mFrameType(eFrameTypeRegular), mAppType(nsIDocShell::APP_TYPE_UNKNOWN), mLoadType(0), mMarginWidth(-1), mMarginHeight(-1), mItemType(typeContent), mPreviousTransIndex(-1), mLoadedTransIndex(-1), mSandboxFlags(0), @@ -763,17 +762,17 @@ nsDocShell::nsDocShell(): mURIResultedInDocument(false), mIsBeingDestroyed(false), mIsExecutingOnLoadHandler(false), mIsPrintingOrPP(false), mSavingOldViewer(false), #ifdef DEBUG mInEnsureScriptEnv(false), #endif - mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID), + mAppId(nsIScriptSecurityManager::NO_APP_ID), mParentCharsetSource(0) { mHistoryID = ++gDocshellIDCounter; if (gDocShellCount++ == 0) { NS_ASSERTION(sURIFixup == nullptr, "Huh, sURIFixup not null in first nsDocShell ctor!"); CallGetService(NS_URIFIXUP_CONTRACTID, &sURIFixup); @@ -2146,29 +2145,29 @@ NS_IMETHODIMP nsDocShell::SetAllowWindow return NS_OK; } NS_IMETHODIMP nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed) { NS_ENSURE_ARG_POINTER(aFullscreenAllowed); - // Browsers and apps have their mFullscreenAllowed retrieved from their + // Content boundaries have their mFullscreenAllowed retrieved from their // corresponding iframe in their parent upon creation. if (mFullscreenAllowed != CHECK_ATTRIBUTES) { *aFullscreenAllowed = (mFullscreenAllowed == PARENT_ALLOWS); return NS_OK; } // Assume false until we determine otherwise... *aFullscreenAllowed = false; - // For non-browsers/apps, check that the enclosing iframe element + // For non-content boundaries, check that the enclosing iframe element // has the allowfullscreen attribute set to true. If any ancestor - // iframe does not have mozallowfullscreen=true, then fullscreen is + // iframe does not have allowfullscreen=true, then fullscreen is // prohibited. nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(GetAsSupports(this)); if (!win) { return NS_OK; } nsCOMPtr<nsIContent> frameElement = do_QueryInterface(win->GetFrameElementInternal()); if (frameElement && frameElement->IsHTML(nsGkAtoms::iframe) && @@ -2195,17 +2194,17 @@ nsDocShell::GetFullscreenAllowed(bool* a NS_ENSURE_TRUE(parent, NS_OK); return parent->GetFullscreenAllowed(aFullscreenAllowed); } NS_IMETHODIMP nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed) { - if (!nsIDocShell::GetIsBrowserOrApp()) { + if (!nsIDocShell::GetIsContentBoundary()) { // Only allow setting of fullscreenAllowed on content/process boundaries. // At non-boundaries the fullscreenAllowed attribute is calculated based on // whether all enclosing frames have the "mozFullscreenAllowed" attribute // set to "true". fullscreenAllowed is set at the process boundaries to // propagate the value of the parent's "mozFullscreenAllowed" attribute // across process boundaries. return NS_ERROR_UNEXPECTED; } @@ -2807,17 +2806,17 @@ nsDocShell::SetDocLoaderParent(nsDocLoad } NS_IMETHODIMP nsDocShell::GetSameTypeParent(nsIDocShellTreeItem ** aParent) { NS_ENSURE_ARG_POINTER(aParent); *aParent = nullptr; - if (nsIDocShell::GetIsBrowserOrApp()) { + if (mIsBrowserFrame) { return NS_OK; } nsCOMPtr<nsIDocShellTreeItem> parent = do_QueryInterface(GetAsSupports(mParent)); if (!parent) return NS_OK; @@ -2826,17 +2825,17 @@ nsDocShell::GetSameTypeParent(nsIDocShel if (parentType == mItemType) { parent.swap(*aParent); } return NS_OK; } NS_IMETHODIMP -nsDocShell::GetSameTypeParentIgnoreBrowserAndAppBoundaries(nsIDocShell** aParent) +nsDocShell::GetParentIgnoreBrowserFrame(nsIDocShell** aParent) { NS_ENSURE_ARG_POINTER(aParent); *aParent = nullptr; nsCOMPtr<nsIDocShellTreeItem> parent = do_QueryInterface(GetAsSupports(mParent)); if (!parent) return NS_OK; @@ -2929,21 +2928,29 @@ nsDocShell::CanAccessItem(nsIDocShellTre nsCOMPtr<nsIDocShell> targetDS = do_QueryInterface(aTargetItem); nsCOMPtr<nsIDocShell> accessingDS = do_QueryInterface(aAccessingItem); if (!!targetDS != !!accessingDS) { // We must be able to convert both or neither to nsIDocShell. return false; } - if (targetDS && accessingDS && - (targetDS->GetIsInBrowserElement() != - accessingDS->GetIsInBrowserElement() || - targetDS->GetAppId() != accessingDS->GetAppId())) { - return false; + if (targetDS && accessingDS) { + bool targetInBrowser = false, accessingInBrowser = false; + targetDS->GetIsInBrowserElement(&targetInBrowser); + accessingDS->GetIsInBrowserElement(&accessingInBrowser); + + uint32_t targetAppId = 0, accessingAppId = 0; + targetDS->GetAppId(&targetAppId); + accessingDS->GetAppId(&accessingAppId); + + if (targetInBrowser != accessingInBrowser || + targetAppId != accessingAppId) { + return false; + } } nsCOMPtr<nsIDocShellTreeItem> accessingRoot; aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot)); if (aTargetItem == accessingRoot) { // A frame can navigate its root. return true; @@ -5217,17 +5224,17 @@ nsDocShell::SetIsActive(bool aIsActive) // children; they handle their state separately. int32_t n = mChildList.Count(); for (int32_t i = 0; i < n; ++i) { nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(ChildAt(i)); if (!docshell) { continue; } - if (!docshell->GetIsBrowserOrApp()) { + if (!docshell->GetIsContentBoundary()) { docshell->SetIsActive(aIsActive); } } return NS_OK; } NS_IMETHODIMP @@ -12299,118 +12306,148 @@ nsDocShell::GetCanExecuteScripts(bool *a #endif // DEBUG } while (treeItem && docshell); } return NS_OK; } NS_IMETHODIMP -nsDocShell::SetIsApp(uint32_t aOwnAppId) -{ - mOwnOrContainingAppId = aOwnAppId; - if (aOwnAppId != nsIScriptSecurityManager::NO_APP_ID && - aOwnAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) { - mFrameType = eFrameTypeApp; - } else { - mFrameType = eFrameTypeRegular; - } - - return NS_OK; -} - -NS_IMETHODIMP -nsDocShell::SetIsBrowserInsideApp(uint32_t aContainingAppId) -{ - mOwnOrContainingAppId = aContainingAppId; - mFrameType = eFrameTypeBrowser; - return NS_OK; -} - -/* [infallible] */ NS_IMETHODIMP -nsDocShell::GetIsBrowserElement(bool* aIsBrowser) -{ - *aIsBrowser = (mFrameType == eFrameTypeBrowser); - return NS_OK; -} - -/* [infallible] */ NS_IMETHODIMP -nsDocShell::GetIsApp(bool* aIsApp) -{ - *aIsApp = (mFrameType == eFrameTypeApp); - return NS_OK; -} - -/* [infallible] */ NS_IMETHODIMP -nsDocShell::GetIsBrowserOrApp(bool* aIsBrowserOrApp) -{ - switch (mFrameType) { - case eFrameTypeRegular: - *aIsBrowserOrApp = false; - break; - case eFrameTypeBrowser: - case eFrameTypeApp: - *aIsBrowserOrApp = true; - break; +nsDocShell::SetIsBrowserElement() +{ + if (mIsBrowserFrame) { + NS_ERROR("You should not call SetIsBrowserElement() more than once."); + return NS_OK; + } + + mIsBrowserFrame = true; + + nsCOMPtr<nsIObserverService> os = services::GetObserverService(); + if (os) { + os->NotifyObservers(GetAsSupports(this), + "docshell-marked-as-browser-frame", NULL); } return NS_OK; } nsDocShell::FrameType nsDocShell::GetInheritedFrameType() { - if (mFrameType != eFrameTypeRegular) { - return mFrameType; + FrameType type = GetFrameType(); + + if (type != eFrameTypeRegular) { + return type; } nsCOMPtr<nsIDocShellTreeItem> parentAsItem; GetSameTypeParent(getter_AddRefs(parentAsItem)); nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem); if (!parent) { return eFrameTypeRegular; } return static_cast<nsDocShell*>(parent.get())->GetInheritedFrameType(); } +nsDocShell::FrameType +nsDocShell::GetFrameType() +{ + if (mAppId != nsIScriptSecurityManager::NO_APP_ID) { + return eFrameTypeApp; + } + + return mIsBrowserFrame ? eFrameTypeBrowser : eFrameTypeRegular; +} + +/* [infallible] */ NS_IMETHODIMP +nsDocShell::GetIsBrowserElement(bool* aIsBrowser) +{ + *aIsBrowser = (GetFrameType() == eFrameTypeBrowser); + return NS_OK; +} + +/* [infallible] */ NS_IMETHODIMP +nsDocShell::GetIsApp(bool* aIsApp) +{ + *aIsApp = (GetFrameType() == eFrameTypeApp); + return NS_OK; +} + +/* [infallible] */ NS_IMETHODIMP +nsDocShell::GetIsContentBoundary(bool* aIsContentBoundary) +{ + switch (GetFrameType()) { + case eFrameTypeRegular: + *aIsContentBoundary = false; + break; + case eFrameTypeBrowser: + case eFrameTypeApp: + *aIsContentBoundary = true; + break; + } + + return NS_OK; +} + /* [infallible] */ NS_IMETHODIMP nsDocShell::GetIsInBrowserElement(bool* aIsInBrowserElement) { *aIsInBrowserElement = (GetInheritedFrameType() == eFrameTypeBrowser); return NS_OK; } /* [infallible] */ NS_IMETHODIMP -nsDocShell::GetIsInBrowserOrApp(bool* aIsInBrowserOrApp) +nsDocShell::GetIsInApp(bool* aIsInApp) +{ + *aIsInApp = (GetInheritedFrameType() == eFrameTypeApp); + return NS_OK; +} + +/* [infallible] */ NS_IMETHODIMP +nsDocShell::GetIsBelowContentBoundary(bool* aIsInContentBoundary) { switch (GetInheritedFrameType()) { case eFrameTypeRegular: - *aIsInBrowserOrApp = false; + *aIsInContentBoundary = false; break; case eFrameTypeBrowser: case eFrameTypeApp: - *aIsInBrowserOrApp = true; + *aIsInContentBoundary = true; break; } return NS_OK; } +NS_IMETHODIMP +nsDocShell::SetAppId(uint32_t aAppId) +{ + MOZ_ASSERT(mAppId == nsIScriptSecurityManager::NO_APP_ID); + MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID); + + mAppId = aAppId; + return NS_OK; +} + /* [infallible] */ NS_IMETHODIMP nsDocShell::GetAppId(uint32_t* aAppId) { - if (mOwnOrContainingAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) { - *aAppId = mOwnOrContainingAppId; + if (mAppId != nsIScriptSecurityManager::NO_APP_ID) { + MOZ_ASSERT(GetFrameType() == eFrameTypeApp); + + *aAppId = mAppId; return NS_OK; } + MOZ_ASSERT(GetFrameType() != eFrameTypeApp); + nsCOMPtr<nsIDocShell> parent; - GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent)); + GetParentIgnoreBrowserFrame(getter_AddRefs(parent)); if (!parent) { *aAppId = nsIScriptSecurityManager::NO_APP_ID; return NS_OK; } return parent->GetAppId(aAppId); }
--- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -660,22 +660,23 @@ protected: void Revoke() { mDocShell = nullptr; } private: nsRefPtr<nsDocShell> mDocShell; }; bool JustStartedNetworkLoad(); enum FrameType { - eFrameTypeRegular, - eFrameTypeBrowser, - eFrameTypeApp + eFrameTypeRegular = 0x0, // 0000 + eFrameTypeBrowser = 0x1, // 0001 + eFrameTypeApp = 0x2 // 0010 }; FrameType GetInheritedFrameType(); + FrameType GetFrameType(); // hash of session storages, keyed by domain nsInterfaceHashtable<nsCStringHashKey, nsIDOMStorage> mStorages; // Dimensions of the docshell nsIntRect mBounds; nsString mName; nsString mTitle; @@ -802,16 +803,17 @@ protected: bool mObserveErrorPages; bool mAllowAuth; bool mAllowKeywordFixup; bool mIsOffScreenBrowser; bool mIsActive; bool mIsAppTab; bool mUseGlobalHistory; bool mInPrivateBrowsing; + bool mIsBrowserFrame; // This boolean is set to true right before we fire pagehide and generally // unset when we embed a new content viewer. While it's true no navigation // is allowed in this docshell. bool mFiredUnloadEvent; // this flag is for bug #21358. a docshell may load many urls // which don't result in new documents being created (i.e. a new @@ -838,28 +840,17 @@ protected: bool mInEnsureScriptEnv; #endif uint64_t mHistoryID; static nsIURIFixup *sURIFixup; nsRefPtr<nsDOMNavigationTiming> mTiming; - // Are we a regular frame, a browser frame, or an app frame? - FrameType mFrameType; - - // We only expect mOwnOrContainingAppId to be something other than - // UNKNOWN_APP_ID if mFrameType != eFrameTypeRegular. For vanilla iframes - // inside an app, we'll retrieve the containing app-id by walking up the - // docshell hierarchy. - // - // (This needs to be the docshell's own /or containing/ app id because the - // containing app frame might be in another process, in which case we won't - // find it by walking up the docshell hierarchy.) - uint32_t mOwnOrContainingAppId; + uint32_t mAppId; private: nsCOMPtr<nsIAtom> mForcedCharset; nsCOMPtr<nsIAtom> mParentCharset; nsTObserverArray<nsWeakPtr> mPrivacyObservers; int32_t mParentCharsetSource; nsCString mOriginalUriString;
--- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -34,17 +34,17 @@ interface nsISHEntry; interface nsILayoutHistoryState; interface nsISecureBrowserUI; interface nsIDOMStorage; interface nsIPrincipal; interface nsIWebBrowserPrint; interface nsIVariant; interface nsIPrivacyTransitionObserver; -[scriptable, builtinclass, uuid(318CE516-3F7A-41F6-8F3D-3661650F7A46)] +[scriptable, builtinclass, uuid(e93b2f6a-c543-448b-9239-55c96e31672e)] interface nsIDocShell : nsISupports { /** * Loads a given URI. This will give priority to loading the requested URI * in the object implementing this interface. If it can't be loaded here * however, the URL dispatcher will go through its normal process of content * loading. * @@ -574,112 +574,102 @@ interface nsIDocShell : nsISupports /** * Add an observer to the list of parties to be notified when this docshell's * private browsing status is changed. |obs| must support weak references. */ void addWeakPrivacyTransitionObserver(in nsIPrivacyTransitionObserver obs); /** - * Returns true if this docshell corresponds to an <iframe mozbrowser>. - * (<iframe mozapp mozbrowser> is not considered a browser.) + * Mark the docshell as a browser frame. + * This should be used for <iframe mozbrowser> but not for <iframe mozapp>. + * + * This method should not be called more than once. + */ + void setIsBrowserElement(); + + /** + * Returns true iff the docshell is marked as a browser frame. */ [infallible] readonly attribute boolean isBrowserElement; /** - * Returns true iff the docshell corresponds to an <iframe mozapp>. + * Returns true iif the docshell is marked as an app frame. */ [infallible] readonly attribute boolean isApp; /** - * Returns isBrowserElement || isApp. + * Returns true iif the docshell is marked as a type that behaves like a + * content boundary. */ - [infallible] readonly attribute boolean isBrowserOrApp; + [infallible] readonly attribute boolean isContentBoundary; /** - * Returns true if this docshell corresponds to an <iframe mozbrowser> or if - * the docshell is contained in an <iframe mozbrowser>. (<iframe mozapp - * mozbrowser> does not count as a browser.) - * - * Our notion here of "contained in" means: Walk up the docshell hierarchy in - * this process until we hit an <iframe mozapp> or <iframe mozbrowser> (or - * until the hierarchy ends). Return true iff the docshell we stopped on has - * isBrowserElement == true. + * Returns true iif the docshell is inside a browser element. */ [infallible] readonly attribute boolean isInBrowserElement; /** - * Returns true if this docshell corresponds to an <iframe mozbrowser> or - * <iframe mozap>, or if this docshell is contained in an <iframe mozbrowser> - * or <iframe mozapp>. + * Returns true iif the docshell is inside an application. However, it will + * return false if the docshell is inside a browser element that is inside + * an application. * - * To compute this value, we walk up the docshell hierarchy. If we encounter - * a docshell with isBrowserElement or isApp before we hit the end of the - * hierarchy, we return true. Otherwise, we return false. + * Note: Do not use this method for permissions checks! An app may contain + * an <iframe> pointing at arbitrary web code. This iframe's docshell will + * have isInApp() == true, but the iframe's content is not "app code", and + * so should not be granted more trust than vanilla web content. + * + * (For example, suppose when web content calls API method X, we show a + * permission prompt, but when "app code" calls method X, we don't. In this + * case, it would be /incorrect/ to show the permission prompt if + * !isInApp().) + * + * If you're doing a security check, use the content's principal instead of + * this method. */ - [infallible] readonly attribute boolean isInBrowserOrApp; - - /** - * Indicate that this docshell corresponds to an app with the given app id. - * - * You may pass NO_APP_ID or UNKNOWN_APP_ID for containingAppId. If you - * pass NO_APP_ID, then this docshell will return NO_APP_ID for appId. If - * you pass UNKNOWN_APP_ID, then this docshell will search its hiearchy for - * an app frame and use that frame's appId. - * - * You can call this method more than once, but there's no guarantee that - * other components will update their view of the world if you change a - * docshell's app id, so tread lightly. - * - * If you call this method after calling setIsBrowserInsideApp, this - * docshell will forget the fact that it was a browser. - */ - void setIsApp(in unsigned long ownAppId); - - /** - * Indicate that this docshell corresponds to a browser inside an app with - * the given ID. As with setIsApp, you may pass NO_APP_ID or - * UNKNOWN_APP_ID. - * - * As with setIsApp, you may call this more than once, but it's kind of a - * hack, so be careful. - */ - void setIsBrowserInsideApp(in unsigned long containingAppId); + [infallible] readonly attribute boolean isInApp; /** - * Returns the id of the app associated with this docshell. If this docshell - * is an <iframe mozbrowser> inside an <iframe mozapp>, we return the app's - * appId. + * Returns if the docshell has a docshell that behaves as a content boundary + * in his parent hierarchy. + */ + [infallible] readonly attribute boolean isBelowContentBoundary; + + /** + * Set the app id this docshell is associated with. The id has to be a valid + * app id. If the docshell isn't associated with any app, the value should be + * nsIScriptSecurityManager::NO_APP_ID. However, this is the default value if + * nothing is et. * - * We compute this value by walking up the docshell hierarchy until we find a - * docshell on which setIsApp(x) or setIsBrowserInsideApp(x) was called - * (ignoring those docshells where x == UNKNOWN_APP_ID). We return the app - * id x. + * This method is [noscript] to reduce the scope. It should be used at very + * specific moments. * - * If we don't find a docshell with an associated app id in our hierarchy, we - * return NO_APP_ID. We never return UNKNOWN_APP_ID. - * - * Notice that a docshell may have an associated app even if it returns true - * for isBrowserElement! + * Calling setAppId() will mark the frame as an app frame. + */ + [noscript] void setAppId(in unsigned long appId); + + /** + * Returns the app id of the app the docshell is in. Returns + * nsIScriptSecurityManager::NO_APP_ID if the docshell is not in an app. */ [infallible] readonly attribute unsigned long appId; - /** - * Like nsIDocShellTreeItem::GetSameTypeParent, except this ignores <iframe - * mozbrowser> and <iframe mozapp> boundaries. - */ - nsIDocShell getSameTypeParentIgnoreBrowserAndAppBoundaries(); - /** * True iff asynchronous panning and zooming is enabled for this * docshell. */ readonly attribute bool asyncPanZoomEnabled; /** + * Like GetSameTypeParent, except this ignores <iframe mozbrowser> + * boundaries. + */ + nsIDocShell getParentIgnoreBrowserFrame(); + + /** * The sandbox flags on the docshell. These reflect the value of the sandbox * attribute of the associated IFRAME or CSP-protectable content, if * existent. See the HTML5 spec for more details. * These flags on the docshell reflect the current state of the sandbox * attribute, which is modifiable. They are only used when loading new * content, sandbox flags are also immutably set on the document when it is * loaded. * The sandbox flags of a document depend on the sandbox flags on its
--- a/docshell/base/nsIDocShellTreeItem.idl +++ b/docshell/base/nsIDocShellTreeItem.idl @@ -48,21 +48,20 @@ interface nsIDocShellTreeItem : nsIDocSh attribute long itemType; /* Parent DocShell. */ readonly attribute nsIDocShellTreeItem parent; /* - This getter returns the same thing parent does however if the parent - is of a different itemType, or if the parent is an <iframe mozbrowser> - or <iframe mozapp>, it will instead return nullptr. This call is a - convience function for those wishing to not cross the boundaries at - which item types change. + This is call returns the same thing parent does however if the parent is + of a different itemType, it will instead return nullptr. This call is a + convience function for those wishing to not cross the boundaries at which + item types change. */ readonly attribute nsIDocShellTreeItem sameTypeParent; /* Returns the root DocShellTreeItem. This is a convience equivalent to getting the parent and its parent until there isn't a parent. */ readonly attribute nsIDocShellTreeItem rootTreeItem;
--- a/docshell/base/nsILoadContext.idl +++ b/docshell/base/nsILoadContext.idl @@ -78,17 +78,17 @@ interface nsILoadContext : nsISupports %} /** * Set the private browsing state of the load context, meant to be used internally. */ [noscript] void SetPrivateBrowsing(in boolean aInPrivateBrowsing); /** - * Returns true iff the load is occurring inside a browser element. + * Returns true iif the load is occurring inside a browser element. */ readonly attribute boolean isInBrowserElement; /** * Returns the app id of the app the load is occurring is in. Returns * nsIScriptSecurityManager::NO_APP_ID if the load is not part of an app. */ readonly attribute unsigned long appId;
--- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -1829,16 +1829,20 @@ this.DOMApplicationRegistry = { mm.addMessageListener(msgName, listener); }); }, receiveAppMessage: function(appId, message) { switch (message.name) { case "Webapps:ClearBrowserData": this._clearPrivateData(appId, true); + // XXXbent This is a hack until bug 802366 is fixed. Currently all data + // loaded in mozbrowser frames within an app believe that their + // appId is 0. + this._clearPrivateData(0, true); break; } }, _clearPrivateData: function(appId, browserOnly) { let subject = { appId: appId, browserOnly: browserOnly,
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2919,17 +2919,17 @@ nsGlobalWindow::GetScriptableParent(nsID { FORWARD_TO_OUTER(GetScriptableParent, (aParent), NS_ERROR_NOT_INITIALIZED); *aParent = NULL; if (!mDocShell) { return NS_OK; } - if (mDocShell->GetIsBrowserOrApp()) { + if (mDocShell->GetIsContentBoundary()) { nsCOMPtr<nsIDOMWindow> parent = static_cast<nsIDOMWindow*>(this); parent.swap(*aParent); return NS_OK; } return GetRealParent(aParent); } @@ -2943,17 +2943,17 @@ nsGlobalWindow::GetRealParent(nsIDOMWind FORWARD_TO_OUTER(GetRealParent, (aParent), NS_ERROR_NOT_INITIALIZED); *aParent = nullptr; if (!mDocShell) { return NS_OK; } nsCOMPtr<nsIDocShell> parent; - mDocShell->GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent)); + mDocShell->GetParentIgnoreBrowserFrame(getter_AddRefs(parent)); if (parent) { nsCOMPtr<nsIScriptGlobalObject> globalObject(do_GetInterface(parent)); NS_ENSURE_SUCCESS(CallQueryInterface(globalObject.get(), aParent), NS_ERROR_FAILURE); } else { *aParent = static_cast<nsIDOMWindow*>(this); @@ -3024,19 +3024,19 @@ nsGlobalWindow::GetTopImpl(nsIDOMWindow* } NS_IMETHODIMP nsGlobalWindow::GetContent(nsIDOMWindow** aContent) { FORWARD_TO_OUTER(GetContent, (aContent), NS_ERROR_NOT_INITIALIZED); *aContent = nullptr; - // If we're contained in <iframe mozbrowser> or <iframe mozapp>, then - // GetContent is the same as window.top. - if (mDocShell && mDocShell->GetIsInBrowserOrApp()) { + // If we're contained in <iframe mozbrowser>, then GetContent is the same as + // window.top. + if (mDocShell && mDocShell->GetIsBelowContentBoundary()) { return GetScriptableTop(aContent); } nsCOMPtr<nsIDocShellTreeItem> primaryContent; if (!nsContentUtils::IsCallerChrome()) { // If we're called by non-chrome code, make sure we don't return // the primary content window if the calling tab is hidden. In // such a case we return the same-type root in the hidden tab, @@ -6483,17 +6483,17 @@ nsGlobalWindow::CanClose() } NS_IMETHODIMP nsGlobalWindow::Close() { FORWARD_TO_OUTER(Close, (), NS_ERROR_NOT_INITIALIZED); if (!mDocShell || IsInModalState() || - (IsFrame() && !mDocShell->GetIsBrowserOrApp())) { + (IsFrame() && !mDocShell->GetIsContentBoundary())) { // window.close() is called on a frame in a frameset, on a window // that's already closed, or on a window for which there's // currently a modal dialog open. Ignore such calls. return NS_OK; } if (mHavePendingClose) { @@ -7002,27 +7002,26 @@ nsGlobalWindow::CacheXBLPrototypeHandler mCachedXBLPrototypeHandlers.Put(aKey, aHandler.get()); } /** * GetScriptableFrameElement is called when script reads * nsIGlobalWindow::frameElement. * * In contrast to GetRealFrameElement, GetScriptableFrameElement says that the - * window contained by an <iframe mozbrowser> or <iframe mozapp> has no frame - * element (effectively treating a mozbrowser the same as a content/chrome - * boundary). + * window contained by an <iframe mozbrowser> has no frame element + * (effectively treating a mozbrowser the same as a content/chrome boundary). */ NS_IMETHODIMP nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement) { FORWARD_TO_OUTER(GetScriptableFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED); *aFrameElement = NULL; - if (!mDocShell || mDocShell->GetIsBrowserOrApp()) { + if (!mDocShell || mDocShell->GetIsContentBoundary()) { return NS_OK; } return GetFrameElement(aFrameElement); } /** * nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper @@ -7035,17 +7034,17 @@ nsGlobalWindow::GetRealFrameElement(nsID *aFrameElement = NULL; if (!mDocShell) { return NS_OK; } nsCOMPtr<nsIDocShell> parent; - mDocShell->GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent)); + mDocShell->GetParentIgnoreBrowserFrame(getter_AddRefs(parent)); if (!parent || parent == mDocShell) { // We're at a chrome boundary, don't expose the chrome iframe // element to content code. return NS_OK; } *aFrameElement = mFrameElement;
--- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -115,17 +115,17 @@ BrowserElementParentFactory.prototype = // Maps frame elements to BrowserElementParent objects. We never look up // anything in this map; the purpose is to keep the BrowserElementParent // alive for as long as its frame element lives. this._bepMap = new WeakMap(); var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); os.addObserver(this, 'remote-browser-frame-shown', /* ownsWeak = */ true); - os.addObserver(this, 'in-process-browser-or-app-frame-shown', /* ownsWeak = */ true); + os.addObserver(this, 'in-process-browser-frame-shown', /* ownsWeak = */ true); }, _browserFramesPrefEnabled: function() { var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); try { return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF); } catch(e) { @@ -156,17 +156,17 @@ BrowserElementParentFactory.prototype = case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: if (data == BROWSER_FRAMES_ENABLED_PREF) { this._init(); } break; case 'remote-browser-frame-shown': this._observeRemoteBrowserFrameShown(subject); break; - case 'in-process-browser-or-app-frame-shown': + case 'in-process-browser-frame-shown': this._observeInProcessBrowserFrameShown(subject); break; case 'content-document-global-created': this._observeContentGlobalCreated(subject); break; } }, };
--- a/dom/browser-element/mochitest/Makefile.in +++ b/dom/browser-element/mochitest/Makefile.in @@ -85,19 +85,16 @@ MOCHITEST_FILES = \ file_browserElement_ForwardName.html \ browserElement_TargetBlank.js \ test_browserElement_inproc_TargetBlank.html \ file_browserElement_TargetBlank.html \ browserElement_PromptCheck.js \ test_browserElement_inproc_PromptCheck.html \ browserElement_PromptConfirm.js \ test_browserElement_inproc_PromptConfirm.html \ - browserElement_CookiesNotThirdParty.js \ - file_browserElement_CookiesNotThirdParty.html \ - test_browserElement_inproc_CookiesNotThirdParty.html \ browserElement_Close.js \ test_browserElement_inproc_Close.html \ browserElement_CloseFromOpener.js \ test_browserElement_inproc_CloseFromOpener.html \ file_browserElement_CloseFromOpener.html \ browserElement_CloseApp.js \ test_browserElement_inproc_CloseApp.html \ file_browserElement_CloseApp.html \ @@ -194,17 +191,16 @@ MOCHITEST_FILES += \ test_browserElement_oop_FirstPaint.html \ test_browserElement_oop_Alert.html \ test_browserElement_oop_AlertInFrame.html \ test_browserElement_oop_TargetTop.html \ test_browserElement_oop_ForwardName.html \ test_browserElement_oop_TargetBlank.html \ test_browserElement_oop_PromptCheck.html \ test_browserElement_oop_PromptConfirm.html \ - test_browserElement_oop_CookiesNotThirdParty.html \ test_browserElement_oop_Close.html \ test_browserElement_oop_CloseFromOpener.html \ test_browserElement_oop_CloseApp.html \ test_browserElement_oop_OpenWindow.html \ test_browserElement_oop_OpenWindowInFrame.html \ test_browserElement_oop_OpenWindowRejected.html \ test_browserElement_oop_OpenWindowDifferentOrigin.html \ test_browserElement_oop_OpenNamed.html \
deleted file mode 100644 --- a/dom/browser-element/mochitest/browserElement_CookiesNotThirdParty.js +++ /dev/null @@ -1,50 +0,0 @@ -/* Any copyright is dedicated to the public domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -// Bug 806127 - Test that cookies set by <iframe mozbrowser> are not considered -// third-party. -"use strict"; - -SimpleTest.waitForExplicitFinish(); - -function runTest() { - browserElementTestHelpers.setEnabledPref(true); - browserElementTestHelpers.addPermission(); - - const innerPage = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html'; - - var iframe = document.createElement('iframe'); - iframe.mozbrowser = true; - - iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { - if (e.detail.message == 'next') { - iframe.src = innerPage + '?step=2'; - return; - } - - if (e.detail.message.startsWith('success:')) { - ok(true, e.detail.message); - return; - } - - if (e.detail.message.startsWith('failure:')) { - ok(false, e.detail.message); - return; - } - - if (e.detail.message == 'finish') { - SimpleTest.finish(); - } - }); - - // innerPage will set a cookie and then alert('next'). We'll load - // innerPage?step=2. That page will check that the cooke exists (despite the - // fact that we've disabled third-party cookies) and alert('success:') or - // alert('failure:'), as appropriate. Finally, the page will - // alert('finish'); - iframe.src = innerPage; - document.body.appendChild(iframe); -} - -// Disable third-party cookies for this test. -SpecialPowers.pushPrefEnv({'set': [['network.cookie.cookieBehavior', 1]]}, runTest);
deleted file mode 100644 --- a/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html +++ /dev/null @@ -1,25 +0,0 @@ -<html> -<body> -file_browserElement_CookiesNotThirdParty.html - -<script type='text/javascript;version=1.7'> -if (location.search != '?step=2') { - // Step 1: Set a cookie. - document.cookie = 'file_browserElement_CookiesNotThirdParty'; - alert('next'); -} -else { - // Step 2: Read the cookie. - if (document.cookie == 'file_browserElement_CookiesNotThirdParty') { - alert('success: got the correct cookie'); - } - else { - alert('failure: got unexpected cookie: "' + document.cookie + '"'); - } - - alert('finish'); -} -</script> - -</body> -</html>
deleted file mode 100644 --- a/dom/browser-element/mochitest/test_browserElement_inproc_CookiesNotThirdParty.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test for Bug 806127</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <script type="application/javascript" src="browserElementTestHelpers.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<script type="application/javascript;version=1.7" src="browserElement_CookiesNotThirdParty.js"> -</script> -</body> -</html> \ No newline at end of file
deleted file mode 100644 --- a/dom/browser-element/mochitest/test_browserElement_oop_CookiesNotThirdParty.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test for Bug 806127</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <script type="application/javascript" src="browserElementTestHelpers.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<script type="application/javascript;version=1.7" src="browserElement_CookiesNotThirdParty.js"> -</script> -</body> -</html> \ No newline at end of file
--- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -17,17 +17,16 @@ #include "nsIScriptError.h" #include "nsIScriptObjectPrincipal.h" #include "nsIScriptSecurityManager.h" #include "nsISHEntry.h" #include "nsISimpleEnumerator.h" #include "nsITimer.h" #include "mozilla/dom/file/FileService.h" -#include "mozilla/dom/TabContext.h" #include "mozilla/LazyIdleThread.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "mozilla/storage.h" #include "nsAppDirectoryServiceDefs.h" #include "nsContentUtils.h" #include "nsCRTGlue.h" #include "nsDirectoryServiceUtils.h" @@ -193,16 +192,23 @@ GetOriginPatternString(uint32_t aAppId, "Origin doesn't match parameters!"); } #endif _retval = aOrigin; } void +GetOriginPatternString(uint32_t aAppId, nsAutoCString& _retval) +{ + return GetOriginPatternString(aAppId, IgnoreMozBrowser, EmptyCString(), + _retval); +} + +void GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly, nsAutoCString& _retval) { return GetOriginPatternString(aAppId, aBrowserOnly ? MozBrowser : NotMozBrowser, EmptyCString(), _retval); } @@ -613,39 +619,43 @@ IndexedDatabaseManager::FireWindowOnErro do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); return consoleService->LogMessage(scriptError); } // static bool -IndexedDatabaseManager::TabContextMayAccessOrigin(const TabContext& aContext, - const nsACString& aOrigin) +IndexedDatabaseManager::OriginMatchesApp(const nsACString& aOrigin, + uint32_t aAppId) { NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!"); + NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, + "Bad appId!"); nsAutoCString pattern; - GetOriginPatternString(aContext.OwnOrContainingAppId(), - aContext.IsBrowserElement(), - pattern); - if (PatternMatchesOrigin(pattern, aOrigin)) { - return true; - } - - // If aContext is not for a browser element, then it's allowed to access - // is-browser-element origins. - if (!aContext.IsBrowserElement()) { - GetOriginPatternString(aContext.OwnOrContainingAppId(), - /* isBrowser */ true, - pattern); - return PatternMatchesOrigin(pattern, aOrigin); - } - - return false; + GetOriginPatternString(aAppId, pattern); + + return PatternMatchesOrigin(pattern, aOrigin); +} + +// static +bool +IndexedDatabaseManager::OriginMatchesApp(const nsACString& aOrigin, + uint32_t aAppId, + bool aInMozBrowser) +{ + NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!"); + NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, + "Bad appId!"); + + nsAutoCString pattern; + GetOriginPatternString(aAppId, aInMozBrowser, pattern); + + return PatternMatchesOrigin(pattern, aOrigin); } bool IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aDatabase, "Null pointer!");
--- a/dom/indexedDB/IndexedDatabaseManager.h +++ b/dom/indexedDB/IndexedDatabaseManager.h @@ -25,23 +25,16 @@ class mozIStorageQuotaCallback; class nsIAtom; class nsIFile; class nsITimer; class nsPIDOMWindow; class nsEventChainPostVisitor; -namespace mozilla { -namespace dom { -class TabContext; -} -} - - BEGIN_INDEXEDDB_NAMESPACE class AsyncConnectionHelper; class CheckQuotaHelper; class FileManager; class IDBDatabase; class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager, @@ -206,18 +199,23 @@ public: GetDatabaseId(const nsACString& aOrigin, const nsAString& aName); static nsresult FireWindowOnError(nsPIDOMWindow* aOwner, nsEventChainPostVisitor& aVisitor); static bool - TabContextMayAccessOrigin(const TabContext& aContext, - const nsACString& aOrigin); + OriginMatchesApp(const nsACString& aOrigin, + uint32_t aAppId); + + static bool + OriginMatchesApp(const nsACString& aOrigin, + uint32_t aAppId, + bool aInMozBrowser); private: IndexedDatabaseManager(); ~IndexedDatabaseManager(); nsresult AcquireExclusiveAccess(const nsACString& aOrigin, IDBDatabase* aDatabase, AsyncConnectionHelper* aHelper,
--- a/dom/indexedDB/test/Makefile.in +++ b/dom/indexedDB/test/Makefile.in @@ -99,24 +99,21 @@ MOCHITEST_FILES = \ test_transaction_lifetimes.html \ test_transaction_lifetimes_nested.html \ test_transaction_ordering.html \ test_setVersion.html \ test_setVersion_abort.html \ test_setVersion_events.html \ test_setVersion_exclusion.html \ test_unique_index_update.html \ - test_webapp_clearBrowserData_inproc_oop.html \ - test_webapp_clearBrowserData_oop_inproc.html \ - test_webapp_clearBrowserData_inproc_inproc.html \ + test_webapp_clearBrowserData.html \ third_party_iframe1.html \ third_party_iframe2.html \ test_app_isolation_inproc.html \ test_app_isolation_oop.html \ - webapp_clearBrowserData.js \ webapp_clearBrowserData_appFrame.html \ webapp_clearBrowserData_browserFrame.html \ $(NULL) # test_writer_starvation.html disabled for infinite loops, bug 595368 ifeq (browser,$(MOZ_BUILD_APP)) MOCHITEST_BROWSER_FILES = \
rename from dom/indexedDB/test/webapp_clearBrowserData.js rename to dom/indexedDB/test/test_webapp_clearBrowserData.html --- a/dom/indexedDB/test/webapp_clearBrowserData.js +++ b/dom/indexedDB/test/test_webapp_clearBrowserData.html @@ -1,147 +1,137 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html> +<head> + <title>Indexed Database Clear Browser Data Test</title> -"use strict"; + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + + <script type="text/javascript;version=1.7"> + "use strict"; -const appDomain = "example.org"; -const manifestURL = - location.protocol + "//" + appDomain + "/manifest.webapp"; + const appDomain = "example.org"; + const manifestURL = + location.protocol + "//" + appDomain + "/manifest.webapp"; -function testSteps() -{ - const objectStoreName = "foo"; - const testKey = 1; - const testValue = objectStoreName; + function testSteps() + { + const objectStoreName = "foo"; + const testKey = 1; + const testValue = objectStoreName; + + let request = indexedDB.open(window.location.pathname, 1); + request.onerror = errorHandler; + request.onupgradeneeded = grabEventAndContinueHandler; + request.onsuccess = unexpectedSuccessHandler; + let event = yield; - // Determine whether the app and browser frames should be in or - // out-of-process. - let remote_app, remote_browser; - if (window.location.href.indexOf("inproc_oop") != -1) { - remote_app = false; - remote_browser = true; - } - else if (window.location.href.indexOf("oop_inproc") != -1) { - remote_app = true; - remote_browser = false; - } - else if (window.location.href.indexOf("inproc_inproc") != -1) { - remote_app = false; - remote_browser = false; - } - else { - ok(false, "Bad test filename!"); - return; - } + let db = event.target.result; + db.onerror = errorHandler; + db.onversionchange = function(event) { + event.target.close(); + } + + let objectStore = db.createObjectStore(objectStoreName); + objectStore.add(testValue, testKey); + + request.onsuccess = grabEventAndContinueHandler; + event = yield; + + let srcURL = + location.protocol + "//" + appDomain + + location.pathname.replace("test_webapp_clearBrowserData.html", + "webapp_clearBrowserData_appFrame.html"); - let request = indexedDB.open(window.location.pathname, 1); - request.onerror = errorHandler; - request.onupgradeneeded = grabEventAndContinueHandler; - request.onsuccess = unexpectedSuccessHandler; - let event = yield; - - let db = event.target.result; - db.onerror = errorHandler; - db.onversionchange = function(event) { - event.target.close(); - } - - let objectStore = db.createObjectStore(objectStoreName); - objectStore.add(testValue, testKey); + let iframe = document.createElement("iframe"); + iframe.setAttribute("mozbrowser", ""); + iframe.setAttribute("mozapp", manifestURL); + iframe.setAttribute("src", srcURL); + iframe.setAttribute("remote", "true"); + iframe.addEventListener("mozbrowsershowmodalprompt", function(event) { + let message = JSON.parse(event.detail.message); + switch (message.type) { + case "info": + case "ok": + window[message.type].apply(window, message.args); + break; + case "done": + continueToNextStepSync(); + break; + default: + throw "unknown message"; + } + }); - request.onsuccess = grabEventAndContinueHandler; - event = yield; - - // We need to send both remote_browser and remote_app in the querystring - // because webapp_clearBrowserData_appFrame uses the path + querystring to - // create and open a database which it checks no other test has touched. If - // we sent only remote_browser, then we wouldn't be able to test both - // (remote_app==false, remote_browser==false) and (remote_app==true, - // remote_browser==false). - let srcURL = location.protocol + "//" + appDomain + - location.pathname.substring(0, location.pathname.lastIndexOf('/')) + - "/webapp_clearBrowserData_appFrame.html?" + - "remote_browser=" + remote_browser + "&" + - "remote_app=" + remote_app; + info("loading app frame"); - let iframe = document.createElement("iframe"); - iframe.setAttribute("mozbrowser", ""); - iframe.setAttribute("mozapp", manifestURL); - iframe.setAttribute("src", srcURL); - iframe.setAttribute("remote", remote_app); - iframe.addEventListener("mozbrowsershowmodalprompt", function(event) { - let message = JSON.parse(event.detail.message); - switch (message.type) { - case "info": - case "ok": - window[message.type].apply(window, message.args); - break; - case "done": - continueToNextStepSync(); - break; - default: - throw "unknown message"; - } - }); + document.body.appendChild(iframe); + yield; + + request = indexedDB.open(window.location.pathname, 1); + request.onerror = errorHandler; + request.onupgradeneeded = unexpectedSuccessHandler; + request.onsuccess = grabEventAndContinueHandler; + event = yield; + + db = event.target.result; + db.onerror = errorHandler; - info("loading app frame"); + objectStore = + db.transaction(objectStoreName).objectStore(objectStoreName); + objectStore.get(testKey).onsuccess = grabEventAndContinueHandler; + event = yield; - document.body.appendChild(iframe); - yield; + ok(testValue == event.target.result, "data still exists"); - request = indexedDB.open(window.location.pathname, 1); - request.onerror = errorHandler; - request.onupgradeneeded = unexpectedSuccessHandler; - request.onsuccess = grabEventAndContinueHandler; - event = yield; + finishTest(); + yield; + } - db = event.target.result; - db.onerror = errorHandler; - - objectStore = - db.transaction(objectStoreName).objectStore(objectStoreName); - objectStore.get(testKey).onsuccess = grabEventAndContinueHandler; - event = yield; - - ok(testValue == event.target.result, "data still exists"); + function start() + { + if (!SpecialPowers.isMainProcess()) { + todo(false, "Test disabled in child processes, for now"); + SimpleTest.finish(); + return; + } - finishTest(); - yield; -} + SpecialPowers.addPermission("browser", true, document); + SpecialPowers.addPermission("browser", true, { manifestURL: manifestURL, + isInBrowserElement: false }); + SpecialPowers.addPermission("embed-apps", true, document); -function start() -{ - if (!SpecialPowers.isMainProcess()) { - todo(false, "Test disabled in child processes, for now"); - SimpleTest.finish(); - return; - } + let Webapps = {}; + SpecialPowers.wrap(Components) + .utils.import("resource://gre/modules/Webapps.jsm", Webapps); + let appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry); - SpecialPowers.addPermission("browser", true, document); - SpecialPowers.addPermission("browser", true, { manifestURL: manifestURL, - isInBrowserElement: false }); - SpecialPowers.addPermission("embed-apps", true, document); + let originalAllAppsLaunchable = appRegistry.allAppsLaunchable; + appRegistry.allAppsLaunchable = true; + + window.addEventListener("unload", function cleanup(event) { + if (event.target == document) { + window.removeEventListener("unload", cleanup, false); - let Webapps = {}; - SpecialPowers.wrap(Components) - .utils.import("resource://gre/modules/Webapps.jsm", Webapps); - let appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry); - - let originalAllAppsLaunchable = appRegistry.allAppsLaunchable; - appRegistry.allAppsLaunchable = true; - - window.addEventListener("unload", function cleanup(event) { - if (event.target == document) { - window.removeEventListener("unload", cleanup, false); + SpecialPowers.removePermission("browser", location.href); + SpecialPowers.removePermission("browser", + location.protocol + "//" + appDomain); + SpecialPowers.removePermission("embed-apps", location.href); + appRegistry.allAppsLaunchable = originalAllAppsLaunchable; + } + }, false); - SpecialPowers.removePermission("browser", location.href); - SpecialPowers.removePermission("browser", - location.protocol + "//" + appDomain); - SpecialPowers.removePermission("embed-apps", location.href); - appRegistry.allAppsLaunchable = originalAllAppsLaunchable; + SpecialPowers.pushPrefEnv({ + "set": [["dom.mozBrowserFramesEnabled", true]] + }, runTest); } - }, false); + </script> - SpecialPowers.pushPrefEnv({ - "set": [["dom.mozBrowserFramesEnabled", true]] - }, runTest); -} + <script type="text/javascript;version=1.7" src="helpers.js"></script> +</head> + +<body onload="start();"></body> + +</html>
deleted file mode 100644 --- a/dom/indexedDB/test/test_webapp_clearBrowserData_inproc_inproc.html +++ /dev/null @@ -1,33 +0,0 @@ -<!-- - Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ ---> - -<!-- - We have three similar tests here which each check that indexedDB data for a - browser inside an app is cleared upon request: - - 1) test_webapp_clearBrowserData_inproc_oop.html, - 2) test_webapp_clearBrowserData_oop_inproc.html, and - 3) test_webapp_clearBrowserData_inproc_inproc.html. - - The only difference between these is that the first constructs an in-process - app frame which contains an out-of-process browser frame, the second - constructs an out-of-process app frame which contains an in-process browser - frame, and the third has both frames in process. - - The tests share all their JS code. webapp_clearBrowserData.js determines - which frames are in- and out-of-process by looking at the test's filename. ---> - -<html> -<head> - <title>Indexed Database Clear Browser Data Test inproc/inproc</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> - <script type="text/javascript;version=1.7" src="webapp_clearBrowserData.js"></script> - <script type="text/javascript;version=1.7" src="helpers.js"></script> -</head> -<body onload="start();"> -</body> -</html>
deleted file mode 100644 --- a/dom/indexedDB/test/test_webapp_clearBrowserData_inproc_oop.html +++ /dev/null @@ -1,21 +0,0 @@ -<!-- - Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ ---> - -<!-- - See comment in test_webapp_clearBrowserData_inproc_inproc.html for an - explanation of what's going on here. ---> - -<html> -<head> - <title>Indexed Database Clear Browser Data Test inproc/oop</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <script type="text/javascript;version=1.7" src="webapp_clearBrowserData.js"></script> - <script type="text/javascript;version=1.7" src="helpers.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body onload="start();"> -</body> -</html>
deleted file mode 100644 --- a/dom/indexedDB/test/test_webapp_clearBrowserData_oop_inproc.html +++ /dev/null @@ -1,21 +0,0 @@ -<!-- - Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ ---> - -<!-- - See comment in test_webapp_clearBrowserData_inproc_inproc.html for an - explanation of what's going on here. ---> - -<html> -<head> - <title>Indexed Database Clear Browser Data Test oop/inproc</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <script type="text/javascript;version=1.7" src="webapp_clearBrowserData.js"></script> - <script type="text/javascript;version=1.7" src="helpers.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body onload="start();"> -</body> -</html>
--- a/dom/indexedDB/test/webapp_clearBrowserData_appFrame.html +++ b/dom/indexedDB/test/webapp_clearBrowserData_appFrame.html @@ -28,33 +28,18 @@ window.onerror = ok.bind(window, false); function testSteps() { const objectStoreName = "foo"; const testKey = 1; const testValue = objectStoreName; - const dbName = location.pathname + location.search; - // Determine whether our parent iframe asked us to create a remote - // browser frame here. - let remote_browser; - if (location.search.indexOf("remote_browser=true") != -1) { - remote_browser = true; - } - else if (location.search.indexOf("remote_browser=false") != -1) { - remote_browser = false; - } - else { - ok(false, "Expected remote_browser={true,false} in query string."); - return; - } - - let request = indexedDB.open(dbName, 1); + let request = indexedDB.open(window.location.pathname, 1); request.onerror = errorHandler; request.onupgradeneeded = grabEventAndContinueHandler; request.onsuccess = unexpectedSuccessHandler; let event = yield; let db = event.target.result; db.onerror = errorHandler; db.onversionchange = function(event) { @@ -73,21 +58,17 @@ db.transaction(objectStoreName).objectStore(objectStoreName); objectStore.get(testKey).onsuccess = grabEventAndContinueHandler; event = yield; ok(testValue == event.target.result, "data exists"); let iframe = document.createElement("iframe"); iframe.setAttribute("mozbrowser", ""); - // Send our querystring to the subframe because - // webapp_clearBrowserData_browserFrame uses its pathname + querystring to - // open a database which it assumes hasn't been touched by another test. - iframe.setAttribute("src", "webapp_clearBrowserData_browserFrame.html" + location.search); - iframe.setAttribute("remote", remote_browser); + iframe.setAttribute("src", "webapp_clearBrowserData_browserFrame.html"); iframe.addEventListener("mozbrowsershowmodalprompt", function(event) { let message = JSON.parse(event.detail.message); switch (message.type) { case "block": info("blocking browserFrame"); event.preventDefault(); let request = navigator.mozApps.getSelf(); @@ -110,17 +91,17 @@ } }); info("loading browser frame"); document.body.appendChild(iframe); yield; - request = indexedDB.open(dbName, 1); + request = indexedDB.open(window.location.pathname, 1); request.onerror = errorHandler; request.onupgradeneeded = unexpectedSuccessHandler; request.onsuccess = grabEventAndContinueHandler; event = yield; db = event.target.result; db.onerror = errorHandler;
--- a/dom/indexedDB/test/webapp_clearBrowserData_browserFrame.html +++ b/dom/indexedDB/test/webapp_clearBrowserData_browserFrame.html @@ -38,19 +38,18 @@ window.onerror = ok.bind(window, false); function testSteps() { const objectStoreName = "foo"; const testKey = 1; const testValue = objectStoreName; - const dbName = window.location.pathname + window.location.search; - let request = indexedDB.open(dbName, 1); + let request = indexedDB.open(window.location.pathname, 1); request.onerror = errorHandler; request.onupgradeneeded = grabEventAndContinueHandler; request.onsuccess = unexpectedSuccessHandler; let event = yield; let db = event.target.result; db.onerror = errorHandler; db.onversionchange = function(event) { @@ -69,17 +68,17 @@ db.transaction(objectStoreName).objectStore(objectStoreName); objectStore.get(testKey).onsuccess = grabEventAndContinueHandler; event = yield; ok(testValue == event.target.result, "data exists"); block(); - request = indexedDB.open(dbName, 1); + request = indexedDB.open(window.location.pathname, 1); request.onerror = errorHandler; request.onupgradeneeded = grabEventAndContinueHandler; request.onsuccess = unexpectedSuccessHandler; event = yield; ok(event.type == "upgradeneeded", "db doesn't exist"); request.onsuccess = grabEventAndContinueHandler;
--- a/dom/interfaces/html/nsIMozBrowserFrame.idl +++ b/dom/interfaces/html/nsIMozBrowserFrame.idl @@ -4,42 +4,40 @@ /* 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 "nsIDOMMozBrowserFrame.idl" interface nsITabParent; -[scriptable, builtinclass, uuid(929AED00-3E15-49B7-8CA2-75003715B7E7)] +[scriptable, uuid(6f043e42-02c9-4e8f-8f8d-1b83c6102827)] interface nsIMozBrowserFrame : nsIDOMMozBrowserFrame { /** * Gets whether this frame really is a browser or app frame. * * In order to really be a browser frame, this frame's * nsIDOMMozBrowserFrame::mozbrowser attribute must be true, and the frame * may have to pass various security checks. */ - [infallible] readonly attribute boolean reallyIsBrowserOrApp; + readonly attribute boolean reallyIsBrowser; /** * Gets whether this frame really is an app frame. * * In order to really be an app frame, this frame must really be a browser * frame (this requirement will go away eventually), and the frame's mozapp * attribute must point to the manifest of a valid app. */ - [infallible] readonly attribute boolean reallyIsApp; + readonly attribute boolean reallyIsApp; /** * Gets this frame's app manifest URL, if the frame really is an app frame. * Otherwise, returns the empty string. - * - * This method is guaranteed not to fail. */ readonly attribute AString appManifestURL; /** * Normally, a frame tries to create its frame loader when its src is * modified, or its contentWindow is accessed. * * disallowCreateFrameLoader prevents the frame element from creating its
--- a/dom/ipc/AppProcessPermissions.cpp +++ b/dom/ipc/AppProcessPermissions.cpp @@ -22,17 +22,17 @@ bool AssertAppProcessPermission(PBrowserParent* aActor, const char* aPermission) { if (!aActor) { NS_WARNING("Testing permissions for null actor"); return false; } TabParent* tab = static_cast<TabParent*>(aActor); - nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp(); + nsCOMPtr<mozIApplication> app = tab->GetApp(); bool hasPermission = false; // isBrowser frames inherit their app descriptor to identify their // data storage, but they don't inherit the permissions associated // with that descriptor. if (app && !tab->IsBrowserElement()) { if (!NS_SUCCEEDED(app->HasPermission(aPermission, &hasPermission))) { hasPermission = false;
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -226,21 +226,23 @@ ConsoleListener::Observe(nsIConsoleMessa NS_ENSURE_SUCCESS(rv, rv); mChild->SendConsoleMessage(msg); return NS_OK; } ContentChild* ContentChild::sSingleton; ContentChild::ContentChild() - : TabContext() - , mID(uint64_t(-1)) + : + mID(uint64_t(-1)) #ifdef ANDROID ,mScreenSize(0, 0) #endif + , mIsForApp(false) + , mIsForBrowser(false) { // This process is a content process, so it's clearly running in // multiprocess mode! nsDebugImpl::SetMultiprocessMode("Child"); } ContentChild::~ContentChild() { @@ -294,17 +296,17 @@ ContentChild::Init(MessageLoop* aIOLoop, bool startBackground = true; SendGetProcessAttributes(&mID, &startBackground, &mIsForApp, &mIsForBrowser); hal::SetProcessPriority( GetCurrentProcId(), startBackground ? hal::PROCESS_PRIORITY_BACKGROUND: hal::PROCESS_PRIORITY_FOREGROUND); if (mIsForApp && !mIsForBrowser) { - SetProcessName(NS_LITERAL_STRING("(Preallocated app)")); + SetProcessName(NS_LITERAL_STRING("(App)")); } else { SetProcessName(NS_LITERAL_STRING("Browser")); } return true; } void @@ -482,31 +484,27 @@ ContentChild::AllocPImageBridge(mozilla: } static void FirstIdle(void) { ContentChild::GetSingleton()->SendFirstIdle(); } PBrowserChild* -ContentChild::AllocPBrowser(const IPCTabContext& aContext, - const uint32_t& aChromeFlags) +ContentChild::AllocPBrowser(const uint32_t& aChromeFlags, + const bool& aIsBrowserElement, const AppId& aApp) { static bool firstIdleTaskPosted = false; if (!firstIdleTaskPosted) { MessageLoop::current()->PostIdleTask(FROM_HERE, NewRunnableFunction(FirstIdle)); firstIdleTaskPosted = true; } - // We'll happily accept any kind of IPCTabContext here; we don't need to - // check that it's of a certain type for security purposes, because we - // believe whatever the parent process tells us. - - nsRefPtr<TabChild> child = TabChild::Create(TabContext(aContext), aChromeFlags); - + nsRefPtr<TabChild> child = + TabChild::Create(aChromeFlags, aIsBrowserElement, aApp.get_uint32_t()); // The ref here is released below. return child.forget().get(); } bool ContentChild::DeallocPBrowser(PBrowserChild* iframe) { TabChild* child = static_cast<TabChild*>(iframe);
--- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -4,17 +4,16 @@ * 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 mozilla_dom_ContentChild_h #define mozilla_dom_ContentChild_h #include "mozilla/Attributes.h" #include "mozilla/dom/PContentChild.h" -#include "mozilla/dom/TabContext.h" #include "mozilla/dom/ipc/Blob.h" #include "nsTArray.h" #include "nsIConsoleListener.h" struct ChromePackage; class nsIDOMBlob; class nsIObserver; @@ -36,17 +35,16 @@ namespace dom { class AlertObserver; class PrefObserver; class ConsoleListener; class PStorageChild; class ClonedMessageData; class ContentChild : public PContentChild - , public TabContext { typedef mozilla::dom::ClonedMessageData ClonedMessageData; typedef mozilla::ipc::OptionalURIParams OptionalURIParams; typedef mozilla::ipc::URIParams URIParams; public: ContentChild(); virtual ~ContentChild(); @@ -75,18 +73,19 @@ public: PCompositorChild* AllocPCompositor(mozilla::ipc::Transport* aTransport, base::ProcessId aOtherProcess) MOZ_OVERRIDE; PImageBridgeChild* AllocPImageBridge(mozilla::ipc::Transport* aTransport, base::ProcessId aOtherProcess) MOZ_OVERRIDE; - virtual PBrowserChild* AllocPBrowser(const IPCTabContext &aContext, - const uint32_t &chromeFlags); + virtual PBrowserChild* AllocPBrowser(const uint32_t& aChromeFlags, + const bool& aIsBrowserElement, + const AppId& aAppId); virtual bool DeallocPBrowser(PBrowserChild*); virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequest(const DeviceStorageParams&); virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestChild*); virtual PBlobChild* AllocPBlob(const BlobConstructorParams& aParams); virtual bool DeallocPBlob(PBlobChild*); @@ -191,16 +190,19 @@ public: #endif // Get the directory for IndexedDB files. We query the parent for this and // cache the value nsString &GetIndexedDBPath(); uint64_t GetID() { return mID; } + bool IsForApp() { return mIsForApp; } + bool IsForBrowser() { return mIsForBrowser; } + BlobChild* GetOrCreateActorForBlob(nsIDOMBlob* aBlob); private: virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; virtual void ProcessingError(Result what) MOZ_OVERRIDE; /**
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -50,16 +50,17 @@ #include "nsConsoleService.h" #include "nsDebugImpl.h" #include "nsDirectoryServiceDefs.h" #include "nsDOMFile.h" #include "nsExternalHelperAppService.h" #include "nsFrameMessageManager.h" #include "nsHashPropertyBag.h" #include "nsIAlertsService.h" +#include "nsIAppsService.h" #include "nsIClipboard.h" #include "nsIDOMApplicationRegistry.h" #include "nsIDOMGeoGeolocation.h" #include "nsIDOMWindow.h" #include "nsIFilePicker.h" #include "nsIMemoryReporter.h" #include "nsIObserverService.h" #include "nsIPresShell.h" @@ -311,74 +312,90 @@ AppNeedsInheritedOSPrivileges(mozIApplic } else if (needsInherit) { return true; } } return false; } /*static*/ TabParent* -ContentParent::CreateBrowserOrApp(const TabContext& aContext) +ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement) { - if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) { - if (ContentParent* cp = GetNewOrUsed(aContext.IsBrowserElement())) { - nsRefPtr<TabParent> tp(new TabParent(aContext)); - PBrowserParent* browser = cp->SendPBrowserConstructor( - tp.forget().get(), // DeallocPBrowserParent() releases this ref. - aContext.AsIPCTabContext(), - /* chromeFlags */ 0); - return static_cast<TabParent*>(browser); + // We currently don't set the <app> ancestor for <browser> content + // correctly. This assertion is to notify the person who fixes + // this code that they need to reevaluate places here where we may + // make bad assumptions based on that bug. + MOZ_ASSERT(!aApp || !aIsBrowserElement); + + if (!aApp) { + if (ContentParent* cp = GetNewOrUsed(aIsBrowserElement)) { + nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement)); + return static_cast<TabParent*>( + cp->SendPBrowserConstructor( + // DeallocPBrowserParent() releases the ref we take here + tp.forget().get(), + /*chromeFlags*/0, + aIsBrowserElement, nsIScriptSecurityManager::NO_APP_ID)); } return nullptr; } - // If we got here, we have an app and we're not a browser element. ownApp - // shouldn't be null, because we otherwise would have gone into the - // !HasOwnApp() branch above. - nsCOMPtr<mozIApplication> ownApp = aContext.GetOwnApp(); - if (!gAppContentParents) { gAppContentParents = new nsDataHashtable<nsStringHashKey, ContentParent*>(); gAppContentParents->Init(); } // Each app gets its own ContentParent instance. nsAutoString manifestURL; - if (NS_FAILED(ownApp->GetManifestURL(manifestURL))) { + if (NS_FAILED(aApp->GetManifestURL(manifestURL))) { NS_ERROR("Failed to get manifest URL"); return nullptr; } + nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); + if (!appsService) { + NS_ERROR("Failed to get apps service"); + return nullptr; + } + + // Send the local app ID to the new TabChild so it knows what app + // it is. + uint32_t appId; + if (NS_FAILED(appsService->GetAppLocalIdByManifestURL(manifestURL, &appId))) { + NS_ERROR("Failed to get local app ID"); + return nullptr; + } + nsRefPtr<ContentParent> p = gAppContentParents->Get(manifestURL); if (!p) { - if (AppNeedsInheritedOSPrivileges(ownApp)) { - p = new ContentParent(manifestURL, /* isBrowserElement = */ false, + if (AppNeedsInheritedOSPrivileges(aApp)) { + p = new ContentParent(manifestURL, aIsBrowserElement, base::PRIVILEGES_INHERIT); p->Init(); } else { p = MaybeTakePreallocatedAppProcess(); if (p) { p->SetManifestFromPreallocated(manifestURL); } else { NS_WARNING("Unable to use pre-allocated app process"); - p = new ContentParent(manifestURL, /* isBrowserElement = */ false, + p = new ContentParent(manifestURL, aIsBrowserElement, base::PRIVILEGES_DEFAULT); p->Init(); } } gAppContentParents->Put(manifestURL, p); } - nsRefPtr<TabParent> tp = new TabParent(aContext); - PBrowserParent* browser = p->SendPBrowserConstructor( - tp.forget().get(), // DeallocPBrowserParent() releases this ref. - aContext.AsIPCTabContext(), - /* chromeFlags */ 0); - return static_cast<TabParent*>(browser); + nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement)); + return static_cast<TabParent*>( + // DeallocPBrowserParent() releases the ref we take here + p->SendPBrowserConstructor(tp.forget().get(), + /*chromeFlags*/0, + aIsBrowserElement, appId)); } static PLDHashOperator AppendToTArray(const nsAString& aKey, ContentParent* aValue, void* aArray) { nsTArray<ContentParent*> *array = static_cast<nsTArray<ContentParent*>*>(aArray); array->AppendElement(aValue); @@ -1141,47 +1158,40 @@ ContentParent::RecvGetXPCOMProcessAttrib NS_ASSERTION(io, "No IO service?"); DebugOnly<nsresult> rv = io->GetOffline(aIsOffline); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed getting offline?"); return true; } PBrowserParent* -ContentParent::AllocPBrowser(const IPCTabContext& aContext, - const uint32_t &aChromeFlags) +ContentParent::AllocPBrowser(const uint32_t& aChromeFlags, + const bool& aIsBrowserElement, const AppId& aApp) { - unused << aChromeFlags; + // We only use this Alloc() method when the content processes asks + // us to open a window. In that case, we're expecting to see the + // opening PBrowser as its app descriptor, and we can trust the data + // associated with that PBrowser since it's fully owned by this + // process. + if (AppId::TPBrowserParent != aApp.type()) { + NS_ERROR("Content process attempting to forge app ID"); + return nullptr; + } + TabParent* opener = static_cast<TabParent*>(aApp.get_PBrowserParent()); - // We don't trust the IPCTabContext we receive from the child, so we'll bail - // if we receive an IPCTabContext that's not a PopupIPCTabContext. - // (PopupIPCTabContext lets the child process prove that it has access to - // the app it's trying to open.) - if (aContext.type() != IPCTabContext::TPopupIPCTabContext) { - NS_ERROR("Unexpected IPCTabContext type. Aborting AllocPBrowser."); + // Popup windows of isBrowser frames are isBrowser if the parent + // isBrowser. Allocating a !isBrowser frame with same app ID + // would allow the content to access data it's not supposed to. + if (opener && opener->IsBrowserElement() && !aIsBrowserElement) { + NS_ERROR("Content process attempting to escalate data access privileges"); return nullptr; } - const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext(); - TabParent* opener = static_cast<TabParent*>(popupContext.openerParent()); - if (!opener) { - NS_ERROR("Got null opener from child; aborting AllocPBrowser."); - return nullptr; - } - - // Popup windows of isBrowser frames must be isBrowser if the parent - // isBrowser. Allocating a !isBrowser frame with same app ID would allow - // the content to access data it's not supposed to. - if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) { - NS_ERROR("Child trying to escalate privileges! Aborting AllocPBrowser."); - return nullptr; - } - - TabParent* parent = new TabParent(TabContext(aContext)); - + TabParent* parent = new TabParent(opener ? opener->GetApp() : nullptr, + aIsBrowserElement); // We release this ref in DeallocPBrowser() NS_ADDREF(parent); return parent; } bool ContentParent::DeallocPBrowser(PBrowserParent* frame) {
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -6,17 +6,16 @@ #ifndef mozilla_dom_ContentParent_h #define mozilla_dom_ContentParent_h #include "base/waitable_event_watcher.h" #include "mozilla/dom/PContentParent.h" #include "mozilla/dom/PMemoryReportRequestParent.h" -#include "mozilla/dom/TabContext.h" #include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/dom/ipc/Blob.h" #include "mozilla/Attributes.h" #include "nsFrameMessageManager.h" #include "nsIObserver.h" #include "nsIThreadInternal.h" #include "nsNetUtil.h" @@ -70,19 +69,25 @@ public: */ static void StartUp(); /** Shut down the content-process machinery. */ static void ShutDown(); static ContentParent* GetNewOrUsed(bool aForBrowserElement = false); /** - * Get or create a content process for the given TabContext. + * Get or create a content process for the given app descriptor, + * which may be null. This function will assign processes to app + * or non-app browsers by internal heuristics. + * + * Currently apps are given their own process, and browser tabs + * share processes. */ - static TabParent* CreateBrowserOrApp(const TabContext& aContext); + static TabParent* CreateBrowser(mozIApplication* aApp, + bool aIsBrowserFrame); static void GetAll(nsTArray<ContentParent*>& aArray); NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER NS_DECL_NSITHREADOBSERVER NS_DECL_NSIDOMGEOPOSITIONCALLBACK @@ -179,18 +184,19 @@ private: base::ProcessId aOtherProcess) MOZ_OVERRIDE; virtual bool RecvGetProcessAttributes(uint64_t* aId, bool* aStartBackground, bool* aIsForApp, bool* aIsForBrowser) MOZ_OVERRIDE; virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE; - virtual PBrowserParent* AllocPBrowser(const IPCTabContext& aContext, - const uint32_t& aChromeFlags); + virtual PBrowserParent* AllocPBrowser(const uint32_t& aChromeFlags, + const bool& aIsBrowserElement, + const AppId& aApp); virtual bool DeallocPBrowser(PBrowserParent* frame); virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&); virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestParent*); virtual PBlobParent* AllocPBlob(const BlobConstructorParams& aParams); virtual bool DeallocPBlob(PBlobParent*);
--- a/dom/ipc/Makefile.in +++ b/dom/ipc/Makefile.in @@ -37,17 +37,16 @@ EXPORTS_mozilla/dom = \ ContentParent.h \ ContentProcess.h \ CrashReporterChild.h \ CrashReporterParent.h \ PermissionMessageUtils.h \ StructuredCloneUtils.h \ TabParent.h \ TabChild.h \ - TabContext.h \ TabMessageUtils.h \ $(NULL) EXPORTS_mozilla/dom/ipc = \ Blob.h \ ProcessPriorityManager.h \ nsIRemoteBlob.h \ $(NULL) @@ -60,17 +59,16 @@ CPPSRCS = \ ContentChild.cpp \ CrashReporterParent.cpp \ CrashReporterChild.cpp \ PermissionMessageUtils.cpp \ ProcessPriorityManager.cpp \ StructuredCloneUtils.cpp \ TabParent.cpp \ TabChild.cpp \ - TabContext.cpp \ TabMessageUtils.cpp \ $(NULL) ifdef MOZ_SYDNEYAUDIO EXPORTS_mozilla/dom += \ AudioChild.h \ AudioParent.h \ $(NULL)
--- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -130,70 +130,19 @@ struct MysteryBlobConstructorParams union BlobConstructorParams { NormalBlobConstructorParams; FileBlobConstructorParams; SlicedBlobConstructorParams; MysteryBlobConstructorParams; }; -// An IPCTabContext which corresponds to a PBrowser opened by a child when it -// receives window.open(). -// -// If isBrowserElement is false, this PopupIPCTabContext corresponds to an app -// frame, and the frame's app-id and app-frame-owner-app-id will be equal to the -// opener's values. -// -// If isBrowserElement is true, the frame's browserFrameOwnerAppId will be equal -// to the opener's app-id. -// -// It's an error to set isBrowserElement == false if opener is a browser -// element. Such a PopupIPCTabContext should be rejected by code which receives -// it. -struct PopupIPCTabContext -{ - PBrowser opener; - bool isBrowserElement; -}; - -// An IPCTabContext which corresponds to an app frame. -struct AppFrameIPCTabContext -{ - // The ID of the app this frame corresponds to. May be NO_APP_ID. - uint32_t ownAppId; - - // The ID of the app containing this frame. May be NO_APP_ID. - uint32_t appFrameOwnerAppId; -}; - -// An IPCTabContext which corresponds to a browser frame. -struct BrowserFrameIPCTabContext -{ - // The ID of the app which contains this browser frame. May be NO_APP_ID. - uint32_t browserFrameOwnerAppId; -}; - -// This is equivalent to AppFrameIPCTabContext with all fields set to NO_APP_ID. -struct VanillaFrameIPCTabContext -{}; - -// IPCTabContext is an analog to mozilla::dom::TabContext. Both specify an -// iframe/PBrowser's own and containing app-ids and tell you whether the -// iframe/PBrowser is a browser frame. But only IPCTabContext is allowed to -// travel over IPC. -// -// We need IPCTabContext (specifically, PopupIPCTabContext) to prevent a -// privilege escalation attack by a compromised child process. See the comment -// on AllocPBrowser for details. -union IPCTabContext -{ - PopupIPCTabContext; - AppFrameIPCTabContext; - BrowserFrameIPCTabContext; - VanillaFrameIPCTabContext; +union AppId { + uint32_t; + nullable PBrowser; }; union PrefValue { nsCString; int32_t; bool; }; @@ -228,36 +177,26 @@ rpc protocol PContent manages PStorage; manages PTestShell; both: // Depending on exactly how the new browser is being created, it might be // created from either the child or parent process! // // The child creates the PBrowser as part of - // TabChild::BrowserFrameProvideWindow (which happens when the child's - // content calls window.open()), and the parent creates the PBrowser as part - // of ContentParent::CreateTab. - // - // When the parent constructs a PBrowser, the child trusts the app token it - // receives from the parent. In that case, context can be any of the - // IPCTabContext subtypes. + // TabChild::BrowserFrameProvideWindow, and the parent creates the + // PBrowser as part of ContentParent::CreateTab. // - // When the child constructs a PBrowser, the parent doesn't trust the app - // token it receives from the child. In this case, context must have type - // PopupIPCTabContext. The browser created using a PopupIPCTabContext has - // the opener PBrowser's app-id and containing-app-id. The parent checks - // that if the opener is a browser element, the context is also for a - // browser element. - // - // This allows the parent to prevent a malicious child from escalating its - // privileges by requesting a PBrowser corresponding to a highly-privileged - // app; the child can only request privileges for an app which the child has - // access to (in the form of a TabChild). - async PBrowser(IPCTabContext context, uint32_t chromeFlags); + // When the parent constructs a PBrowser, the app ID handed to the + // child side is trusted. In that case, |appId| is uint32_t. + // However, when the child side constructs a PBrowser, for + // window.open(), the parent must validate the app ID used on the + // parent side. To do so, the child process must pass a valid + // PBrowser as its |AppId|. + async PBrowser(uint32_t chromeFlags, bool isBrowserElement, AppId appId); async PBlob(BlobConstructorParams params); child: PMemoryReportRequest(); /** * Dump the contents of about:memory to a file in our temp directory.
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -115,59 +115,64 @@ public: StaticRefPtr<TabChild> sPreallocatedTab; /*static*/ void TabChild::PreloadSlowThings() { MOZ_ASSERT(!sPreallocatedTab); - nsRefPtr<TabChild> tab(new TabChild(TabContext(), /* chromeFlags */ 0)); + nsRefPtr<TabChild> tab(new TabChild(0, false, + nsIScriptSecurityManager::NO_APP_ID)); if (!NS_SUCCEEDED(tab->Init()) || !tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) { return; } tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT); sPreallocatedTab = tab; ClearOnShutdown(&sPreallocatedTab); } /*static*/ already_AddRefed<TabChild> -TabChild::Create(const TabContext &aContext, uint32_t aChromeFlags) +TabChild::Create(uint32_t aChromeFlags, + bool aIsBrowserElement, uint32_t aAppId) { if (sPreallocatedTab && sPreallocatedTab->mChromeFlags == aChromeFlags && - aContext.IsBrowserOrApp()) { - + (aIsBrowserElement || + aAppId != nsIScriptSecurityManager::NO_APP_ID)) { nsRefPtr<TabChild> child = sPreallocatedTab.get(); sPreallocatedTab = nullptr; MOZ_ASSERT(!child->mTriedBrowserInit); - child->SetTabContext(aContext); - child->NotifyTabContextUpdated(); + child->SetAppBrowserConfig(aIsBrowserElement, aAppId); + return child.forget(); } - nsRefPtr<TabChild> iframe = new TabChild(aContext, aChromeFlags); + nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement, + aAppId); return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr; } -TabChild::TabChild(const TabContext& aContext, uint32_t aChromeFlags) - : TabContext(aContext) - , mRemoteFrame(nullptr) +TabChild::TabChild(uint32_t aChromeFlags, bool aIsBrowserElement, + uint32_t aAppId) + : mRemoteFrame(nullptr) , mTabChildGlobal(nullptr) , mChromeFlags(aChromeFlags) , mOuterRect(0, 0, 0, 0) , mInnerSize(0, 0) , mOldViewportWidth(0.0f) , mLastBackgroundColor(NS_RGB(255, 255, 255)) + , mAppId(aAppId) , mDidFakeShow(false) + , mIsBrowserElement(aIsBrowserElement) , mNotified(false) , mContentDocumentIsDisplayed(false) , mTriedBrowserInit(false) { printf("creating %d!\n", NS_IsMainThread()); } NS_IMETHODIMP @@ -520,17 +525,17 @@ TabChild::Init() nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)), nullptr, // HandleWidgetEvent nullptr // nsDeviceContext ); baseWindow->InitWindow(0, mWidget, 0, 0, 0, 0); baseWindow->Create(); - NotifyTabContextUpdated(); + SetAppBrowserConfig(mIsBrowserElement, mAppId); // IPC uses a WebBrowser object for which DNS prefetching is turned off // by default. But here we really want it, so enable it explicitly nsCOMPtr<nsIWebBrowserSetup> webBrowserSetup = do_QueryInterface(baseWindow); if (webBrowserSetup) { webBrowserSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH, true); @@ -544,28 +549,28 @@ TabChild::Init() nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell); NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE); webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION); return NS_OK; } void -TabChild::NotifyTabContextUpdated() +TabChild::SetAppBrowserConfig(bool aIsBrowserElement, uint32_t aAppId) { + mIsBrowserElement = aIsBrowserElement; + mAppId = aAppId; + nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mWebNav); MOZ_ASSERT(docShell); if (docShell) { - // nsDocShell will do the right thing if we pass NO_APP_ID or - // UNKNOWN_APP_ID for aOwnOrContainingAppId. - if (IsBrowserElement()) { - docShell->SetIsBrowserInsideApp(BrowserOwnerAppId()); - } else { - docShell->SetIsApp(OwnAppId()); + docShell->SetAppId(mAppId); + if (mIsBrowserElement) { + docShell->SetIsBrowserElement(); } } } NS_INTERFACE_MAP_BEGIN(TabChild) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) @@ -779,21 +784,21 @@ TabChild::ProvideWindow(nsIDOMWindow* aP bool aCalledFromJS, bool aPositionSpecified, bool aSizeSpecified, nsIURI* aURI, const nsAString& aName, const nsACString& aFeatures, bool* aWindowIsNew, nsIDOMWindow** aReturn) { *aReturn = nullptr; - // If aParent is inside an <iframe mozbrowser> or <iframe mozapp> and this - // isn't a request to open a modal-type window, we're going to create a new - // <iframe mozbrowser/mozapp> and return its window here. + // If aParent is inside an <iframe mozbrowser> and this isn't a request to + // open a modal-type window, we're going to create a new <iframe mozbrowser> + // and return its window here. nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent); - if (docshell && docshell->GetIsInBrowserOrApp() && + if (docshell && docshell->GetIsBelowContentBoundary() && !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL | nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) { // Note that BrowserFrameProvideWindow may return NS_ERROR_ABORT if the // open window call was canceled. It's important that we pass this error // code back to our caller. return BrowserFrameProvideWindow(aParent, aURI, aName, aFeatures, @@ -818,35 +823,26 @@ TabChild::BrowserFrameProvideWindow(nsID nsIURI* aURI, const nsAString& aName, const nsACString& aFeatures, bool* aWindowIsNew, nsIDOMWindow** aReturn) { *aReturn = nullptr; - nsRefPtr<TabChild> newChild = - new TabChild(/* TabContext */ *this, /* chromeFlags */ 0); + uint32_t chromeFlags = 0; + nsRefPtr<TabChild> newChild = new TabChild(chromeFlags, + mIsBrowserElement, mAppId); if (!NS_SUCCEEDED(newChild->Init())) { return NS_ERROR_ABORT; } - - // We must use PopupIPCTabContext here; ContentParent will not accept the - // result of this->AsIPCTabContext() (which will be a - // BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security - // reasons. - PopupIPCTabContext context; - context.openerChild() = this; - context.isBrowserElement() = IsBrowserElement(); - unused << Manager()->SendPBrowserConstructor( // We release this ref in DeallocPBrowserChild nsRefPtr<TabChild>(newChild).forget().get(), - context, /* chromeFlags */ 0); - + chromeFlags, mIsBrowserElement, this); nsAutoCString spec; if (aURI) { aURI->GetSpec(spec); } NS_ConvertUTF8toUTF16 url(spec); nsString name(aName); NS_ConvertUTF8toUTF16 features(aFeatures); @@ -997,53 +993,63 @@ TabChild::~TabChild() } mTabChildGlobal->mTabChild = nullptr; } } void TabChild::SetProcessNameToAppName() { - nsCOMPtr<mozIApplication> app = GetOwnApp(); - if (!app) { + if (mIsBrowserElement || (mAppId == nsIScriptSecurityManager::NO_APP_ID)) { + return; + } + nsCOMPtr<nsIAppsService> appsService = + do_GetService(APPS_SERVICE_CONTRACTID); + if (!appsService) { + NS_WARNING("No AppsService"); return; } - + nsresult rv; + nsCOMPtr<mozIDOMApplication> domApp; + rv = appsService->GetAppByLocalId(mAppId, getter_AddRefs(domApp)); + if (NS_FAILED(rv) || !domApp) { + NS_WARNING("GetAppByLocalId failed"); + return; + } + nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp); + if (!app) { + NS_WARNING("app isn't a mozIApplication"); + return; + } nsAutoString appName; - nsresult rv = app->GetName(appName); + rv = app->GetName(appName); if (NS_FAILED(rv)) { NS_WARNING("Failed to retrieve app name"); return; } ContentChild::GetSingleton()->SetProcessName(appName); } bool TabChild::IsRootContentDocument() { - // A TabChild is a "root content document" if it's - // - // - <iframe mozapp> not inside another <iframe mozapp>, - // - <iframe mozbrowser> (not mozapp), or - // - a vanilla remote frame (<html:iframe remote=true> or <xul:browser - // remote=true>). - // - // Put another way, an iframe is /not/ a "root content document" iff it's a - // mozapp inside a mozapp. (This corresponds exactly to !HasAppOwnerApp.) - // - // Note that we're lying through our teeth here (thus the scare quotes). - // <html:iframe remote=true> or <xul:browser remote=true> inside another - // content iframe is not actually a root content document, but we say it is. - // - // We do this because we make a remote frame opaque iff - // IsRootContentDocument(), and making vanilla remote frames transparent - // breaks our remote reftests. + if (mIsBrowserElement || mAppId == nsIScriptSecurityManager::NO_APP_ID) { + // We're the child side of a browser element. This always + // behaves like a root content document. + return true; + } - return !HasAppOwnerApp(); + // Otherwise, we're the child side of an <html:app remote=true> + // embedded in an outer <html:app>. These don't behave like root + // content documents in nested contexts. Because of bug 761935, + // <html:browser remote> and <html:app remote> can't nest, so we + // assume this isn't the root. When that bug is fixed, we need to + // revisit that assumption. + return false; } bool TabChild::RecvLoadURL(const nsCString& uri) { printf("loading %s, %d\n", uri.get(), NS_IsMainThread()); SetProcessNameToAppName(); @@ -1691,17 +1697,17 @@ TabChild::InitTabChildGlobal(FrameScript chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false); } if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) { mTriedBrowserInit = true; // Initialize the child side of the browser element machinery, // if appropriate. - if (IsBrowserOrApp()) { + if (mIsBrowserElement || mAppId != nsIScriptSecurityManager::NO_APP_ID) { RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT); } } return true; } bool
--- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -46,17 +46,16 @@ #include "nsIScriptObjectPrincipal.h" #include "nsIScriptContext.h" #include "nsPIDOMWindow.h" #include "nsWeakReference.h" #include "nsITabChild.h" #include "mozilla/Attributes.h" #include "FrameMetrics.h" #include "ProcessUtils.h" -#include "mozilla/dom/TabContext.h" struct gfxMatrix; namespace mozilla { namespace layout { class RenderFrameChild; } @@ -145,36 +144,37 @@ class TabChild : public PBrowserChild, public nsIInterfaceRequestor, public nsIWindowProvider, public nsIDOMEventListener, public nsIWebProgressListener, public nsSupportsWeakReference, public nsIDialogCreator, public nsITabChild, public nsIObserver, - public ipc::MessageManagerCallback, - public TabContext + public mozilla::dom::ipc::MessageManagerCallback { typedef mozilla::layout::RenderFrameChild RenderFrameChild; typedef mozilla::dom::ClonedMessageData ClonedMessageData; public: /** * This is expected to be called off the critical path to content * startup. This is an opportunity to load things that are slow * on the critical path. */ static void PreloadSlowThings(); /** Return a TabChild with the given attributes. */ static already_AddRefed<TabChild> - Create(const TabContext& aContext, uint32_t aChromeFlags); + Create(uint32_t aChromeFlags, bool aIsBrowserElement, uint32_t aAppId); virtual ~TabChild(); + uint32_t GetAppId() { return mAppId; } + bool IsRootContentDocument(); NS_DECL_ISUPPORTS NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIWEBBROWSERCHROME2 NS_DECL_NSIEMBEDDINGSITEWINDOW NS_DECL_NSIWEBBROWSERCHROMEFOCUS NS_DECL_NSIINTERFACEREQUESTOR @@ -315,31 +315,25 @@ protected: bool* /* aAllowed */); virtual bool DeallocPIndexedDB(PIndexedDBChild* aActor); private: /** * Create a new TabChild object. * - * |aOwnOrContainingAppId| is the app-id of our frame or of the closest app - * frame in the hierarchy which contains us. - * - * |aIsBrowserElement| indicates whether we're a browser (but not an app). + * |aIsBrowserElement| indicates whether the tab is inside an <iframe mozbrowser>. + * |aAppId| is the app id of the app containing this tab. If the tab isn't + * contained in an app, aAppId will be nsIScriptSecurityManager::NO_APP_ID. */ - TabChild(const TabContext& aContext, uint32_t aChromeFlags); + TabChild(uint32_t aChromeFlags, bool aIsBrowserElement, uint32_t aAppId); nsresult Init(); - // Notify others that our TabContext has been updated. (At the moment, this - // sets the appropriate app-id and is-browser flags on our docshell.) - // - // You should call this after calling TabContext::SetTabContext(). We also - // call this during Init(). - void NotifyTabContextUpdated(); + void SetAppBrowserConfig(bool aIsBrowserElement, uint32_t aAppId); bool UseDirectCompositor(); void ActorDestroy(ActorDestroyReason why); enum FrameScriptLoading { DONT_LOAD_SCRIPTS, DEFAULT_LOAD_SCRIPTS }; bool InitTabChildGlobal(FrameScriptLoading aScriptLoading = DEFAULT_LOAD_SCRIPTS); bool InitRenderingState(); @@ -393,17 +387,19 @@ private: RenderFrameChild* mRemoteFrame; nsRefPtr<TabChildGlobal> mTabChildGlobal; uint32_t mChromeFlags; nsIntRect mOuterRect; nsIntSize mInnerSize; float mOldViewportWidth; nscolor mLastBackgroundColor; ScrollingBehavior mScrolling; + uint32_t mAppId; bool mDidFakeShow; + bool mIsBrowserElement; bool mNotified; bool mContentDocumentIsDisplayed; bool mTriedBrowserInit; DISALLOW_EVIL_CONSTRUCTORS(TabChild); }; inline TabChild*
deleted file mode 100644 --- a/dom/ipc/TabContext.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=8 et 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/TabContext.h" -#include "mozilla/dom/TabParent.h" -#include "mozilla/dom/TabChild.h" -#include "nsIAppsService.h" - -using namespace mozilla::dom::ipc; - -namespace mozilla { -namespace dom { - -TabContext::TabContext() - : mInitialized(false) - , mOwnAppId(nsIScriptSecurityManager::NO_APP_ID) - , mContainingAppId(nsIScriptSecurityManager::NO_APP_ID) - , mIsBrowser(false) -{ -} - -TabContext::TabContext(const IPCTabContext& aParams) - : mInitialized(true) -{ - switch(aParams.type()) { - case IPCTabContext::TPopupIPCTabContext: { - const PopupIPCTabContext &ipcContext = aParams.get_PopupIPCTabContext(); - - TabContext *context; - if (ipcContext.openerParent()) { - context = static_cast<TabParent*>(ipcContext.openerParent()); - if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) { - // If the TabParent corresponds to a browser element, then it can only - // open other browser elements, for security reasons. We should have - // checked this before calling the TabContext constructor, so this is - // a fatal error. - MOZ_CRASH(); - } - } - else if (ipcContext.openerChild()) { - context = static_cast<TabChild*>(ipcContext.openerChild()); - } - else { - // This should be unreachable because PopupIPCTabContext::opener is not a - // nullable field. - MOZ_CRASH(); - } - - // If ipcContext is a browser element, then the opener's app-id becomes - // our containing app-id. Otherwise, our own and containing app-ids are - // directly inherited from our opener. - if (ipcContext.isBrowserElement()) { - mIsBrowser = true; - mOwnAppId = nsIScriptSecurityManager::NO_APP_ID; - mContainingAppId = context->OwnAppId(); - } - else { - mIsBrowser = false; - mOwnAppId = context->mOwnAppId; - mContainingAppId = context->mContainingAppId; - } - break; - } - case IPCTabContext::TAppFrameIPCTabContext: { - const AppFrameIPCTabContext &ipcContext = - aParams.get_AppFrameIPCTabContext(); - - mIsBrowser = false; - mOwnAppId = ipcContext.ownAppId(); - mContainingAppId = ipcContext.appFrameOwnerAppId(); - break; - } - case IPCTabContext::TBrowserFrameIPCTabContext: { - const BrowserFrameIPCTabContext &ipcContext = - aParams.get_BrowserFrameIPCTabContext(); - - mIsBrowser = true; - mOwnAppId = nsIScriptSecurityManager::NO_APP_ID; - mContainingAppId = ipcContext.browserFrameOwnerAppId(); - break; - } - case IPCTabContext::TVanillaFrameIPCTabContext: { - mIsBrowser = false; - mOwnAppId = nsIScriptSecurityManager::NO_APP_ID; - mContainingAppId = nsIScriptSecurityManager::NO_APP_ID; - break; - } - default: { - MOZ_CRASH(); - } - } -} - -bool -TabContext::IsBrowserElement() const -{ - return mIsBrowser; -} - -bool -TabContext::IsBrowserOrApp() const -{ - return HasOwnApp() || IsBrowserElement(); -} - -uint32_t -TabContext::OwnAppId() const -{ - return mOwnAppId; -} - -already_AddRefed<mozIApplication> -TabContext::GetOwnApp() const -{ - return GetAppForId(OwnAppId()); -} - -bool -TabContext::HasOwnApp() const -{ - return mOwnAppId != nsIScriptSecurityManager::NO_APP_ID; -} - -uint32_t -TabContext::BrowserOwnerAppId() const -{ - if (mIsBrowser) { - return mContainingAppId; - } - return nsIScriptSecurityManager::NO_APP_ID; -} - -already_AddRefed<mozIApplication> -TabContext::GetBrowserOwnerApp() const -{ - return GetAppForId(BrowserOwnerAppId()); -} - -bool -TabContext::HasBrowserOwnerApp() const -{ - return BrowserOwnerAppId() != nsIScriptSecurityManager::NO_APP_ID; -} - -uint32_t -TabContext::AppOwnerAppId() const -{ - if (mOwnAppId != nsIScriptSecurityManager::NO_APP_ID) { - return mContainingAppId; - } - return nsIScriptSecurityManager::NO_APP_ID; -} - -already_AddRefed<mozIApplication> -TabContext::GetAppOwnerApp() const -{ - return GetAppForId(AppOwnerAppId()); -} - -bool -TabContext::HasAppOwnerApp() const -{ - return AppOwnerAppId() != nsIScriptSecurityManager::NO_APP_ID; -} - -uint32_t -TabContext::OwnOrContainingAppId() const -{ - if (mIsBrowser) { - MOZ_ASSERT(mOwnAppId == nsIScriptSecurityManager::NO_APP_ID); - return mContainingAppId; - } - - if (mOwnAppId) { - return mOwnAppId; - } - - return mContainingAppId; -} - -already_AddRefed<mozIApplication> -TabContext::GetOwnOrContainingApp() const -{ - return GetAppForId(OwnOrContainingAppId()); -} - -bool -TabContext::HasOwnOrContainingApp() const -{ - return OwnOrContainingAppId() != nsIScriptSecurityManager::NO_APP_ID; -} - -bool -TabContext::SetTabContext(const TabContext& aContext) -{ - NS_ENSURE_FALSE(mInitialized, false); - - // Verify that we can actually get apps for the given ids. This step gives us - // confidence that HasX() returns true iff GetX() returns true. - if (aContext.mOwnAppId != nsIScriptSecurityManager::NO_APP_ID) { - nsCOMPtr<mozIApplication> app = GetAppForId(aContext.mOwnAppId); - NS_ENSURE_TRUE(app, false); - } - - if (aContext.mContainingAppId != nsIScriptSecurityManager::NO_APP_ID) { - nsCOMPtr<mozIApplication> app = GetAppForId(aContext.mContainingAppId); - NS_ENSURE_TRUE(app, false); - } - - mInitialized = true; - mIsBrowser = aContext.mIsBrowser; - mOwnAppId = aContext.mOwnAppId; - mContainingAppId = aContext.mContainingAppId; - return true; -} - -bool -TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp, mozIApplication* aAppFrameOwnerApp) -{ - NS_ENSURE_FALSE(mInitialized, false); - - // Get ids for both apps and only write to our member variables after we've - // verified that this worked. - uint32_t ownAppId = nsIScriptSecurityManager::NO_APP_ID; - if (aOwnApp) { - nsresult rv = aOwnApp->GetLocalId(&ownAppId); - NS_ENSURE_SUCCESS(rv, false); - } - - uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID; - if (aAppFrameOwnerApp) { - nsresult rv = aOwnApp->GetLocalId(&containingAppId); - NS_ENSURE_SUCCESS(rv, false); - } - - mInitialized = true; - mIsBrowser = false; - mOwnAppId = ownAppId; - mContainingAppId = containingAppId; - return true; -} - -bool -TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp) -{ - NS_ENSURE_FALSE(mInitialized, false); - - uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID; - if (aBrowserFrameOwnerApp) { - nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId); - NS_ENSURE_SUCCESS(rv, false); - } - - mInitialized = true; - mIsBrowser = true; - mOwnAppId = nsIScriptSecurityManager::NO_APP_ID; - mContainingAppId = containingAppId; - return true; -} - -IPCTabContext -TabContext::AsIPCTabContext() const -{ - if (mIsBrowser) { - return BrowserFrameIPCTabContext(mContainingAppId); - } - - return AppFrameIPCTabContext(mOwnAppId, mContainingAppId); -} - -already_AddRefed<mozIApplication> -TabContext::GetAppForId(uint32_t aAppId) const -{ - if (aAppId == nsIScriptSecurityManager::NO_APP_ID) { - return nullptr; - } - - nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(appsService, nullptr); - - nsCOMPtr<mozIDOMApplication> domApp; - appsService->GetAppByLocalId(aAppId, getter_AddRefs(domApp)); - - nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp); - return app.forget(); -} - -} // namespace dom -} // namespace mozilla
deleted file mode 100644 --- a/dom/ipc/TabContext.h +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=8 et 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/. */ - -#ifndef mozilla_dom_TabContext_h -#define mozilla_dom_TabContext_h - -#include "mozilla/Assertions.h" -#include "mozilla/dom/PContent.h" -#include "mozilla/dom/PBrowser.h" -#include "nsIScriptSecurityManager.h" -#include "mozIApplication.h" - -namespace mozilla { -namespace dom { - -/** - * TabContext encapsulates information about an iframe that may be a mozbrowser - * or mozapp. You can ask whether a TabContext correspodns to a mozbrowser or - * mozapp, get the app that contains the browser, and so on. - * - * TabParent and TabChild both inherit from TabContext, and you can also have - * standalone TabContext objects. - * - * This class is immutable except by calling one of the protected - * SetTabContext*() methods (and those methods can only be called once). See - * also MutableTabContext. - */ -class TabContext -{ -public: - /** - * This constructor sets is-browser to false, and sets all relevant apps to - * NO_APP_ID. If you inherit from TabContext, you can mutate this object - * exactly once by calling one of the protected SetTabContext*() methods. - */ - TabContext(); - - /** - * This constructor copies the information in aContext. The TabContext is - * immutable after calling this method; you won't be able call any of the - * protected SetTabContext*() methods on an object constructed using this - * constructor. - * - * If aContext is a PopupIPCTabContext with isBrowserElement false and whose - * openerParent is a browser element, this constructor will crash (even in - * release builds). So please check that case before calling this method. - */ - TabContext(const IPCTabContext& aContext); - - /** - * Generates IPCTabContext of type BrowserFrameIPCTabContext or - * AppFrameIPCTabContext from this TabContext's information. - */ - IPCTabContext AsIPCTabContext() const; - - /** - * Does this TabContext correspond to a mozbrowser? (<iframe mozbrowser - * mozapp> is not a browser.) - * - * If IsBrowserElement() is true, HasOwnApp() and HasAppOwnerApp() are - * guaranteed to be false. - * - * If IsBrowserElement() is false, HasBrowserOwnerApp() is guaranteed to be - * false. - */ - bool IsBrowserElement() const; - - /** - * Does this TabContext correspond to a mozbrowser or mozapp? This is - * equivalent to IsBrowserElement() || HasOwnApp(). - */ - bool IsBrowserOrApp() const; - - /** - * OwnAppId() returns the id of the app which directly corresponds to this - * context's frame. GetOwnApp() returns the corresponding app object, and - * HasOwnApp() returns true iff GetOwnApp() would return a non-null value. - * - * If HasOwnApp() is true, IsBrowserElement() is guaranteed to be false. - */ - uint32_t OwnAppId() const; - already_AddRefed<mozIApplication> GetOwnApp() const; - bool HasOwnApp() const; - - /** - * BrowserOwnerAppId() gets the ID of the app which contains this browser - * frame. If this is not a browser frame (i.e., if !IsBrowserElement()), then - * BrowserOwnerAppId() is guaranteed to return NO_APP_ID. - * - * Even if we are a browser frame, BrowserOwnerAppId() may still return - * NO_APP_ID, if this browser frame is not contained inside an app. - */ - uint32_t BrowserOwnerAppId() const; - already_AddRefed<mozIApplication> GetBrowserOwnerApp() const; - bool HasBrowserOwnerApp() const; - - /** - * AppOwnerAppId() gets the ID of the app which contains this app frame. If - * this is not an app frame (i.e., if !HasOwnApp()), then AppOwnerAppId() is - * guaranteed to return NO_APP_ID. - * - * Even if we are an app frame, AppOwnerAppId() may still return NO_APP_ID, if - * this app frame is not contained inside an app. - */ - uint32_t AppOwnerAppId() const; - already_AddRefed<mozIApplication> GetAppOwnerApp() const; - bool HasAppOwnerApp() const; - - /** - * OwnOrContainingAppId() gets the ID of this frame, if HasOwnApp(). If this - * frame does not have its own app, it gets the ID of the app which contains - * this frame (i.e., the result of {Browser,App}OwnerAppId(), as applicable). - */ - uint32_t OwnOrContainingAppId() const; - already_AddRefed<mozIApplication> GetOwnOrContainingApp() const; - bool HasOwnOrContainingApp() const; - -protected: - /** - * These protected mutator methods let you modify a TabContext once. Further - * attempts to modify a given TabContext will fail (the method will return - * false). - * - * These mutators will also fail if the TabContext was created with anything - * other than the no-args constructor. - */ - - /** - * Set this TabContext to match the given TabContext. - */ - bool SetTabContext(const TabContext& aContext); - - /** - * Set this TabContext to be an app frame (with the given own app) inside the - * given app. Either or both apps may be null. - */ - bool SetTabContextForAppFrame(mozIApplication* aOwnApp, - mozIApplication* aAppFrameOwnerApp); - - /** - * Set this TabContext to be a browser frame inside the given app (which may - * be null). - */ - bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp); - -private: - /** - * Translate an appId into a mozIApplication. - */ - already_AddRefed<mozIApplication> GetAppForId(uint32_t aAppId) const; - - /** - * Has this TabContext been initialized? If so, mutator methods will fail. - */ - bool mInitialized; - - /** - * This TabContext's own app id. If this is something other than NO_APP_ID, - * then this TabContext corresponds to an app, and mIsBrowser must be false. - */ - uint32_t mOwnAppId; - - /** - * The id of the app which contains this TabContext's frame. If mIsBrowser, - * this corresponds to the ID of the app which contains the browser frame; - * otherwise, this correspodns to the ID of the app which contains the app - * frame. - */ - uint32_t mContainingAppId; - - /** - * Does this TabContext correspond to a browser element? - * - * If this is true, mOwnAppId must be NO_APP_ID. - */ - bool mIsBrowser; -}; - -/** - * MutableTabContext is the same as TabContext, except the mutation methods are - * public instead of protected. You can still only call these mutation methods - * once on a given object. - */ -class MutableTabContext : public TabContext -{ -public: - bool SetTabContext(const TabContext& aContext) - { - return TabContext::SetTabContext(aContext); - } - - bool SetTabContextForAppFrame(mozIApplication* aOwnApp, mozIApplication* aAppFrameOwnerApp) - { - return TabContext::SetTabContextForAppFrame(aOwnApp, aAppFrameOwnerApp); - } - - bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp) - { - return TabContext::SetTabContextForBrowserFrame(aBrowserFrameOwnerApp); - } -}; - -} // namespace dom -} // namespace mozilla - -#endif
--- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -68,28 +68,29 @@ namespace mozilla { namespace dom { TabParent* sEventCapturer; TabParent *TabParent::mIMETabParent = nullptr; NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI) -TabParent::TabParent(const TabContext& aContext) - : TabContext(aContext) - , mFrameElement(NULL) +TabParent::TabParent(mozIApplication* aApp, bool aIsBrowserElement) + : mFrameElement(NULL) + , mApp(aApp) , mIMESelectionAnchor(0) , mIMESelectionFocus(0) , mIMEComposing(false) , mIMECompositionEnding(false) , mIMECompositionStart(0) , mIMESeqno(0) , mEventCaptureDepth(0) , mDimensions(0, 0) , mDPI(0) + , mIsBrowserElement(aIsBrowserElement) , mShown(false) { } TabParent::~TabParent() { } @@ -182,17 +183,17 @@ TabParent::RecvEvent(const RemoteDOMEven bool TabParent::AnswerCreateWindow(PBrowserParent** retval) { if (!mBrowserDOMWindow) { return false; } // Only non-app, non-browser processes may call CreateWindow. - if (IsBrowserOrApp()) { + if (GetApp() || IsBrowserElement()) { return false; } // Get a new rendering area from the browserDOMWin. We don't want // to be starting any loads here, so get it with a null URI. nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner; mBrowserDOMWindow->OpenURIInFrame(nullptr, nullptr, nsIBrowserDOMWindow::OPEN_NEWTAB, @@ -890,25 +891,27 @@ TabParent::RecvPIndexedDBConstructor(PIn if (!IndexedDatabaseManager::IsMainProcess()) { NS_RUNTIMEABORT("Not supported yet!"); } nsresult rv; // XXXbent Need to make sure we have a whitelist for chrome databases! - // Verify that the child is requesting to access a database it's allowed to - // see. (aASCIIOrigin here specifies a TabContext + a website origin, and - // we're checking that the TabContext may access it.) - if (!aASCIIOrigin.EqualsLiteral("chrome") && - !IndexedDatabaseManager::TabContextMayAccessOrigin(*this, aASCIIOrigin)) { + // Verify the appID in the origin first. + if (mApp && !aASCIIOrigin.EqualsLiteral("chrome")) { + uint32_t appId; + rv = mApp->GetLocalId(&appId); + NS_ENSURE_SUCCESS(rv, false); - NS_WARNING("App attempted to open databases that it does not have " - "permission to access!"); - return false; + if (!IndexedDatabaseManager::OriginMatchesApp(aASCIIOrigin, appId)) { + NS_WARNING("App attempted to open databases that it does not have " + "permission to access!"); + return false; + } } nsCOMPtr<nsINode> node = do_QueryInterface(GetOwnerElement()); NS_ENSURE_TRUE(node, false); nsIDocument* doc = node->GetOwnerDocument(); NS_ENSURE_TRUE(doc, false); @@ -1156,23 +1159,38 @@ TabParent::GetWidget() const if (!frame) return nullptr; nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget(); return widget.forget(); } bool +TabParent::IsForMozBrowser() +{ + nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement); + nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(content); + if (browserFrame) { + bool isBrowser = false; + browserFrame->GetReallyIsBrowser(&isBrowser); + return isBrowser; + } + return false; +} + +bool TabParent::UseAsyncPanZoom() { bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop(); bool asyncPanZoomEnabled = Preferences::GetBool("layers.async-pan-zoom.enabled", false); + ContentParent* cp = static_cast<ContentParent*>(Manager()); return (usingOffMainThreadCompositing && - IsBrowserElement() && asyncPanZoomEnabled); + !cp->IsForApp() && IsForMozBrowser() && + asyncPanZoomEnabled); } void TabParent::MaybeForwardEventToRenderFrame(const nsInputEvent& aEvent, nsInputEvent* aOutEvent) { if (RenderFrameParent* rfp = GetRenderFrame()) { rfp->NotifyInputEvent(aEvent, aOutEvent);
--- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -7,17 +7,16 @@ #ifndef mozilla_tabs_TabParent_h #define mozilla_tabs_TabParent_h #include "base/basictypes.h" #include "jsapi.h" #include "mozilla/dom/PBrowserParent.h" #include "mozilla/dom/PContentDialogParent.h" -#include "mozilla/dom/TabContext.h" #include "mozilla/ipc/GeckoChildProcessHost.h" #include "nsCOMPtr.h" #include "nsIAuthPromptProvider.h" #include "nsIBrowserDOMWindow.h" #include "nsIDialogParamBlock.h" #include "nsISecureBrowserUI.h" #include "nsITabParent.h" #include "nsWeakReference.h" @@ -46,29 +45,31 @@ class ClonedMessageData; struct StructuredCloneData; class ContentDialogParent : public PContentDialogParent {}; class TabParent : public PBrowserParent , public nsITabParent , public nsIAuthPromptProvider , public nsISecureBrowserUI - , public TabContext { typedef mozilla::dom::ClonedMessageData ClonedMessageData; public: - TabParent(const TabContext& aContext); + TabParent(mozIApplication* aApp, bool aIsBrowserElement); virtual ~TabParent(); nsIDOMElement* GetOwnerElement() { return mFrameElement; } void SetOwnerElement(nsIDOMElement* aElement); nsIBrowserDOMWindow *GetBrowserDOMWindow() { return mBrowserDOMWindow; } void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) { mBrowserDOMWindow = aBrowserDOMWindow; } + + mozIApplication* GetApp() { return mApp; } + bool IsBrowserElement() { return mIsBrowserElement; } /** * Return the TabParent that has decided it wants to capture an * event series for fast-path dispatch to its subprocess, if one * has. * * DOM event dispatch and widget are free to ignore capture * requests from TabParents; the end result wrt remote content is @@ -256,16 +257,17 @@ protected: bool AllowContentIME(); virtual PRenderFrameParent* AllocPRenderFrame(ScrollingBehavior* aScrolling, LayersBackend* aBackend, int32_t* aMaxTextureSize, uint64_t* aLayersId) MOZ_OVERRIDE; virtual bool DeallocPRenderFrame(PRenderFrameParent* aFrame) MOZ_OVERRIDE; + nsCOMPtr<mozIApplication> mApp; // IME static TabParent *mIMETabParent; nsString mIMECacheText; uint32_t mIMESelectionAnchor; uint32_t mIMESelectionFocus; bool mIMEComposing; bool mIMECompositionEnding; // Buffer to store composition text during ResetInputState @@ -274,24 +276,27 @@ protected: uint32_t mIMECompositionStart; uint32_t mIMESeqno; // The number of event series we're currently capturing. int32_t mEventCaptureDepth; nsIntSize mDimensions; float mDPI; + bool mIsBrowserElement; bool mShown; private: already_AddRefed<nsFrameLoader> GetFrameLoader() const; already_AddRefed<nsIWidget> GetWidget() const; layout::RenderFrameParent* GetRenderFrame(); void TryCacheDPI(); - + // Return true iff this TabParent was created for a mozbrowser + // frame. + bool IsForMozBrowser(); // When true, we create a pan/zoom controller for our frame and // notify it of input events targeting us. bool UseAsyncPanZoom(); // If we have a render frame currently, notify it that we're about // to dispatch |aEvent| to our child. If there's a relevant // transform in place, |aOutEvent| is the transformed |aEvent| to // dispatch to content. void MaybeForwardEventToRenderFrame(const nsInputEvent& aEvent,
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -1628,18 +1628,22 @@ uint32_t nsWindowWatcher::CalculateChrom if (!(chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) { // Remove the dependent flag if we're not opening as chrome chromeFlags &= ~nsIWebBrowserChrome::CHROME_DEPENDENT; } // Disable CHROME_OPENAS_DIALOG if the window is inside <iframe mozbrowser>. // It's up to the embedder to interpret what dialog=1 means. nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent); - if (docshell && docshell->GetIsInBrowserOrApp()) { - chromeFlags &= ~nsIWebBrowserChrome::CHROME_OPENAS_DIALOG; + if (docshell) { + bool belowContentBoundary = false; + docshell->GetIsBelowContentBoundary(&belowContentBoundary); + if (belowContentBoundary) { + chromeFlags &= ~nsIWebBrowserChrome::CHROME_OPENAS_DIALOG; + } } return chromeFlags; } // static int32_t nsWindowWatcher::WinHasOption(const char *aOptions, const char *aName,
--- a/gfx/thebes/gfxAndroidPlatform.cpp +++ b/gfx/thebes/gfxAndroidPlatform.cpp @@ -191,18 +191,19 @@ gfxAndroidPlatform::FontHintingEnabled() // hinting. // // XXX when gecko-android-java is used as an "app runtime", we'll // want to re-enable hinting. return false; #else // Otherwise, enable hinting unless we're in a content process // that might be used for non-reflowing zoom. - return XRE_GetProcessType() != GeckoProcessType_Content || - ContentChild::GetSingleton()->HasOwnApp(); + return (XRE_GetProcessType() != GeckoProcessType_Content || + (ContentChild::GetSingleton()->IsForApp() && + !ContentChild::GetSingleton()->IsForBrowser())); #endif // MOZ_USING_ANDROID_JAVA_WIDGETS } int gfxAndroidPlatform::GetScreenDepth() const { return mScreenDepth; }
--- a/testing/mochitest/android.json +++ b/testing/mochitest/android.json @@ -147,19 +147,17 @@ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html": "bug 775227", "dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html": "bug 775227", "dom/imptests/webapps/WebStorage/tests/submissions/Infraware/test_storage_local_key.html": "bug 775227", "dom/indexedDB/ipc/test_ipc.html": "bug 783513", "dom/indexedDB/test/test_third_party.html": "TIMED_OUT", "dom/indexedDB/test/test_event_propagation.html": "TIMED_OUT, bug 780855", "dom/indexedDB/test/test_app_isolation_inproc.html": "TIMED_OUT", "dom/indexedDB/test/test_app_isolation_oop.html": "TIMED_OUT", - "dom/indexedDB/test/test_webapp_clearBrowserData_inproc_inproc.html": "No test app installed", - "dom/indexedDB/test/test_webapp_clearBrowserData_inproc_oop.html": "No test app installed", - "dom/indexedDB/test/test_webapp_clearBrowserData_oop_inproc.html": "No test app installed", + "dom/indexedDB/test/test_webapp_clearBrowserData.html": "No test app installed", "dom/network/tests/test_network_basics.html": "", "dom/permission/tests/test_permission_basics.html": "", "dom/sms/tests/test_sms_basics.html": "", "dom/tests/mochitest/ajax/jquery/test_jQuery.html": "bug 775227", "dom/tests/mochitest/ajax/offline/test_simpleManifest.html": "TIMED_OUT", "dom/tests/mochitest/ajax/offline/test_updatingManifest.html": "TIMED_OUT", "dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml": "TIMED_OUT", "dom/tests/mochitest/ajax/prototype/test_Prototype.html": "",
--- a/xpfe/appshell/src/nsContentTreeOwner.cpp +++ b/xpfe/appshell/src/nsContentTreeOwner.cpp @@ -846,17 +846,17 @@ nsContentTreeOwner::ProvideWindow(nsIDOM static_cast<nsIDocShellTreeOwner*>(this)), "Parent from wrong docshell tree?"); #endif // If aParent is inside an <iframe mozbrowser> and this isn't a request to // open a modal-type window, we're going to create a new <iframe mozbrowser> // and return its window here. nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent); - if (docshell && docshell->GetIsInBrowserOrApp() && + if (docshell && docshell->GetIsBelowContentBoundary() && !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL | nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) { *aWindowIsNew = BrowserElementParent::OpenWindowInProcess(aParent, aURI, aName, aFeatures, aReturn); // If OpenWindowInProcess failed (perhaps because the embedder blocked the