Bug 1218594 - r=smaug, a=sledru
authorMike Conley <mconley@mozilla.com>
Thu, 29 Oct 2015 13:05:23 -0400
changeset 305349 7063e8c719a2d48e4fb5024f7a0a6c8501d1eabb
parent 305348 cb029edb917f480e9cdd9d4613a623f708ef9139
child 305350 b03b4145b89e7c641ff38d0d4870d0e7ff91b120
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, sledru
bugs1218594
milestone44.0a2
Bug 1218594 - r=smaug, a=sledru
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
embedding/components/windowwatcher/nsWindowWatcher.cpp
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -165,20 +165,20 @@ parent:
 
     Event(RemoteDOMEvent aEvent);
 
     sync CreateWindow(PBrowser aNewTab,
                       uint32_t aChromeFlags,
                       bool aCalledFromJS,
                       bool aPositionSpecified,
                       bool aSizeSpecified,
-                      nsString aURI,
+                      nsCString aURI,
                       nsString aName,
                       nsCString aFeatures,
-                      nsString aBaseURI)
+                      nsCString aBaseURI)
       returns (nsresult rv,
                bool windowOpened,
                FrameScriptInfo[] frameScripts,
                nsCString urlToLoad);
 
     sync SyncMessage(nsString aMessage, ClonedMessageData aData,
                      CpowEntry[] aCpows, Principal aPrincipal)
       returns (StructuredCloneData[] retval);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1170,29 +1170,33 @@ TabChild::ProvideWindowCommon(nsIDOMWind
 
   context.opener() = this;
   unused << Manager()->SendPBrowserConstructor(
       // We release this ref in DeallocPBrowserChild
       RefPtr<TabChild>(newChild).forget().take(),
       tabId, IPCTabContext(context), aChromeFlags,
       cc->GetID(), cc->IsForApp(), cc->IsForBrowser());
 
-  nsAutoCString spec;
+  nsAutoCString url;
   if (aURI) {
-    aURI->GetSpec(spec);
+    aURI->GetSpec(url);
+  } else {
+    // We can't actually send a nullptr up as the URI, since IPDL doesn't let us
+    // send nullptr's for primitives. We indicate that the nsString for the URI
+    // should be converted to a nullptr by voiding the string.
+    url.SetIsVoid(true);
   }
 
-  NS_ConvertUTF8toUTF16 url(spec);
   nsString name(aName);
   nsAutoCString features(aFeatures);
   nsTArray<FrameScriptInfo> frameScripts;
   nsCString urlToLoad;
 
   if (aIframeMoz) {
-    newChild->SendBrowserFrameOpenWindow(this, url, name,
+    newChild->SendBrowserFrameOpenWindow(this, NS_ConvertUTF8toUTF16(url), name,
                                          NS_ConvertUTF8toUTF16(features),
                                          aWindowIsNew);
   } else {
     nsCOMPtr<nsPIDOMWindow> opener = do_QueryInterface(aOpener);
     nsCOMPtr<nsIDocument> doc = opener->GetDoc();
     nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
     if (!baseURI) {
       NS_ERROR("nsIDocument didn't return a base URI");
@@ -1203,17 +1207,17 @@ TabChild::ProvideWindowCommon(nsIDOMWind
     baseURI->GetSpec(baseURIString);
 
     nsresult rv;
 
     if (!SendCreateWindow(newChild,
                           aChromeFlags, aCalledFromJS, aPositionSpecified,
                           aSizeSpecified, url,
                           name, features,
-                          NS_ConvertUTF8toUTF16(baseURIString),
+                          baseURIString,
                           &rv,
                           aWindowIsNew,
                           &frameScripts,
                           &urlToLoad)) {
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     if (NS_FAILED(rv)) {
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -784,20 +784,20 @@ FindMostRecentOpenWindow()
 }
 
 bool
 TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
                             const uint32_t& aChromeFlags,
                             const bool& aCalledFromJS,
                             const bool& aPositionSpecified,
                             const bool& aSizeSpecified,
-                            const nsString& aURI,
+                            const nsCString& aURI,
                             const nsString& aName,
                             const nsCString& aFeatures,
-                            const nsString& aBaseURI,
+                            const nsCString& aBaseURI,
                             nsresult* aResult,
                             bool* aWindowIsNew,
                             InfallibleTArray<FrameScriptInfo>* aFrameScripts,
                             nsCString* aURLToLoad)
 {
   // We always expect to open a new window here. If we don't, it's an error.
   *aWindowIsNew = true;
 
@@ -868,17 +868,17 @@ TabParent::RecvCreateWindow(PBrowserPare
       return true;
     }
 
     bool isPrivate;
     nsCOMPtr<nsILoadContext> loadContext = GetLoadContext();
     loadContext->GetUsePrivateBrowsing(&isPrivate);
 
     nsCOMPtr<nsIOpenURIInFrameParams> params = new nsOpenURIInFrameParams();
-    params->SetReferrer(aBaseURI);
+    params->SetReferrer(NS_ConvertUTF8toUTF16(aBaseURI));
     params->SetIsPrivate(isPrivate);
 
     AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
 
     nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
     browserDOMWin->OpenURIInFrame(nullptr, params,
                                   openLocation,
                                   nsIBrowserDOMWindow::OPEN_NEW,
@@ -901,33 +901,37 @@ TabParent::RecvCreateWindow(PBrowserPare
   *aResult = NS_NewURI(getter_AddRefs(baseURI), aBaseURI);
 
   if (NS_WARN_IF(NS_FAILED(*aResult)))
     return true;
 
   nsAutoCString finalURIString;
   if (!aURI.IsEmpty()) {
     nsCOMPtr<nsIURI> finalURI;
-    *aResult = NS_NewURI(getter_AddRefs(finalURI), NS_ConvertUTF16toUTF8(aURI).get(), baseURI);
+    *aResult = NS_NewURI(getter_AddRefs(finalURI), aURI.get(), baseURI);
 
     if (NS_WARN_IF(NS_FAILED(*aResult)))
       return true;
 
     finalURI->GetSpec(finalURIString);
   }
 
   nsCOMPtr<nsIDOMWindow> window;
 
   AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
 
-  const char* features = aFeatures.Length() ? aFeatures.get() : nullptr;
-
-  *aResult = pwwatch->OpenWindow2(parent, finalURIString.get(),
-                                  NS_ConvertUTF16toUTF8(aName).get(),
-                                  features, aCalledFromJS,
+  // If nsWindowWatcher::OpenWindowInternal was passed a nullptr for the URI
+  // to open in the content process, we indicate that by sending up a voided
+  // nsString (since primitives are not nullable). If we detect the voided
+  // nsString, we know that we need to send OpenWindow2 a nullptr for the URI.
+  const char* uri = aURI.IsVoid() ? nullptr : finalURIString.get();
+  const char* name = aName.IsVoid() ? nullptr : NS_ConvertUTF16toUTF8(aName).get();
+  const char* features = aFeatures.IsVoid() ? nullptr : aFeatures.get();
+
+  *aResult = pwwatch->OpenWindow2(parent, uri, name, features, aCalledFromJS,
                                   false, false, this, nullptr, getter_AddRefs(window));
 
   if (NS_WARN_IF(NS_FAILED(*aResult)))
     return true;
 
   *aResult = NS_ERROR_FAILURE;
 
   nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(window);
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -147,20 +147,20 @@ public:
                                             const nsString& aName,
                                             const nsString& aFeatures,
                                             bool* aOutWindowOpened) override;
     virtual bool RecvCreateWindow(PBrowserParent* aOpener,
                                   const uint32_t& aChromeFlags,
                                   const bool& aCalledFromJS,
                                   const bool& aPositionSpecified,
                                   const bool& aSizeSpecified,
-                                  const nsString& aURI,
+                                  const nsCString& aURI,
                                   const nsString& aName,
                                   const nsCString& aFeatures,
-                                  const nsString& aBaseURI,
+                                  const nsCString& aBaseURI,
                                   nsresult* aResult,
                                   bool* aWindowIsNew,
                                   InfallibleTArray<FrameScriptInfo>* aFrameScripts,
                                   nsCString* aURLToLoad) override;
     virtual bool RecvSyncMessage(const nsString& aMessage,
                                  const ClonedMessageData& aData,
                                  InfallibleTArray<CpowEntry>&& aCpows,
                                  const IPC::Principal& aPrincipal,
--- a/embedding/components/windowwatcher/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp
@@ -490,35 +490,42 @@ nsWindowWatcher::OpenWindowInternal(nsID
 
   if (!nsContentUtils::IsSafeToRunScript()) {
     nsContentUtils::WarnScriptWasIgnored(nullptr);
     return NS_ERROR_FAILURE;
   }
 
   GetWindowTreeOwner(aParent, getter_AddRefs(parentTreeOwner));
 
-  if (aUrl) {
+  // We expect TabParent to have provided us the absolute URI of the window
+  // we're to open, so there's no need to call URIfromURL (or more importantly,
+  // to check for a chrome URI, which cannot be opened from a remote tab).
+  if (aUrl && !openedFromRemoteTab) {
     rv = URIfromURL(aUrl, aParent, getter_AddRefs(uriToLoad));
     if (NS_FAILED(rv)) {
       return rv;
     }
     uriToLoad->SchemeIs("chrome", &uriToLoadIsChrome);
   }
 
   bool nameSpecified = false;
   if (aName) {
     CopyUTF8toUTF16(aName, name);
     nameSpecified = true;
+  } else {
+    name.SetIsVoid(true);
   }
 
   bool featuresSpecified = false;
   if (aFeatures) {
     features.Assign(aFeatures);
     featuresSpecified = true;
     features.StripWhitespace();
+  } else {
+    features.SetIsVoid(true);
   }
 
   // We only want to check for existing named windows if:
   // a) We're the child process
   // b) We're the parent process, and aOpeningTab wasn't passed
   //    in.
   // This is because when using child processes, the parent process shouldn't
   // know or care about names - unless we're opening named windows from chrome.