LCOV - code coverage report
Current view: top level - netwerk/base - nsMediaFragmentURIParser.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 206 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsTArray.h"
       8             : #include "nsCharSeparatedTokenizer.h"
       9             : #include "nsEscape.h"
      10             : #include "nsIURI.h"
      11             : #include <utility>
      12             : 
      13             : #include "nsMediaFragmentURIParser.h"
      14             : 
      15             : using std::pair;
      16             : using std::make_pair;
      17             : 
      18             : namespace mozilla { namespace net {
      19             : 
      20           0 : nsMediaFragmentURIParser::nsMediaFragmentURIParser(nsIURI* aURI)
      21           0 :   : mClipUnit(eClipUnit_Pixel)
      22             : {
      23           0 :   nsAutoCString ref;
      24           0 :   aURI->GetRef(ref);
      25           0 :   Parse(ref);
      26           0 : }
      27             : 
      28           0 : nsMediaFragmentURIParser::nsMediaFragmentURIParser(nsCString& aRef)
      29           0 :   : mClipUnit(eClipUnit_Pixel)
      30             : {
      31           0 :   Parse(aRef);
      32           0 : }
      33             : 
      34           0 : bool nsMediaFragmentURIParser::ParseNPT(nsDependentSubstring aString)
      35             : {
      36           0 :   nsDependentSubstring original(aString);
      37           0 :   if (aString.Length() > 4 &&
      38           0 :       aString[0] == 'n' && aString[1] == 'p' &&
      39           0 :       aString[2] == 't' && aString[3] == ':') {
      40           0 :     aString.Rebind(aString, 4);
      41             :   }
      42             : 
      43           0 :   if (aString.Length() == 0) {
      44           0 :     return false;
      45             :   }
      46             : 
      47           0 :   double start = -1.0;
      48           0 :   double end = -1.0;
      49             : 
      50           0 :   ParseNPTTime(aString, start);
      51             : 
      52           0 :   if (aString.Length() == 0) {
      53           0 :     mStart.emplace(start);
      54           0 :     return true;
      55             :   }
      56             : 
      57           0 :   if (aString[0] != ',') {
      58           0 :     aString.Rebind(original, 0);
      59           0 :     return false;
      60             :   }
      61             : 
      62           0 :   aString.Rebind(aString, 1);
      63             : 
      64           0 :   if (aString.Length() == 0) {
      65           0 :     aString.Rebind(original, 0);
      66           0 :     return false;
      67             :   }
      68             : 
      69           0 :   ParseNPTTime(aString, end);
      70             : 
      71           0 :   if (end <= start || aString.Length() != 0) {
      72           0 :     aString.Rebind(original, 0);
      73           0 :     return false;
      74             :   }
      75             : 
      76           0 :   mStart.emplace(start);
      77           0 :   mEnd.emplace(end);
      78           0 :   return true;
      79             : }
      80             : 
      81           0 : bool nsMediaFragmentURIParser::ParseNPTTime(nsDependentSubstring& aString, double& aTime)
      82             : {
      83           0 :   if (aString.Length() == 0) {
      84           0 :     return false;
      85             :   }
      86             : 
      87             :   return
      88           0 :     ParseNPTHHMMSS(aString, aTime) ||
      89           0 :     ParseNPTMMSS(aString, aTime) ||
      90           0 :     ParseNPTSec(aString, aTime);
      91             : }
      92             : 
      93             : // Return true if the given character is a numeric character
      94           0 : static bool IsDigit(nsDependentSubstring::char_type aChar)
      95             : {
      96           0 :   return (aChar >= '0' && aChar <= '9');
      97             : }
      98             : 
      99             : // Return the index of the first character in the string that is not
     100             : // a numerical digit, starting from 'aStart'.
     101           0 : static uint32_t FirstNonDigit(nsDependentSubstring& aString, uint32_t aStart)
     102             : {
     103           0 :    while (aStart < aString.Length() && IsDigit(aString[aStart])) {
     104           0 :     ++aStart;
     105             :   }
     106           0 :   return aStart;
     107             : }
     108             : 
     109           0 : bool nsMediaFragmentURIParser::ParseNPTSec(nsDependentSubstring& aString, double& aSec)
     110             : {
     111           0 :   nsDependentSubstring original(aString);
     112           0 :   if (aString.Length() == 0) {
     113           0 :     return false;
     114             :   }
     115             : 
     116           0 :   uint32_t index = FirstNonDigit(aString, 0);
     117           0 :   if (index == 0) {
     118           0 :     return false;
     119             :   }
     120             : 
     121           0 :   nsDependentSubstring n(aString, 0, index);
     122             :   nsresult ec;
     123           0 :   int32_t s = PromiseFlatString(n).ToInteger(&ec);
     124           0 :   if (NS_FAILED(ec)) {
     125           0 :     return false;
     126             :   }
     127             : 
     128           0 :   aString.Rebind(aString, index);
     129           0 :   double fraction = 0.0;
     130           0 :   if (!ParseNPTFraction(aString, fraction)) {
     131           0 :     aString.Rebind(original, 0);
     132           0 :     return false;
     133             :   }
     134             : 
     135           0 :   aSec = s + fraction;
     136           0 :   return true;
     137             : }
     138             : 
     139           0 : bool nsMediaFragmentURIParser::ParseNPTMMSS(nsDependentSubstring& aString, double& aTime)
     140             : {
     141           0 :   nsDependentSubstring original(aString);
     142           0 :   uint32_t mm = 0;
     143           0 :   uint32_t ss = 0;
     144           0 :   double fraction = 0.0;
     145           0 :   if (!ParseNPTMM(aString, mm)) {
     146           0 :     aString.Rebind(original, 0);
     147           0 :     return false;
     148             :   }
     149             : 
     150           0 :   if (aString.Length() < 2 || aString[0] != ':') {
     151           0 :     aString.Rebind(original, 0);
     152           0 :     return false;
     153             :   }
     154             : 
     155           0 :   aString.Rebind(aString, 1);
     156           0 :   if (!ParseNPTSS(aString, ss)) {
     157           0 :     aString.Rebind(original, 0);
     158           0 :     return false;
     159             :   }
     160             : 
     161           0 :   if (!ParseNPTFraction(aString, fraction)) {
     162           0 :     aString.Rebind(original, 0);
     163           0 :     return false;
     164             :   }
     165           0 :   aTime = mm * 60 + ss + fraction;
     166           0 :   return true;
     167             : }
     168             : 
     169           0 : bool nsMediaFragmentURIParser::ParseNPTFraction(nsDependentSubstring& aString, double& aFraction)
     170             : {
     171           0 :   double fraction = 0.0;
     172             : 
     173           0 :   if (aString.Length() > 0 && aString[0] == '.') {
     174           0 :     uint32_t index = FirstNonDigit(aString, 1);
     175             : 
     176           0 :     if (index > 1) {
     177           0 :       nsDependentSubstring number(aString, 0, index);
     178             :       nsresult ec;
     179           0 :       fraction = PromiseFlatString(number).ToDouble(&ec);
     180           0 :       if (NS_FAILED(ec)) {
     181           0 :         return false;
     182             :       }
     183             :     }
     184           0 :     aString.Rebind(aString, index);
     185             :   }
     186             : 
     187           0 :   aFraction = fraction;
     188           0 :   return true;
     189             : }
     190             : 
     191           0 : bool nsMediaFragmentURIParser::ParseNPTHHMMSS(nsDependentSubstring& aString, double& aTime)
     192             : {
     193           0 :   nsDependentSubstring original(aString);
     194           0 :   uint32_t hh = 0;
     195           0 :   double seconds = 0.0;
     196           0 :   if (!ParseNPTHH(aString, hh)) {
     197           0 :     return false;
     198             :   }
     199             : 
     200           0 :   if (aString.Length() < 2 || aString[0] != ':') {
     201           0 :     aString.Rebind(original, 0);
     202           0 :     return false;
     203             :   }
     204             : 
     205           0 :   aString.Rebind(aString, 1);
     206           0 :   if (!ParseNPTMMSS(aString, seconds)) {
     207           0 :     aString.Rebind(original, 0);
     208           0 :     return false;
     209             :   }
     210             : 
     211           0 :   aTime = hh * 3600 + seconds;
     212           0 :   return true;
     213             : }
     214             : 
     215           0 : bool nsMediaFragmentURIParser::ParseNPTHH(nsDependentSubstring& aString, uint32_t& aHour)
     216             : {
     217           0 :   if (aString.Length() == 0) {
     218           0 :     return false;
     219             :   }
     220             : 
     221           0 :   uint32_t index = FirstNonDigit(aString, 0);
     222           0 :   if (index == 0) {
     223           0 :     return false;
     224             :   }
     225             : 
     226           0 :   nsDependentSubstring n(aString, 0, index);
     227             :   nsresult ec;
     228           0 :   int32_t u = PromiseFlatString(n).ToInteger(&ec);
     229           0 :   if (NS_FAILED(ec)) {
     230           0 :     return false;
     231             :   }
     232             : 
     233           0 :   aString.Rebind(aString, index);
     234           0 :   aHour = u;
     235           0 :   return true;
     236             : }
     237             : 
     238           0 : bool nsMediaFragmentURIParser::ParseNPTMM(nsDependentSubstring& aString, uint32_t& aMinute)
     239             : {
     240           0 :   return ParseNPTSS(aString, aMinute);
     241             : }
     242             : 
     243           0 : bool nsMediaFragmentURIParser::ParseNPTSS(nsDependentSubstring& aString, uint32_t& aSecond)
     244             : {
     245           0 :   if (aString.Length() < 2) {
     246           0 :     return false;
     247             :   }
     248             : 
     249           0 :   if (IsDigit(aString[0]) && IsDigit(aString[1])) {
     250           0 :     nsDependentSubstring n(aString, 0, 2);
     251             :     nsresult ec;
     252           0 :     int32_t u = PromiseFlatString(n).ToInteger(&ec);
     253           0 :     if (NS_FAILED(ec)) {
     254           0 :       return false;
     255             :     }
     256             : 
     257           0 :     aString.Rebind(aString, 2);
     258           0 :     if (u >= 60)
     259           0 :       return false;
     260             : 
     261           0 :     aSecond = u;
     262           0 :     return true;
     263             :   }
     264             : 
     265           0 :   return false;
     266             : }
     267             : 
     268           0 : static bool ParseInteger(nsDependentSubstring& aString,
     269             :                          int32_t& aResult)
     270             : {
     271           0 :   uint32_t index = FirstNonDigit(aString, 0);
     272           0 :   if (index == 0) {
     273           0 :     return false;
     274             :   }
     275             : 
     276           0 :   nsDependentSubstring n(aString, 0, index);
     277             :   nsresult ec;
     278           0 :   int32_t s = PromiseFlatString(n).ToInteger(&ec);
     279           0 :   if (NS_FAILED(ec)) {
     280           0 :     return false;
     281             :   }
     282             : 
     283           0 :   aString.Rebind(aString, index);
     284           0 :   aResult = s;
     285           0 :   return true;
     286             : }
     287             : 
     288           0 : static bool ParseCommaSeparator(nsDependentSubstring& aString)
     289             : {
     290           0 :   if (aString.Length() > 1 && aString[0] == ',') {
     291           0 :     aString.Rebind(aString, 1);
     292           0 :     return true;
     293             :   }
     294             : 
     295           0 :   return false;
     296             : }
     297             : 
     298           0 : bool nsMediaFragmentURIParser::ParseXYWH(nsDependentSubstring aString)
     299             : {
     300             :   int32_t x, y, w, h;
     301             :   ClipUnit clipUnit;
     302             : 
     303             :   // Determine units.
     304           0 :   if (StringBeginsWith(aString, NS_LITERAL_STRING("pixel:"))) {
     305           0 :     clipUnit = eClipUnit_Pixel;
     306           0 :     aString.Rebind(aString, 6);
     307           0 :   } else if (StringBeginsWith(aString, NS_LITERAL_STRING("percent:"))) {
     308           0 :     clipUnit = eClipUnit_Percent;
     309           0 :     aString.Rebind(aString, 8);
     310             :   } else {
     311           0 :     clipUnit = eClipUnit_Pixel;
     312             :   }
     313             : 
     314             :   // Read and validate coordinates.
     315           0 :   if (ParseInteger(aString, x) && x >= 0 &&
     316           0 :       ParseCommaSeparator(aString)       &&
     317           0 :       ParseInteger(aString, y) && y >= 0 &&
     318           0 :       ParseCommaSeparator(aString)       &&
     319           0 :       ParseInteger(aString, w) && w > 0  &&
     320           0 :       ParseCommaSeparator(aString)       &&
     321           0 :       ParseInteger(aString, h) && h > 0  &&
     322           0 :       aString.Length() == 0) {
     323             : 
     324             :     // Reject invalid percentage coordinates.
     325           0 :     if (clipUnit == eClipUnit_Percent &&
     326           0 :         (x + w > 100 || y + h > 100)) {
     327           0 :       return false;
     328             :     }
     329             : 
     330           0 :     mClip.emplace(x, y, w, h);
     331           0 :     mClipUnit = clipUnit;
     332           0 :     return true;
     333             :   }
     334             : 
     335           0 :   return false;
     336             : }
     337             : 
     338           0 : void nsMediaFragmentURIParser::Parse(nsACString& aRef)
     339             : {
     340             :   // Create an array of possibly-invalid media fragments.
     341           0 :   nsTArray< std::pair<nsCString, nsCString> > fragments;
     342           0 :   nsCCharSeparatedTokenizer tokenizer(aRef, '&');
     343             : 
     344           0 :   while (tokenizer.hasMoreTokens()) {
     345           0 :     const nsACString& nv = tokenizer.nextToken();
     346           0 :     int32_t index = nv.FindChar('=');
     347           0 :     if (index >= 0) {
     348           0 :       nsAutoCString name;
     349           0 :       nsAutoCString value;
     350           0 :       NS_UnescapeURL(StringHead(nv, index), esc_Ref | esc_AlwaysCopy, name);
     351           0 :       NS_UnescapeURL(Substring(nv, index + 1, nv.Length()),
     352           0 :                      esc_Ref | esc_AlwaysCopy, value);
     353           0 :       fragments.AppendElement(make_pair(name, value));
     354             :     }
     355             :   }
     356             : 
     357             :   // Parse the media fragment values.
     358           0 :   bool gotTemporal = false, gotSpatial = false;
     359           0 :   for (int i = fragments.Length() - 1 ; i >= 0 ; --i) {
     360           0 :     if (gotTemporal && gotSpatial) {
     361             :       // We've got one of each possible type. No need to look at the rest.
     362             :       break;
     363           0 :     } else if (!gotTemporal && fragments[i].first.EqualsLiteral("t")) {
     364           0 :       nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second);
     365           0 :       gotTemporal = ParseNPT(nsDependentSubstring(value, 0));
     366           0 :     } else if (!gotSpatial && fragments[i].first.EqualsLiteral("xywh")) {
     367           0 :       nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second);
     368           0 :       gotSpatial = ParseXYWH(nsDependentSubstring(value, 0));
     369             :     }
     370             :   }
     371           0 : }
     372             : 
     373             : } // namespace net
     374             : } // namespace mozilla

Generated by: LCOV version 1.13