b=451938; ensure correct principal is used in case of <video> and drawImage; r=bz
authorVladimir Vukicevic <vladimir@pobox.com>
Sat, 06 Sep 2008 16:47:28 -0700
changeset 18910 ad53051ebd43cef1488b48175e8c88d2b5bdfb8a
parent 18909 4b551d0f3833f3b966c20c6476073ff6ad4a712e
child 18911 6b64d5fe2848a961353c55d21528dde6ec90d773
push id1817
push uservladimir@mozilla.com
push dateSat, 06 Sep 2008 23:48:22 +0000
treeherderautoland@ad53051ebd43 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs451938
milestone1.9.1b1pre
b=451938; ensure correct principal is used in case of <video> and drawImage; r=bz
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/html/content/public/nsHTMLMediaElement.h
content/html/content/src/nsHTMLMediaElement.cpp
content/media/video/public/nsChannelReader.h
content/media/video/public/nsOggDecoder.h
content/media/video/public/nsVideoDecoder.h
content/media/video/src/nsChannelReader.cpp
content/media/video/src/nsOggDecoder.cpp
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -2799,16 +2799,22 @@ nsCanvasRenderingContext2D::ThebesSurfac
         return NS_OK;
     }
 
 #ifdef MOZ_MEDIA
     /* Maybe it's <video>? */
     nsCOMPtr<nsIDOMHTMLVideoElement> ve = do_QueryInterface(imgElt);
     if (node && ve) {
         nsHTMLVideoElement *video = static_cast<nsHTMLVideoElement*>(ve.get());
+
+        /* If it doesn't have a principal, just bail */
+        nsCOMPtr<nsIPrincipal> principal = video->GetCurrentPrincipal();
+        if (!principal)
+            return NS_ERROR_DOM_SECURITY_ERR;
+
         PRUint32 videoWidth, videoHeight;
         rv = video->GetVideoWidth(&videoWidth);
         rv |= video->GetVideoHeight(&videoHeight);
         if (NS_FAILED(rv))
             return NS_ERROR_NOT_AVAILABLE;
 
         nsRefPtr<gfxASurface> surf =
             gfxPlatform::GetPlatform()->CreateOffscreenSurface
@@ -2818,17 +2824,17 @@ nsCanvasRenderingContext2D::ThebesSurfac
         ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
 
         video->Paint(ctx, gfxRect(0, 0, videoWidth, videoHeight));
 
         *aSurface = surf.forget().get();
         *widthOut = videoWidth;
         *heightOut = videoHeight;
 
-        NS_ADDREF(*prinOut = node->NodePrincipal());
+        *prinOut = principal.forget().get();
         *forceWriteOnlyOut = PR_FALSE;
 
         return NS_OK;
     }
 #endif
 
     /* Finally, check if it's a normal image */
     nsCOMPtr<imgIContainer> imgContainer;
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -113,16 +113,19 @@ public:
   nsresult DispatchProgressEvent(const nsAString& aName);
   nsresult DispatchAsyncSimpleEvent(const nsAString& aName);
   nsresult DispatchAsyncProgressEvent(const nsAString& aName);
 
   // Use this method to change the mReadyState member, so required
   // events can be fired.
   void ChangeReadyState(nsMediaReadyState aState);
 
+  // principal of the currently playing stream
+  nsIPrincipal* GetCurrentPrincipal();
+
 protected:
   nsresult PickMediaElement(nsAString& aChosenMediaResource);
   virtual nsresult InitializeDecoder(nsAString& aChosenMediaResource);
 
   nsRefPtr<nsVideoDecoder> mDecoder;
 
   // Error attribute
   nsCOMPtr<nsIDOMHTMLMediaError> mError;
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -768,8 +768,17 @@ nsresult nsHTMLMediaElement::DoneAddingC
 
   return NS_OK;
 }
 
 PRBool nsHTMLMediaElement::IsDoneAddingChildren()
 {
   return mIsDoneAddingChildren;
 }
+
+nsIPrincipal*
+nsHTMLMediaElement::GetCurrentPrincipal()
+{
+  if (!mDecoder)
+    return nsnull;
+
+  return mDecoder->GetCurrentPrincipal();
+}
--- a/content/media/video/public/nsChannelReader.h
+++ b/content/media/video/public/nsChannelReader.h
@@ -39,16 +39,17 @@
 #define nsChannelReader_h___
 
 #include "nsCOMPtr.h"
 #include "nsIChannel.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsIRequestObserver.h"
 #include "nsIStreamListener.h"
+#include "nsIPrincipal.h"
 
 #include "oggplay/oggplay.h"
 
 class nsOggDecoder;
 
 /* 
    Reads all data on the input stream of a channel and
    writes it to a pipe. This allows a seperate thread to
@@ -67,19 +68,22 @@ class nsChannelToPipeListener : public n
 
   public:
   nsChannelToPipeListener(nsOggDecoder* aDecoder);
   nsresult Init();
   void GetInputStream(nsIInputStream** aStream);
   void Stop();
   double BytesPerSecond() const;
 
+  nsIPrincipal* GetCurrentPrincipal();
+
 private:
   nsCOMPtr<nsIInputStream> mInput;
   nsCOMPtr<nsIOutputStream> mOutput;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
   nsOggDecoder* mDecoder;
 
   // Interval when download started. Used in
   // computing bytes per second download rate.
   PRIntervalTime mIntervalStart;
 
   // Interval when last downloaded bytes occurred. Used in computer
   // bytes per second download rate.
@@ -99,17 +103,20 @@ public:
   OggPlayErrorCode destroy();
   size_t io_read(char* aBuffer, size_t aCount);
   int io_seek(long aOffset, int aWhence);
   long io_tell();  
 
   // Return average number of bytes per second that the 
   // download of the media resource is achieving.
   double BytesPerSecond() const;
-  
+
+  // return the principal that we saved in GetRequest
+  nsIPrincipal* GetCurrentPrincipal();
+
 public:
   nsCOMPtr<nsIChannel>  mChannel;
   nsCOMPtr<nsIInputStream>  mInput;
   nsCOMPtr<nsChannelToPipeListener> mListener;
   unsigned long mCurrentPosition;
 };
 
 #endif
--- a/content/media/video/public/nsOggDecoder.h
+++ b/content/media/video/public/nsOggDecoder.h
@@ -162,16 +162,17 @@ class nsOggDecoder : public nsVideoDecod
   nsresult PlaybackRateChanged();
 
   void Pause();
   float GetVolume();
   void SetVolume(float volume);
   float GetDuration();
 
   void GetCurrentURI(nsIURI** aURI);
+  nsIPrincipal* GetCurrentPrincipal();
 
   virtual void UpdateBytesDownloaded(PRUint32 aBytes);
 
 protected:
   /******
    * The following methods must only be called on the presentation
    * thread.
    ******/
--- a/content/media/video/public/nsVideoDecoder.h
+++ b/content/media/video/public/nsVideoDecoder.h
@@ -65,20 +65,22 @@ class nsVideoDecoder : public nsIObserve
   // Initialize the logging object
   static nsresult InitLogger();
 
   // Perform any initialization required for the decoder.
   // Return PR_TRUE on successful initialisation, PR_FALSE
   // on failure.
   virtual PRBool Init();
 
-  
   // Return the current URI being played or downloaded.
   virtual void GetCurrentURI(nsIURI** aURI) = 0;
 
+  // Return the principal of the current URI being played or downloaded.
+  virtual nsIPrincipal* GetCurrentPrincipal() = 0;
+
   // Return the time position in the video stream being
   // played measured in seconds.
   virtual float GetCurrentTime() = 0;
 
   // Seek to the time position in (seconds) from the start of the video.
   virtual nsresult Seek(float time) = 0;
 
   // Called by the element when the playback rate has been changed.
--- a/content/media/video/src/nsChannelReader.cpp
+++ b/content/media/video/src/nsChannelReader.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsAString.h"
 #include "nsThreadUtils.h"
 #include "nsNetUtil.h"
 #include "prlog.h"
 #include "nsOggDecoder.h"
 #include "nsChannelReader.h"
+#include "nsIScriptSecurityManager.h"
 
 nsChannelToPipeListener::nsChannelToPipeListener(nsOggDecoder* aDecoder) :
   mDecoder(aDecoder),
   mIntervalStart(0),
   mIntervalEnd(0),
   mTotalBytes(0)
 {
 }
@@ -82,16 +83,31 @@ void nsChannelToPipeListener::GetInputSt
 }
 
 nsresult nsChannelToPipeListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
 {
   mIntervalStart = PR_IntervalNow();
   mIntervalEnd = mIntervalStart;
   mTotalBytes = 0;
   mDecoder->UpdateBytesDownloaded(mTotalBytes);
+
+  /* Get our principal */
+  nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
+  if (chan) {
+    nsCOMPtr<nsIScriptSecurityManager> secMan =
+      do_GetService("@mozilla.org/scriptsecuritymanager;1");
+    if (secMan) {
+      nsresult rv = secMan->GetChannelPrincipal(chan,
+                                                getter_AddRefs(mPrincipal));
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+    }
+  }
+
   return NS_OK;
 }
 
 nsresult nsChannelToPipeListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus) 
 {
   mOutput = nsnull;
   if (mDecoder) {
     mDecoder->ResourceLoaded();
@@ -119,16 +135,22 @@ nsresult nsChannelToPipeListener::OnData
     
     nsresult rv = mOutput->Flush();
     NS_ENSURE_SUCCESS(rv, rv);
     mIntervalEnd = PR_IntervalNow();
   }
   return NS_OK;
 }
 
+nsIPrincipal*
+nsChannelToPipeListener::GetCurrentPrincipal()
+{
+  return mPrincipal;
+}
+
 NS_IMPL_ISUPPORTS2(nsChannelToPipeListener, nsIRequestObserver, nsIStreamListener)
 
 PRUint32 nsChannelReader::Available()
 {
   PRUint32 available = 0;
   mInput->Available(&available);
   return available;
 }
@@ -248,8 +270,16 @@ nsChannelReader::nsChannelReader()
   OggPlayReader* reader = this;
   reader->initialise = &oggplay_channel_reader_initialise;
   reader->destroy = &oggplay_channel_reader_destroy;
   reader->seek = nsnull;
   reader->io_read = &oggplay_channel_reader_io_read;
   reader->io_seek = &oggplay_channel_reader_io_seek;
   reader->io_tell = &oggplay_channel_reader_io_tell;
 }
+
+nsIPrincipal*
+nsChannelReader::GetCurrentPrincipal()
+{
+  if (!mListener)
+    return nsnull;
+  return mListener->GetCurrentPrincipal();
+}
--- a/content/media/video/src/nsOggDecoder.cpp
+++ b/content/media/video/src/nsOggDecoder.cpp
@@ -727,16 +727,23 @@ float nsOggDecoder::GetCurrentTime()
   return mVideoCurrentFrameTime;
 }
 
 void nsOggDecoder::GetCurrentURI(nsIURI** aURI)
 {
   NS_IF_ADDREF(*aURI = mURI);
 }
 
+nsIPrincipal* nsOggDecoder::GetCurrentPrincipal()
+{
+  if (!mReader)
+    return nsnull;
+
+  return mReader->GetCurrentPrincipal();
+}
 
 void nsOggDecoder::DisplayFirstFrame()
 {
   // Step through the decoded frames, allowing display of the first frame
   // of video.
   StepDisplay();
 }