Bug 1250109 - Changing DOMEventTargetHelper subclasses to not assume that GetOwner() is non-null, since it can be nulled out by navigation. r?bzbarsky draft
authorMichelangelo De Simone <michelangelo@mozilla.com>
Fri, 04 Mar 2016 13:37:50 -0800
changeset 338232 447d3e3bfe9389db4cda49d9666c2ea14db00a52
parent 337411 be593a64d7c6a826260514fe758ef32a6ee580f7
child 515771 0c28c3448cdfe3e218511971387a554782eaf1f7
push id12479
push usermdesimone@mozilla.com
push dateTue, 08 Mar 2016 21:57:02 +0000
reviewersbzbarsky
bugs1250109
milestone48.0a1
Bug 1250109 - Changing DOMEventTargetHelper subclasses to not assume that GetOwner() is non-null, since it can be nulled out by navigation. r?bzbarsky MozReview-Commit-ID: 8EGB58FWLi2
dom/base/ScreenOrientation.cpp
dom/base/nsPerformance.cpp
dom/battery/BatteryManager.cpp
dom/media/MediaRecorder.cpp
dom/notification/DesktopNotification.cpp
dom/notification/Notification.cpp
dom/presentation/PresentationReceiver.cpp
dom/tv/TVTuner.cpp
--- a/dom/base/ScreenOrientation.cpp
+++ b/dom/base/ScreenOrientation.cpp
@@ -343,16 +343,21 @@ ScreenOrientation::LockInternal(ScreenOr
   return p.forget();
 #endif
 }
 
 bool
 ScreenOrientation::LockDeviceOrientation(ScreenOrientationInternal aOrientation,
                                          bool aIsFullScreen, ErrorResult& aRv)
 {
+  if (!GetOwner()) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return false;
+  }
+
   nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
   // We need to register a listener so we learn when we leave full-screen
   // and when we will have to unlock the screen.
   // This needs to be done before LockScreenOrientation call to make sure
   // the locking can be unlocked.
   if (aIsFullScreen && !target) {
     return false;
   }
@@ -380,17 +385,18 @@ ScreenOrientation::Unlock(ErrorResult& a
   RefPtr<Promise> p = LockInternal(eScreenOrientation_None, aRv);
 }
 
 void
 ScreenOrientation::UnlockDeviceOrientation()
 {
   hal::UnlockScreenOrientation();
 
-  if (!mFullScreenListener) {
+  if (!mFullScreenListener || !GetOwner()) {
+    mFullScreenListener = nullptr;
     return;
   }
 
   // Remove event listener in case of fullscreen lock.
   nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
   if (target) {
     nsresult rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("fullscreenchange"),
                                                     mFullScreenListener, /* useCapture */ true);
--- a/dom/base/nsPerformance.cpp
+++ b/dom/base/nsPerformance.cpp
@@ -768,19 +768,25 @@ nsPerformance::IsObserverEnabled(JSConte
 
 void
 nsPerformance::InsertUserEntry(PerformanceEntry* aEntry)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoCString uri;
   uint64_t markCreationEpoch = 0;
+
   if (nsContentUtils::IsUserTimingLoggingEnabled() ||
       nsContentUtils::SendPerformanceTimingNotifications()) {
-    nsresult rv = GetOwner()->GetDocumentURI()->GetHost(uri);
+    nsresult rv = NS_ERROR_FAILURE;
+    nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
+    if (owner && owner->GetDocumentURI()) {
+      rv = owner->GetDocumentURI()->GetHost(uri);
+    }
+
     if(NS_FAILED(rv)) {
       // If we have no URI, just put in "none".
       uri.AssignLiteral("none");
     }
     markCreationEpoch = static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC);
 
     if (nsContentUtils::IsUserTimingLoggingEnabled()) {
       PerformanceBase::LogEntry(aEntry, uri);
--- a/dom/battery/BatteryManager.cpp
+++ b/dom/battery/BatteryManager.cpp
@@ -129,17 +129,17 @@ BatteryManager::Level() const
 }
 
 void
 BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo)
 {
   mLevel = aBatteryInfo.level();
 
   // Round to the nearest ten percent for non-chrome and non-certified apps
-  nsIDocument* doc = GetOwner()->GetDoc();
+  nsIDocument* doc = GetOwner() ? GetOwner()->GetDoc() : nullptr;
   uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
   if (doc) {
     doc->NodePrincipal()->GetAppStatus(&status);
   }
 
   if (!nsContentUtils::IsChromeDoc(doc) &&
       status != nsIPrincipal::APP_STATUS_CERTIFIED)
   {
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -552,16 +552,20 @@ private:
     } else {
       // Web Audio node has only audio.
       InitEncoder(ContainerWriter::CREATE_AUDIO_TRACK);
     }
   }
 
   bool CheckPermission(const char* aType)
   {
+    if (!mRecorder || !mRecorder->GetOwner()) {
+      return false;
+    }
+
     nsCOMPtr<nsIDocument> doc = mRecorder->GetOwner()->GetExtantDoc();
     if (!doc) {
       return false;
     }
 
     uint16_t appStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
     doc->NodePrincipal()->GetAppStatus(&appStatus);
 
@@ -1289,17 +1293,17 @@ MediaRecorder::GetSourceMediaStream()
 
 nsIPrincipal*
 MediaRecorder::GetSourcePrincipal()
 {
   if (mDOMStream != nullptr) {
     return mDOMStream->GetPrincipal();
   }
   MOZ_ASSERT(mAudioNode != nullptr);
-  nsIDocument* doc = mAudioNode->GetOwner()->GetExtantDoc();
+  nsIDocument* doc = mAudioNode->GetOwner() ? mAudioNode->GetOwner()->GetExtantDoc() : nullptr;
   return doc ? doc->NodePrincipal() : nullptr;
 }
 
 size_t
 MediaRecorder::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t amount = 42;
   for (size_t i = 0; i < mSessions.Length(); ++i) {
--- a/dom/notification/DesktopNotification.cpp
+++ b/dom/notification/DesktopNotification.cpp
@@ -73,17 +73,18 @@ DesktopNotification::PostDesktopNotifica
     mObserver = new AlertServiceObserver(this);
   }
 
 #ifdef MOZ_B2G
   nsCOMPtr<nsIAppNotificationService> appNotifier =
     do_GetService("@mozilla.org/system-alerts-service;1");
   if (appNotifier) {
     nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
-    uint32_t appId = (window.get())->GetDoc()->NodePrincipal()->GetAppId();
+    uint32_t appId = window ? window->GetDoc()->NodePrincipal()->GetAppId()
+                            : nsIScriptSecurityManager::UNKNOWN_APP_ID;
 
     if (appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
       nsCOMPtr<nsIAppsService> appsService = do_GetService("@mozilla.org/AppsService;1");
       nsString manifestUrl = EmptyString();
       appsService->GetManifestURLByLocalId(appId, manifestUrl);
       mozilla::AutoSafeJSContext cx;
       JS::Rooted<JS::Value> val(cx);
       AppNotificationServiceOptions ops;
@@ -106,17 +107,21 @@ DesktopNotification::PostDesktopNotifica
   }
 
   // Generate a unique name (which will also be used as a cookie) because
   // the nsIAlertsService will coalesce notifications with the same name.
   // In the case of IPC, the parent process will use the cookie to map
   // to nsIObservers, thus cookies must be unique to differentiate observers.
   nsString uniqueName = NS_LITERAL_STRING("desktop-notification:");
   uniqueName.AppendInt(sCount++);
-  nsCOMPtr<nsIDocument> doc = GetOwner()->GetDoc();
+  nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
+  if (!owner) {
+    return NS_ERROR_FAILURE;
+  }
+  nsCOMPtr<nsIDocument> doc = owner->GetDoc();
   nsIPrincipal* principal = doc->NodePrincipal();
   nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
   bool inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
   nsCOMPtr<nsIAlertNotification> alert =
     do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
   NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
   nsresult rv = alert->Init(uniqueName, mIconURL, mTitle,
                             mDescription,
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -1653,18 +1653,26 @@ ServiceWorkerNotificationObserver::Obser
   }
 
   return NS_OK;
 }
 
 bool
 Notification::IsInPrivateBrowsing()
 {
-  nsIDocument* doc = mWorkerPrivate ? mWorkerPrivate->GetDocument()
-                                    : GetOwner()->GetExtantDoc();
+  AssertIsOnMainThread();
+
+  nsIDocument* doc = nullptr;
+
+  if (mWorkerPrivate) {
+    doc = mWorkerPrivate->GetDocument();
+  } else if (GetOwner()) {
+    doc = GetOwner()->GetExtantDoc();
+  }
+
   if (doc) {
     nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
     return loadContext && loadContext->UsePrivateBrowsing();
   }
 
   if (mWorkerPrivate) {
     // Not all workers may have a document, but with Bug 1107516 fixed, they
     // should all have a loadcontext.
@@ -1760,17 +1768,19 @@ Notification::ShowInternal()
   nsCOMPtr<nsIAppNotificationService> appNotifier =
     do_GetService("@mozilla.org/system-alerts-service;1");
   if (appNotifier) {
     uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
     if (mWorkerPrivate) {
       appId = mWorkerPrivate->GetPrincipal()->GetAppId();
     } else {
       nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
-      appId = (window.get())->GetDoc()->NodePrincipal()->GetAppId();
+      if (window) {
+        appId = window->GetDoc()->NodePrincipal()->GetAppId();
+      }
     }
 
     if (appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
       nsCOMPtr<nsIAppsService> appsService = do_GetService("@mozilla.org/AppsService;1");
       nsString manifestUrl = EmptyString();
       nsresult rv = appsService->GetManifestURLByLocalId(appId, manifestUrl);
       if (NS_SUCCEEDED(rv)) {
         mozilla::AutoSafeJSContext cx;
@@ -1972,17 +1982,17 @@ Notification::ResolveIconAndSoundURL(nsS
   // the API base URL and no override encoding. So we've to use UTF-8 on
   // workers, but for backwards compat keeping it document charset on main
   // thread.
   const char* charset = "UTF-8";
 
   if (mWorkerPrivate) {
     baseUri = mWorkerPrivate->GetBaseURI();
   } else {
-    nsIDocument* doc = GetOwner()->GetExtantDoc();
+    nsIDocument* doc = GetOwner() ? GetOwner()->GetExtantDoc() : nullptr;
     if (doc) {
       baseUri = doc->GetBaseURI();
       charset = doc->GetDocumentCharacterSet().get();
     } else {
       NS_WARNING("No document found for main thread notification!");
       return NS_ERROR_FAILURE;
     }
   }
@@ -2756,17 +2766,17 @@ Notification::Observe(nsISupports* aSubj
       if (obs) {
         obs->RemoveObserver(this, DOM_WINDOW_DESTROYED_TOPIC);
         obs->RemoveObserver(this, DOM_WINDOW_FROZEN_TOPIC);
       }
 
       uint16_t appStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
       uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
 
-      nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
+      nsCOMPtr<nsIDocument> doc = window ? window->GetExtantDoc() : nullptr;
       nsCOMPtr<nsIPrincipal> nodePrincipal = doc ? doc->NodePrincipal() :
                                              nullptr;
       if (nodePrincipal) {
         appStatus = nodePrincipal->GetAppStatus();
         appId = nodePrincipal->GetAppId();
       }
 
       if (appStatus == nsIPrincipal::APP_STATUS_NOT_INSTALLED ||
--- a/dom/presentation/PresentationReceiver.cpp
+++ b/dom/presentation/PresentationReceiver.cpp
@@ -157,16 +157,20 @@ PresentationReceiver::GetConnections(Err
   promise->MaybeResolve(mConnections);
   return promise.forget();
 }
 
 NS_IMETHODIMP
 PresentationReceiver::NotifySessionConnect(uint64_t aWindowId,
                                            const nsAString& aSessionId)
 {
+  if (NS_WARN_IF(!GetOwner())) {
+    return NS_ERROR_FAILURE;
+  }
+
   if (NS_WARN_IF(aWindowId != GetOwner()->WindowID())) {
     return NS_ERROR_INVALID_ARG;
   }
 
   RefPtr<PresentationConnection> connection =
     PresentationConnection::Create(GetOwner(), aSessionId,
                                    PresentationConnectionState::Closed);
   if (NS_WARN_IF(!connection)) {
--- a/dom/tv/TVTuner.cpp
+++ b/dom/tv/TVTuner.cpp
@@ -219,22 +219,27 @@ TVTuner::InitMediaStream()
 
   mStream = stream.forget();
   return NS_OK;
 }
 
 already_AddRefed<DOMMediaStream>
 TVTuner::CreateSimulatedMediaStream()
 {
-  ErrorResult error;
+  nsCOMPtr<nsPIDOMWindowInner> domWin = GetOwner();
+  if (NS_WARN_IF(!domWin)) {
+    return nullptr;
+  }
 
-  nsIDocument* doc = GetOwner()->GetExtantDoc();
+  nsIDocument* doc = domWin->GetExtantDoc();
   if (NS_WARN_IF(!doc)) {
     return nullptr;
   }
+
+  ErrorResult error;
   RefPtr<Element> element = doc->CreateElement(VIDEO_TAG, error);
   if (NS_WARN_IF(error.Failed())) {
     return nullptr;
   }
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(element));
   if (NS_WARN_IF(!content)) {
     return nullptr;
@@ -250,21 +255,16 @@ TVTuner::CreateSimulatedMediaStream()
     return nullptr;
   }
 
   mediaElement->SetLoop(true, error);
   if (NS_WARN_IF(error.Failed())) {
     return nullptr;
   }
 
-  nsCOMPtr<nsPIDOMWindowInner> domWin = GetOwner();
-  if (NS_WARN_IF(!domWin)) {
-    return nullptr;
-  }
-
   nsCOMPtr<nsITVSimulatorService> simService(do_QueryInterface(mTVService));
   if (NS_WARN_IF(!simService)) {
     return nullptr;
   }
 
   if (NS_WARN_IF(!mCurrentSource)) {
     return nullptr;
   }