content/html/document/src/MediaDocument.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "MediaDocument.h"
     7 #include "nsGkAtoms.h"
     8 #include "nsRect.h"
     9 #include "nsPresContext.h"
    10 #include "nsIPresShell.h"
    11 #include "nsIScrollable.h"
    12 #include "nsViewManager.h"
    13 #include "nsITextToSubURI.h"
    14 #include "nsIURL.h"
    15 #include "nsIContentViewer.h"
    16 #include "nsIMarkupDocumentViewer.h"
    17 #include "nsIDocShell.h"
    18 #include "nsCharsetSource.h" // kCharsetFrom* macro definition
    19 #include "nsNodeInfoManager.h"
    20 #include "nsContentUtils.h"
    21 #include "nsDocElementCreatedNotificationRunner.h"
    22 #include "mozilla/Services.h"
    23 #include "nsServiceManagerUtils.h"
    24 #include "nsIPrincipal.h"
    26 namespace mozilla {
    27 namespace dom {
    29 MediaDocumentStreamListener::MediaDocumentStreamListener(MediaDocument *aDocument)
    30 {
    31   mDocument = aDocument;
    32 }
    34 MediaDocumentStreamListener::~MediaDocumentStreamListener()
    35 {
    36 }
    39 NS_IMPL_ISUPPORTS(MediaDocumentStreamListener,
    40                   nsIRequestObserver,
    41                   nsIStreamListener)
    44 void
    45 MediaDocumentStreamListener::SetStreamListener(nsIStreamListener *aListener)
    46 {
    47   mNextStream = aListener;
    48 }
    50 NS_IMETHODIMP
    51 MediaDocumentStreamListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
    52 {
    53   NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
    55   mDocument->StartLayout();
    57   if (mNextStream) {
    58     return mNextStream->OnStartRequest(request, ctxt);
    59   }
    61   return NS_BINDING_ABORTED;
    62 }
    64 NS_IMETHODIMP
    65 MediaDocumentStreamListener::OnStopRequest(nsIRequest* request,
    66                                            nsISupports *ctxt,
    67                                            nsresult status)
    68 {
    69   nsresult rv = NS_OK;
    70   if (mNextStream) {
    71     rv = mNextStream->OnStopRequest(request, ctxt, status);
    72   }
    74   // No more need for our document so clear our reference and prevent leaks
    75   mDocument = nullptr;
    77   return rv;
    78 }
    80 NS_IMETHODIMP
    81 MediaDocumentStreamListener::OnDataAvailable(nsIRequest* request,
    82                                              nsISupports *ctxt,
    83                                              nsIInputStream *inStr,
    84                                              uint64_t sourceOffset,
    85                                              uint32_t count)
    86 {
    87   if (mNextStream) {
    88     return mNextStream->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
    89   }
    91   return NS_OK;
    92 }
    94 // default format names for MediaDocument. 
    95 const char* const MediaDocument::sFormatNames[4] = 
    96 {
    97   "MediaTitleWithNoInfo",    // eWithNoInfo
    98   "MediaTitleWithFile",      // eWithFile
    99   "",                        // eWithDim
   100   ""                         // eWithDimAndFile
   101 };
   103 MediaDocument::MediaDocument()
   104     : nsHTMLDocument(),
   105       mDocumentElementInserted(false)
   106 {
   107 }
   108 MediaDocument::~MediaDocument()
   109 {
   110 }
   112 nsresult
   113 MediaDocument::Init()
   114 {
   115   nsresult rv = nsHTMLDocument::Init();
   116   NS_ENSURE_SUCCESS(rv, rv);
   118   // Create a bundle for the localization
   119   nsCOMPtr<nsIStringBundleService> stringService =
   120     mozilla::services::GetStringBundleService();
   121   if (stringService) {
   122     stringService->CreateBundle(NSMEDIADOCUMENT_PROPERTIES_URI,
   123                                 getter_AddRefs(mStringBundle));
   124   }
   126   mIsSyntheticDocument = true;
   128   return NS_OK;
   129 }
   131 nsresult
   132 MediaDocument::StartDocumentLoad(const char*         aCommand,
   133                                  nsIChannel*         aChannel,
   134                                  nsILoadGroup*       aLoadGroup,
   135                                  nsISupports*        aContainer,
   136                                  nsIStreamListener** aDocListener,
   137                                  bool                aReset,
   138                                  nsIContentSink*     aSink)
   139 {
   140   nsresult rv = nsDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup,
   141                                               aContainer, aDocListener, aReset,
   142                                               aSink);
   143   if (NS_FAILED(rv)) {
   144     return rv;
   145   }
   147   // We try to set the charset of the current document to that of the 
   148   // 'genuine' (as opposed to an intervening 'chrome') parent document 
   149   // that may be in a different window/tab. Even if we fail here,
   150   // we just return NS_OK because another attempt is made in 
   151   // |UpdateTitleAndCharset| and the worst thing possible is a mangled 
   152   // filename in the titlebar and the file picker.
   154   // Note that we
   155   // exclude UTF-8 as 'invalid' because UTF-8 is likely to be the charset 
   156   // of a chrome document that has nothing to do with the actual content 
   157   // whose charset we want to know. Even if "the actual content" is indeed 
   158   // in UTF-8, we don't lose anything because the default empty value is 
   159   // considered synonymous with UTF-8. 
   161   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
   163   // not being able to set the charset is not critical.
   164   NS_ENSURE_TRUE(docShell, NS_OK); 
   166   nsAutoCString charset;
   167   int32_t source;
   168   nsCOMPtr<nsIPrincipal> principal;
   169   // opening in a new tab
   170   docShell->GetParentCharset(charset, &source, getter_AddRefs(principal));
   172   if (!charset.IsEmpty() &&
   173       !charset.Equals("UTF-8") &&
   174       NodePrincipal()->Equals(principal)) {
   175     SetDocumentCharacterSetSource(source);
   176     SetDocumentCharacterSet(charset);
   177   }
   179   return NS_OK;
   180 }
   182 void
   183 MediaDocument::BecomeInteractive()
   184 {
   185   // In principle, if we knew the readyState code to work, we could infer
   186   // restoration from GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE.
   187   bool restoring = false;
   188   nsPIDOMWindow* window = GetWindow();
   189   if (window) {
   190     nsIDocShell* docShell = window->GetDocShell();
   191     if (docShell) {
   192       docShell->GetRestoringDocument(&restoring);
   193     }
   194   }
   195   if (!restoring) {
   196     MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_LOADING,
   197                "Bad readyState");
   198     SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
   199   }
   200 }
   202 nsresult
   203 MediaDocument::CreateSyntheticDocument()
   204 {
   205   // Synthesize an empty html document
   206   nsresult rv;
   208   nsCOMPtr<nsINodeInfo> nodeInfo;
   209   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::html, nullptr,
   210                                            kNameSpaceID_XHTML,
   211                                            nsIDOMNode::ELEMENT_NODE);
   213   nsRefPtr<nsGenericHTMLElement> root = NS_NewHTMLHtmlElement(nodeInfo.forget());
   214   NS_ENSURE_TRUE(root, NS_ERROR_OUT_OF_MEMORY);
   216   NS_ASSERTION(GetChildCount() == 0, "Shouldn't have any kids");
   217   rv = AppendChildTo(root, false);
   218   NS_ENSURE_SUCCESS(rv, rv);
   220   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::head, nullptr,
   221                                            kNameSpaceID_XHTML,
   222                                            nsIDOMNode::ELEMENT_NODE);
   224   // Create a <head> so our title has somewhere to live
   225   nsRefPtr<nsGenericHTMLElement> head = NS_NewHTMLHeadElement(nodeInfo.forget());
   226   NS_ENSURE_TRUE(head, NS_ERROR_OUT_OF_MEMORY);
   228   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::meta, nullptr,
   229                                            kNameSpaceID_XHTML,
   230                                            nsIDOMNode::ELEMENT_NODE);
   232   nsRefPtr<nsGenericHTMLElement> metaContent = NS_NewHTMLMetaElement(nodeInfo.forget());
   233   NS_ENSURE_TRUE(metaContent, NS_ERROR_OUT_OF_MEMORY);
   234   metaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
   235                        NS_LITERAL_STRING("viewport"),
   236                        true);
   238   metaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::content,
   239                        NS_LITERAL_STRING("width=device-width; height=device-height;"),
   240                        true);
   241   head->AppendChildTo(metaContent, false);
   243   root->AppendChildTo(head, false);
   245   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::body, nullptr,
   246                                            kNameSpaceID_XHTML,
   247                                            nsIDOMNode::ELEMENT_NODE);
   249   nsRefPtr<nsGenericHTMLElement> body = NS_NewHTMLBodyElement(nodeInfo.forget());
   250   NS_ENSURE_TRUE(body, NS_ERROR_OUT_OF_MEMORY);
   252   root->AppendChildTo(body, false);
   254   return NS_OK;
   255 }
   257 nsresult
   258 MediaDocument::StartLayout()
   259 {
   260   mMayStartLayout = true;
   261   nsCOMPtr<nsIPresShell> shell = GetShell();
   262   // Don't mess with the presshell if someone has already handled
   263   // its initial reflow.
   264   if (shell && !shell->DidInitialize()) {
   265     nsRect visibleArea = shell->GetPresContext()->GetVisibleArea();
   266     nsresult rv = shell->Initialize(visibleArea.width, visibleArea.height);
   267     NS_ENSURE_SUCCESS(rv, rv);
   268   }
   270   return NS_OK;
   271 }
   273 void
   274 MediaDocument::GetFileName(nsAString& aResult)
   275 {
   276   aResult.Truncate();
   278   nsCOMPtr<nsIURL> url = do_QueryInterface(mDocumentURI);
   279   if (!url)
   280     return;
   282   nsAutoCString fileName;
   283   url->GetFileName(fileName);
   284   if (fileName.IsEmpty())
   285     return;
   287   nsAutoCString docCharset;
   288   // Now that the charset is set in |StartDocumentLoad| to the charset of
   289   // the document viewer instead of a bogus value ("ISO-8859-1" set in
   290   // |nsDocument|'s ctor), the priority is given to the current charset. 
   291   // This is necessary to deal with a media document being opened in a new 
   292   // window or a new tab, in which case |originCharset| of |nsIURI| is not 
   293   // reliable.
   294   if (mCharacterSetSource != kCharsetUninitialized) {  
   295     docCharset = mCharacterSet;
   296   } else {  
   297     // resort to |originCharset|
   298     url->GetOriginCharset(docCharset);
   299     SetDocumentCharacterSet(docCharset);
   300   }
   302   nsresult rv;
   303   nsCOMPtr<nsITextToSubURI> textToSubURI = 
   304     do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
   305   if (NS_SUCCEEDED(rv)) {
   306     // UnEscapeURIForUI always succeeds
   307     textToSubURI->UnEscapeURIForUI(docCharset, fileName, aResult);
   308   } else {
   309     CopyUTF8toUTF16(fileName, aResult);
   310   }
   311 }
   313 nsresult
   314 MediaDocument::LinkStylesheet(const nsAString& aStylesheet)
   315 {
   316   nsCOMPtr<nsINodeInfo> nodeInfo;
   317   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::link, nullptr,
   318                                            kNameSpaceID_XHTML,
   319                                            nsIDOMNode::ELEMENT_NODE);
   321   nsRefPtr<nsGenericHTMLElement> link = NS_NewHTMLLinkElement(nodeInfo.forget());
   322   NS_ENSURE_TRUE(link, NS_ERROR_OUT_OF_MEMORY);
   324   link->SetAttr(kNameSpaceID_None, nsGkAtoms::rel, 
   325                 NS_LITERAL_STRING("stylesheet"), true);
   327   link->SetAttr(kNameSpaceID_None, nsGkAtoms::href, aStylesheet, true);
   329   Element* head = GetHeadElement();
   330   return head->AppendChildTo(link, false);
   331 }
   333 void 
   334 MediaDocument::UpdateTitleAndCharset(const nsACString& aTypeStr,
   335                                      const char* const* aFormatNames,
   336                                      int32_t aWidth, int32_t aHeight,
   337                                      const nsAString& aStatus)
   338 {
   339   nsXPIDLString fileStr;
   340   GetFileName(fileStr);
   342   NS_ConvertASCIItoUTF16 typeStr(aTypeStr);
   343   nsXPIDLString title;
   345   if (mStringBundle) {
   346     // if we got a valid size (not all media have a size)
   347     if (aWidth != 0 && aHeight != 0) {
   348       nsAutoString widthStr;
   349       nsAutoString heightStr;
   350       widthStr.AppendInt(aWidth);
   351       heightStr.AppendInt(aHeight);
   352       // If we got a filename, display it
   353       if (!fileStr.IsEmpty()) {
   354         const char16_t *formatStrings[4]  = {fileStr.get(), typeStr.get(), 
   355           widthStr.get(), heightStr.get()};
   356         NS_ConvertASCIItoUTF16 fmtName(aFormatNames[eWithDimAndFile]);
   357         mStringBundle->FormatStringFromName(fmtName.get(), formatStrings, 4,
   358                                             getter_Copies(title));
   359       } 
   360       else {
   361         const char16_t *formatStrings[3]  = {typeStr.get(), widthStr.get(), 
   362           heightStr.get()};
   363         NS_ConvertASCIItoUTF16 fmtName(aFormatNames[eWithDim]);
   364         mStringBundle->FormatStringFromName(fmtName.get(), formatStrings, 3,
   365                                             getter_Copies(title));
   366       }
   367     } 
   368     else {
   369     // If we got a filename, display it
   370       if (!fileStr.IsEmpty()) {
   371         const char16_t *formatStrings[2] = {fileStr.get(), typeStr.get()};
   372         NS_ConvertASCIItoUTF16 fmtName(aFormatNames[eWithFile]);
   373         mStringBundle->FormatStringFromName(fmtName.get(), formatStrings, 2,
   374                                             getter_Copies(title));
   375       }
   376       else {
   377         const char16_t *formatStrings[1] = {typeStr.get()};
   378         NS_ConvertASCIItoUTF16 fmtName(aFormatNames[eWithNoInfo]);
   379         mStringBundle->FormatStringFromName(fmtName.get(), formatStrings, 1,
   380                                             getter_Copies(title));
   381       }
   382     }
   383   } 
   385   // set it on the document
   386   if (aStatus.IsEmpty()) {
   387     SetTitle(title);
   388   }
   389   else {
   390     nsXPIDLString titleWithStatus;
   391     const nsPromiseFlatString& status = PromiseFlatString(aStatus);
   392     const char16_t *formatStrings[2] = {title.get(), status.get()};
   393     NS_NAMED_LITERAL_STRING(fmtName, "TitleWithStatus");
   394     mStringBundle->FormatStringFromName(fmtName.get(), formatStrings, 2,
   395                                         getter_Copies(titleWithStatus));
   396     SetTitle(titleWithStatus);
   397   }
   398 }
   400 void 
   401 MediaDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject)
   402 {
   403     nsHTMLDocument::SetScriptGlobalObject(aGlobalObject);
   404     if (!mDocumentElementInserted && aGlobalObject) {
   405         mDocumentElementInserted = true;
   406         nsContentUtils::AddScriptRunner(
   407             new nsDocElementCreatedNotificationRunner(this));        
   408     }
   409 }
   411 } // namespace dom
   412 } // namespace mozilla

mercurial