tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 1a8092d3eeea75e280e43fcf077a14996c6511c5
parent 888ad507a9896365dfc6148663e6329ac8b63b4e
Author: longsonr <longsonr@gmail.com>
Date:   Wed, 19 Nov 2025 13:51:33 +0000

Bug 1999989 Part 1 - Rename, move and export MediaFragmentURIParser r=emilio,necko-reviewers,media-playback-reviewers,karlt,valentin

Differential Revision: https://phabricator.services.mozilla.com/D272471

Diffstat:
Adom/media/MediaFragmentURIParser.cpp | 353+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adom/media/MediaFragmentURIParser.h | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdom/media/mediaelement/HTMLMediaElement.cpp | 5++---
Mdom/media/mediaelement/moz.build | 1-
Mdom/media/moz.build | 12++++++++++++
Mimage/ImageFactory.cpp | 2+-
Mnetwerk/base/moz.build | 3---
Dnetwerk/base/nsMediaFragmentURIParser.cpp | 354-------------------------------------------------------------------------------
Dnetwerk/base/nsMediaFragmentURIParser.h | 99-------------------------------------------------------------------------------
9 files changed, 465 insertions(+), 461 deletions(-)

diff --git a/dom/media/MediaFragmentURIParser.cpp b/dom/media/MediaFragmentURIParser.cpp @@ -0,0 +1,353 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MediaFragmentURIParser.h" + +#include <utility> + +#include "nsCharSeparatedTokenizer.h" +#include "nsEscape.h" +#include "nsIURI.h" +#include "nsTArray.h" + +using std::make_pair; +using std::pair; + +namespace mozilla { + +MediaFragmentURIParser::MediaFragmentURIParser(nsIURI* aURI) + : mClipUnit(eClipUnit_Pixel) { + nsAutoCString ref; + aURI->GetRef(ref); + Parse(ref); +} + +MediaFragmentURIParser::MediaFragmentURIParser(nsCString& aRef) + : mClipUnit(eClipUnit_Pixel) { + Parse(aRef); +} + +bool MediaFragmentURIParser::ParseNPT(nsDependentSubstring aString) { + nsDependentSubstring original(aString); + if (aString.Length() > 4 && aString[0] == 'n' && aString[1] == 'p' && + aString[2] == 't' && aString[3] == ':') { + aString.Rebind(aString, 4); + } + + if (aString.Length() == 0) { + return false; + } + + double start = -1.0; + double end = -1.0; + + ParseNPTTime(aString, start); + + if (aString.Length() == 0) { + mStart.emplace(start); + return true; + } + + if (aString[0] != ',') { + aString.Rebind(original, 0); + return false; + } + + aString.Rebind(aString, 1); + + if (aString.Length() == 0) { + aString.Rebind(original, 0); + return false; + } + + ParseNPTTime(aString, end); + + if (end <= start || aString.Length() != 0) { + aString.Rebind(original, 0); + return false; + } + + mStart.emplace(start); + mEnd.emplace(end); + return true; +} + +bool MediaFragmentURIParser::ParseNPTTime(nsDependentSubstring& aString, + double& aTime) { + if (aString.Length() == 0) { + return false; + } + + return ParseNPTHHMMSS(aString, aTime) || ParseNPTMMSS(aString, aTime) || + ParseNPTSec(aString, aTime); +} + +// Return true if the given character is a numeric character +static bool IsDigit(nsDependentSubstring::char_type aChar) { + return (aChar >= '0' && aChar <= '9'); +} + +// Return the index of the first character in the string that is not +// a numerical digit, starting from 'aStart'. +static uint32_t FirstNonDigit(nsDependentSubstring& aString, uint32_t aStart) { + while (aStart < aString.Length() && IsDigit(aString[aStart])) { + ++aStart; + } + return aStart; +} + +bool MediaFragmentURIParser::ParseNPTSec(nsDependentSubstring& aString, + double& aSec) { + nsDependentSubstring original(aString); + if (aString.Length() == 0) { + return false; + } + + uint32_t index = FirstNonDigit(aString, 0); + if (index == 0) { + return false; + } + + nsDependentSubstring n(aString, 0, index); + nsresult ec; + int32_t s = n.ToInteger(&ec); + if (NS_FAILED(ec)) { + return false; + } + + aString.Rebind(aString, index); + double fraction = 0.0; + if (!ParseNPTFraction(aString, fraction)) { + aString.Rebind(original, 0); + return false; + } + + aSec = s + fraction; + return true; +} + +bool MediaFragmentURIParser::ParseNPTMMSS(nsDependentSubstring& aString, + double& aTime) { + nsDependentSubstring original(aString); + uint32_t mm = 0; + uint32_t ss = 0; + double fraction = 0.0; + if (!ParseNPTMM(aString, mm)) { + aString.Rebind(original, 0); + return false; + } + + if (aString.Length() < 2 || aString[0] != ':') { + aString.Rebind(original, 0); + return false; + } + + aString.Rebind(aString, 1); + if (!ParseNPTSS(aString, ss)) { + aString.Rebind(original, 0); + return false; + } + + if (!ParseNPTFraction(aString, fraction)) { + aString.Rebind(original, 0); + return false; + } + aTime = mm * 60 + ss + fraction; + return true; +} + +bool MediaFragmentURIParser::ParseNPTFraction(nsDependentSubstring& aString, + double& aFraction) { + double fraction = 0.0; + + if (aString.Length() > 0 && aString[0] == '.') { + uint32_t index = FirstNonDigit(aString, 1); + + if (index > 1) { + nsDependentSubstring number(aString, 0, index); + nsresult ec; + fraction = PromiseFlatString(number).ToDouble(&ec); + if (NS_FAILED(ec)) { + return false; + } + } + aString.Rebind(aString, index); + } + + aFraction = fraction; + return true; +} + +bool MediaFragmentURIParser::ParseNPTHHMMSS(nsDependentSubstring& aString, + double& aTime) { + nsDependentSubstring original(aString); + uint32_t hh = 0; + double seconds = 0.0; + if (!ParseNPTHH(aString, hh)) { + return false; + } + + if (aString.Length() < 2 || aString[0] != ':') { + aString.Rebind(original, 0); + return false; + } + + aString.Rebind(aString, 1); + if (!ParseNPTMMSS(aString, seconds)) { + aString.Rebind(original, 0); + return false; + } + + aTime = hh * 3600 + seconds; + return true; +} + +bool MediaFragmentURIParser::ParseNPTHH(nsDependentSubstring& aString, + uint32_t& aHour) { + if (aString.Length() == 0) { + return false; + } + + uint32_t index = FirstNonDigit(aString, 0); + if (index == 0) { + return false; + } + + nsDependentSubstring n(aString, 0, index); + nsresult ec; + int32_t u = n.ToInteger(&ec); + if (NS_FAILED(ec)) { + return false; + } + + aString.Rebind(aString, index); + aHour = u; + return true; +} + +bool MediaFragmentURIParser::ParseNPTMM(nsDependentSubstring& aString, + uint32_t& aMinute) { + return ParseNPTSS(aString, aMinute); +} + +bool MediaFragmentURIParser::ParseNPTSS(nsDependentSubstring& aString, + uint32_t& aSecond) { + if (aString.Length() < 2) { + return false; + } + + if (IsDigit(aString[0]) && IsDigit(aString[1])) { + nsDependentSubstring n(aString, 0, 2); + nsresult ec; + int32_t u = n.ToInteger(&ec); + if (NS_FAILED(ec)) { + return false; + } + + aString.Rebind(aString, 2); + if (u >= 60) return false; + + aSecond = u; + return true; + } + + return false; +} + +static bool ParseInteger(nsDependentSubstring& aString, int32_t& aResult) { + uint32_t index = FirstNonDigit(aString, 0); + if (index == 0) { + return false; + } + + nsDependentSubstring n(aString, 0, index); + nsresult ec; + int32_t s = n.ToInteger(&ec); + if (NS_FAILED(ec)) { + return false; + } + + aString.Rebind(aString, index); + aResult = s; + return true; +} + +static bool ParseCommaSeparator(nsDependentSubstring& aString) { + if (aString.Length() > 1 && aString[0] == ',') { + aString.Rebind(aString, 1); + return true; + } + + return false; +} + +bool MediaFragmentURIParser::ParseXYWH(nsDependentSubstring aString) { + int32_t x, y, w, h; + ClipUnit clipUnit; + + // Determine units. + if (StringBeginsWith(aString, u"pixel:"_ns)) { + clipUnit = eClipUnit_Pixel; + aString.Rebind(aString, 6); + } else if (StringBeginsWith(aString, u"percent:"_ns)) { + clipUnit = eClipUnit_Percent; + aString.Rebind(aString, 8); + } else { + clipUnit = eClipUnit_Pixel; + } + + // Read and validate coordinates. + if (ParseInteger(aString, x) && x >= 0 && ParseCommaSeparator(aString) && + ParseInteger(aString, y) && y >= 0 && ParseCommaSeparator(aString) && + ParseInteger(aString, w) && w > 0 && ParseCommaSeparator(aString) && + ParseInteger(aString, h) && h > 0 && aString.Length() == 0) { + // Reject invalid percentage coordinates. + if (clipUnit == eClipUnit_Percent && (x + w > 100 || y + h > 100)) { + return false; + } + + mClip.emplace(x, y, w, h); + mClipUnit = clipUnit; + return true; + } + + return false; +} + +void MediaFragmentURIParser::Parse(nsACString& aRef) { + // Create an array of possibly-invalid media fragments. + nsTArray<std::pair<nsCString, nsCString> > fragments; + + for (const nsACString& nv : nsCCharSeparatedTokenizer(aRef, '&').ToRange()) { + int32_t index = nv.FindChar('='); + if (index >= 0) { + nsAutoCString name; + nsAutoCString value; + NS_UnescapeURL(StringHead(nv, index), esc_Ref | esc_AlwaysCopy, name); + NS_UnescapeURL(Substring(nv, index + 1, nv.Length()), + esc_Ref | esc_AlwaysCopy, value); + fragments.AppendElement(make_pair(name, value)); + } + } + + // Parse the media fragment values. + bool gotTemporal = false, gotSpatial = false; + for (int i = fragments.Length() - 1; i >= 0; --i) { + if (gotTemporal && gotSpatial) { + // We've got one of each possible type. No need to look at the rest. + break; + } + if (!gotTemporal && fragments[i].first.EqualsLiteral("t")) { + nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second); + gotTemporal = ParseNPT(nsDependentSubstring(value, 0)); + } else if (!gotSpatial && fragments[i].first.EqualsLiteral("xywh")) { + nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second); + gotSpatial = ParseXYWH(nsDependentSubstring(value, 0)); + } + } +} + +} // namespace mozilla diff --git a/dom/media/MediaFragmentURIParser.h b/dom/media/MediaFragmentURIParser.h @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#if !defined(MediaFragmentURIParser_h__) +# define MediaFragmentURIParser_h__ + +# include "mozilla/Maybe.h" +# include "nsRect.h" +# include "nsStringFwd.h" + +class nsIURI; + +// Class to handle parsing of a W3C media fragment URI as per +// spec at: http://www.w3.org/TR/media-frags/ +// Only the temporaral URI portion of the spec is implemented. +// To use: +// a) Construct an instance with the URI containing the fragment +// b) Check for the validity of the values you are interested in +// using e.g. HasStartTime(). +// c) If the values are valid, obtain them using e.g. GetStartTime(). + +namespace mozilla { + +enum ClipUnit { + eClipUnit_Pixel, + eClipUnit_Percent, +}; + +class MediaFragmentURIParser { + public: + // Create a parser with the provided URI. + explicit MediaFragmentURIParser(nsIURI* aURI); + + // Create a parser with the provided URI reference portion. + explicit MediaFragmentURIParser(nsCString& aRef); + + // True if a valid temporal media fragment indicated a start time. + bool HasStartTime() const { return mStart.isSome(); } + + // If a valid temporal media fragment indicated a start time, returns + // it in units of seconds. If not, defaults to 0. + double GetStartTime() const { return *mStart; } + + // True if a valid temporal media fragment indicated an end time. + bool HasEndTime() const { return mEnd.isSome(); } + + // If a valid temporal media fragment indicated an end time, returns + // it in units of seconds. If not, defaults to -1. + double GetEndTime() const { return *mEnd; } + + // True if a valid spatial media fragment indicated a clipping region. + bool HasClip() const { return mClip.isSome(); } + + // If a valid spatial media fragment indicated a clipping region, + // returns the region. If not, returns an empty region. The unit + // used depends on the value returned by GetClipUnit(). + nsIntRect GetClip() const { return *mClip; } + + // If a valid spatial media fragment indicated a clipping region, + // returns the unit used. + ClipUnit GetClipUnit() const { return mClipUnit; } + + private: + // Parse the URI ref provided, looking for media fragments. This is + // the top-level parser the invokes the others below. + void Parse(nsACString& aRef); + + // The following methods parse the fragment as per the media + // fragments specification. 'aString' contains the remaining + // fragment data to be parsed. The method returns true + // if the parse was successful and leaves the remaining unparsed + // data in 'aString'. If the parse fails then false is returned + // and 'aString' is left as it was when called. + bool ParseNPT(nsDependentSubstring aString); + bool ParseNPTTime(nsDependentSubstring& aString, double& aTime); + bool ParseNPTSec(nsDependentSubstring& aString, double& aSec); + bool ParseNPTFraction(nsDependentSubstring& aString, double& aFraction); + bool ParseNPTMMSS(nsDependentSubstring& aString, double& aTime); + bool ParseNPTHHMMSS(nsDependentSubstring& aString, double& aTime); + bool ParseNPTHH(nsDependentSubstring& aString, uint32_t& aHour); + bool ParseNPTMM(nsDependentSubstring& aString, uint32_t& aMinute); + bool ParseNPTSS(nsDependentSubstring& aString, uint32_t& aSecond); + bool ParseXYWH(nsDependentSubstring aString); + bool ParseMozResolution(nsDependentSubstring aString); + + // Media fragment information. + Maybe<double> mStart; + Maybe<double> mEnd; + Maybe<nsIntRect> mClip; + ClipUnit mClipUnit; +}; + +} // namespace mozilla + +#endif diff --git a/dom/media/mediaelement/HTMLMediaElement.cpp b/dom/media/mediaelement/HTMLMediaElement.cpp @@ -59,6 +59,7 @@ #include "mozilla/EMEUtils.h" #include "mozilla/EventDispatcher.h" #include "mozilla/MathAlgorithms.h" +#include "mozilla/MediaFragmentURIParser.h" #include "mozilla/Preferences.h" #include "mozilla/PresShell.h" #include "mozilla/SVGObserverUtils.h" @@ -123,7 +124,6 @@ #include "nsITimer.h" #include "nsJSUtils.h" #include "nsLayoutUtils.h" -#include "nsMediaFragmentURIParser.h" #include "nsMimeTypes.h" #include "nsNetUtil.h" #include "nsNodeInfoManager.h" @@ -161,7 +161,6 @@ extern mozilla::LazyLogModule gAutoplayPermissionLog; #define LOG_EVENT(type, msg) MOZ_LOG(gMediaElementEventsLog, type, msg) using namespace mozilla::layers; -using mozilla::net::nsMediaFragmentURIParser; using namespace mozilla::dom::HTMLMediaElement_Binding; namespace mozilla::dom { @@ -5833,7 +5832,7 @@ void HTMLMediaElement::ProcessMediaFragmentURI() { mFragmentStart = mFragmentEnd = -1.0; return; } - nsMediaFragmentURIParser parser(mLoadingSrc); + MediaFragmentURIParser parser(mLoadingSrc); if (mDecoder && parser.HasEndTime()) { mFragmentEnd = parser.GetEndTime(); diff --git a/dom/media/mediaelement/moz.build b/dom/media/mediaelement/moz.build @@ -33,7 +33,6 @@ include("/ipc/chromium/chromium-config.mozbuild") LOCAL_INCLUDES += [ "/dom/base", "/dom/media", - "/netwerk/base", "/third_party/abseil-cpp", "/third_party/libwebrtc", ] diff --git a/dom/media/moz.build b/dom/media/moz.build @@ -82,6 +82,17 @@ if CONFIG["MOZ_WEBRTC_SIGNALING"]: if CONFIG["FUZZING_INTERFACES"]: TEST_DIRS += ["webrtc/tests/fuzztests"] +if CONFIG["FUZZING_INTERFACES"] and CONFIG["LIBFUZZER"]: + include("/tools/fuzzing/libfuzzer-flags.mozbuild") + SOURCES += [ + "MediaFragmentURIParser.cpp", + ] + SOURCES["MediaFragmentURIParser.cpp"].flags += libfuzzer_flags +else: + UNIFIED_SOURCES += [ + "MediaFragmentURIParser.cpp", + ] + MOCHITEST_MANIFESTS += [ "test/mochitest.toml", "test/mochitest_background_video.toml", @@ -213,6 +224,7 @@ EXPORTS += [ ] EXPORTS.mozilla += [ + "MediaFragmentURIParser.h", "MediaManager.h", "UnderrunHandler.h", ] diff --git a/image/ImageFactory.cpp b/image/ImageFactory.cpp @@ -19,7 +19,7 @@ #include "RasterImage.h" #include "VectorImage.h" #include "Image.h" -#include "nsMediaFragmentURIParser.h" +#include "mozilla/MediaFragmentURIParser.h" #include "nsContentUtils.h" #include "mozilla/SchedulerGroup.h" diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build @@ -267,16 +267,13 @@ if CONFIG["FUZZING"]: if CONFIG["FUZZING_INTERFACES"] and CONFIG["LIBFUZZER"]: include("/tools/fuzzing/libfuzzer-flags.mozbuild") SOURCES += [ - "nsMediaFragmentURIParser.cpp", "nsURLHelper.cpp", "nsURLParsers.cpp", ] - SOURCES["nsMediaFragmentURIParser.cpp"].flags += libfuzzer_flags SOURCES["nsURLHelper.cpp"].flags += libfuzzer_flags SOURCES["nsURLParsers.cpp"].flags += libfuzzer_flags else: UNIFIED_SOURCES += [ - "nsMediaFragmentURIParser.cpp", "nsURLHelper.cpp", "nsURLParsers.cpp", ] diff --git a/netwerk/base/nsMediaFragmentURIParser.cpp b/netwerk/base/nsMediaFragmentURIParser.cpp @@ -1,354 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsTArray.h" -#include "nsCharSeparatedTokenizer.h" -#include "nsEscape.h" -#include "nsIURI.h" -#include <utility> - -#include "nsMediaFragmentURIParser.h" - -using std::make_pair; -using std::pair; - -namespace mozilla { -namespace net { - -nsMediaFragmentURIParser::nsMediaFragmentURIParser(nsIURI* aURI) - : mClipUnit(eClipUnit_Pixel) { - nsAutoCString ref; - aURI->GetRef(ref); - Parse(ref); -} - -nsMediaFragmentURIParser::nsMediaFragmentURIParser(nsCString& aRef) - : mClipUnit(eClipUnit_Pixel) { - Parse(aRef); -} - -bool nsMediaFragmentURIParser::ParseNPT(nsDependentSubstring aString) { - nsDependentSubstring original(aString); - if (aString.Length() > 4 && aString[0] == 'n' && aString[1] == 'p' && - aString[2] == 't' && aString[3] == ':') { - aString.Rebind(aString, 4); - } - - if (aString.Length() == 0) { - return false; - } - - double start = -1.0; - double end = -1.0; - - ParseNPTTime(aString, start); - - if (aString.Length() == 0) { - mStart.emplace(start); - return true; - } - - if (aString[0] != ',') { - aString.Rebind(original, 0); - return false; - } - - aString.Rebind(aString, 1); - - if (aString.Length() == 0) { - aString.Rebind(original, 0); - return false; - } - - ParseNPTTime(aString, end); - - if (end <= start || aString.Length() != 0) { - aString.Rebind(original, 0); - return false; - } - - mStart.emplace(start); - mEnd.emplace(end); - return true; -} - -bool nsMediaFragmentURIParser::ParseNPTTime(nsDependentSubstring& aString, - double& aTime) { - if (aString.Length() == 0) { - return false; - } - - return ParseNPTHHMMSS(aString, aTime) || ParseNPTMMSS(aString, aTime) || - ParseNPTSec(aString, aTime); -} - -// Return true if the given character is a numeric character -static bool IsDigit(nsDependentSubstring::char_type aChar) { - return (aChar >= '0' && aChar <= '9'); -} - -// Return the index of the first character in the string that is not -// a numerical digit, starting from 'aStart'. -static uint32_t FirstNonDigit(nsDependentSubstring& aString, uint32_t aStart) { - while (aStart < aString.Length() && IsDigit(aString[aStart])) { - ++aStart; - } - return aStart; -} - -bool nsMediaFragmentURIParser::ParseNPTSec(nsDependentSubstring& aString, - double& aSec) { - nsDependentSubstring original(aString); - if (aString.Length() == 0) { - return false; - } - - uint32_t index = FirstNonDigit(aString, 0); - if (index == 0) { - return false; - } - - nsDependentSubstring n(aString, 0, index); - nsresult ec; - int32_t s = n.ToInteger(&ec); - if (NS_FAILED(ec)) { - return false; - } - - aString.Rebind(aString, index); - double fraction = 0.0; - if (!ParseNPTFraction(aString, fraction)) { - aString.Rebind(original, 0); - return false; - } - - aSec = s + fraction; - return true; -} - -bool nsMediaFragmentURIParser::ParseNPTMMSS(nsDependentSubstring& aString, - double& aTime) { - nsDependentSubstring original(aString); - uint32_t mm = 0; - uint32_t ss = 0; - double fraction = 0.0; - if (!ParseNPTMM(aString, mm)) { - aString.Rebind(original, 0); - return false; - } - - if (aString.Length() < 2 || aString[0] != ':') { - aString.Rebind(original, 0); - return false; - } - - aString.Rebind(aString, 1); - if (!ParseNPTSS(aString, ss)) { - aString.Rebind(original, 0); - return false; - } - - if (!ParseNPTFraction(aString, fraction)) { - aString.Rebind(original, 0); - return false; - } - aTime = mm * 60 + ss + fraction; - return true; -} - -bool nsMediaFragmentURIParser::ParseNPTFraction(nsDependentSubstring& aString, - double& aFraction) { - double fraction = 0.0; - - if (aString.Length() > 0 && aString[0] == '.') { - uint32_t index = FirstNonDigit(aString, 1); - - if (index > 1) { - nsDependentSubstring number(aString, 0, index); - nsresult ec; - fraction = PromiseFlatString(number).ToDouble(&ec); - if (NS_FAILED(ec)) { - return false; - } - } - aString.Rebind(aString, index); - } - - aFraction = fraction; - return true; -} - -bool nsMediaFragmentURIParser::ParseNPTHHMMSS(nsDependentSubstring& aString, - double& aTime) { - nsDependentSubstring original(aString); - uint32_t hh = 0; - double seconds = 0.0; - if (!ParseNPTHH(aString, hh)) { - return false; - } - - if (aString.Length() < 2 || aString[0] != ':') { - aString.Rebind(original, 0); - return false; - } - - aString.Rebind(aString, 1); - if (!ParseNPTMMSS(aString, seconds)) { - aString.Rebind(original, 0); - return false; - } - - aTime = hh * 3600 + seconds; - return true; -} - -bool nsMediaFragmentURIParser::ParseNPTHH(nsDependentSubstring& aString, - uint32_t& aHour) { - if (aString.Length() == 0) { - return false; - } - - uint32_t index = FirstNonDigit(aString, 0); - if (index == 0) { - return false; - } - - nsDependentSubstring n(aString, 0, index); - nsresult ec; - int32_t u = n.ToInteger(&ec); - if (NS_FAILED(ec)) { - return false; - } - - aString.Rebind(aString, index); - aHour = u; - return true; -} - -bool nsMediaFragmentURIParser::ParseNPTMM(nsDependentSubstring& aString, - uint32_t& aMinute) { - return ParseNPTSS(aString, aMinute); -} - -bool nsMediaFragmentURIParser::ParseNPTSS(nsDependentSubstring& aString, - uint32_t& aSecond) { - if (aString.Length() < 2) { - return false; - } - - if (IsDigit(aString[0]) && IsDigit(aString[1])) { - nsDependentSubstring n(aString, 0, 2); - nsresult ec; - int32_t u = n.ToInteger(&ec); - if (NS_FAILED(ec)) { - return false; - } - - aString.Rebind(aString, 2); - if (u >= 60) return false; - - aSecond = u; - return true; - } - - return false; -} - -static bool ParseInteger(nsDependentSubstring& aString, int32_t& aResult) { - uint32_t index = FirstNonDigit(aString, 0); - if (index == 0) { - return false; - } - - nsDependentSubstring n(aString, 0, index); - nsresult ec; - int32_t s = n.ToInteger(&ec); - if (NS_FAILED(ec)) { - return false; - } - - aString.Rebind(aString, index); - aResult = s; - return true; -} - -static bool ParseCommaSeparator(nsDependentSubstring& aString) { - if (aString.Length() > 1 && aString[0] == ',') { - aString.Rebind(aString, 1); - return true; - } - - return false; -} - -bool nsMediaFragmentURIParser::ParseXYWH(nsDependentSubstring aString) { - int32_t x, y, w, h; - ClipUnit clipUnit; - - // Determine units. - if (StringBeginsWith(aString, u"pixel:"_ns)) { - clipUnit = eClipUnit_Pixel; - aString.Rebind(aString, 6); - } else if (StringBeginsWith(aString, u"percent:"_ns)) { - clipUnit = eClipUnit_Percent; - aString.Rebind(aString, 8); - } else { - clipUnit = eClipUnit_Pixel; - } - - // Read and validate coordinates. - if (ParseInteger(aString, x) && x >= 0 && ParseCommaSeparator(aString) && - ParseInteger(aString, y) && y >= 0 && ParseCommaSeparator(aString) && - ParseInteger(aString, w) && w > 0 && ParseCommaSeparator(aString) && - ParseInteger(aString, h) && h > 0 && aString.Length() == 0) { - // Reject invalid percentage coordinates. - if (clipUnit == eClipUnit_Percent && (x + w > 100 || y + h > 100)) { - return false; - } - - mClip.emplace(x, y, w, h); - mClipUnit = clipUnit; - return true; - } - - return false; -} - -void nsMediaFragmentURIParser::Parse(nsACString& aRef) { - // Create an array of possibly-invalid media fragments. - nsTArray<std::pair<nsCString, nsCString> > fragments; - - for (const nsACString& nv : nsCCharSeparatedTokenizer(aRef, '&').ToRange()) { - int32_t index = nv.FindChar('='); - if (index >= 0) { - nsAutoCString name; - nsAutoCString value; - NS_UnescapeURL(StringHead(nv, index), esc_Ref | esc_AlwaysCopy, name); - NS_UnescapeURL(Substring(nv, index + 1, nv.Length()), - esc_Ref | esc_AlwaysCopy, value); - fragments.AppendElement(make_pair(name, value)); - } - } - - // Parse the media fragment values. - bool gotTemporal = false, gotSpatial = false; - for (int i = fragments.Length() - 1; i >= 0; --i) { - if (gotTemporal && gotSpatial) { - // We've got one of each possible type. No need to look at the rest. - break; - } - if (!gotTemporal && fragments[i].first.EqualsLiteral("t")) { - nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second); - gotTemporal = ParseNPT(nsDependentSubstring(value, 0)); - } else if (!gotSpatial && fragments[i].first.EqualsLiteral("xywh")) { - nsAutoString value = NS_ConvertUTF8toUTF16(fragments[i].second); - gotSpatial = ParseXYWH(nsDependentSubstring(value, 0)); - } - } -} - -} // namespace net -} // namespace mozilla diff --git a/netwerk/base/nsMediaFragmentURIParser.h b/netwerk/base/nsMediaFragmentURIParser.h @@ -1,99 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(nsMediaFragmentURIParser_h__) -# define nsMediaFragmentURIParser_h__ - -# include "mozilla/Maybe.h" -# include "nsStringFwd.h" -# include "nsRect.h" - -class nsIURI; - -// Class to handle parsing of a W3C media fragment URI as per -// spec at: http://www.w3.org/TR/media-frags/ -// Only the temporaral URI portion of the spec is implemented. -// To use: -// a) Construct an instance with the URI containing the fragment -// b) Check for the validity of the values you are interested in -// using e.g. HasStartTime(). -// c) If the values are valid, obtain them using e.g. GetStartTime(). - -namespace mozilla { -namespace net { - -enum ClipUnit { - eClipUnit_Pixel, - eClipUnit_Percent, -}; - -class nsMediaFragmentURIParser { - public: - // Create a parser with the provided URI. - explicit nsMediaFragmentURIParser(nsIURI* aURI); - - // Create a parser with the provided URI reference portion. - explicit nsMediaFragmentURIParser(nsCString& aRef); - - // True if a valid temporal media fragment indicated a start time. - bool HasStartTime() const { return mStart.isSome(); } - - // If a valid temporal media fragment indicated a start time, returns - // it in units of seconds. If not, defaults to 0. - double GetStartTime() const { return *mStart; } - - // True if a valid temporal media fragment indicated an end time. - bool HasEndTime() const { return mEnd.isSome(); } - - // If a valid temporal media fragment indicated an end time, returns - // it in units of seconds. If not, defaults to -1. - double GetEndTime() const { return *mEnd; } - - // True if a valid spatial media fragment indicated a clipping region. - bool HasClip() const { return mClip.isSome(); } - - // If a valid spatial media fragment indicated a clipping region, - // returns the region. If not, returns an empty region. The unit - // used depends on the value returned by GetClipUnit(). - nsIntRect GetClip() const { return *mClip; } - - // If a valid spatial media fragment indicated a clipping region, - // returns the unit used. - ClipUnit GetClipUnit() const { return mClipUnit; } - - private: - // Parse the URI ref provided, looking for media fragments. This is - // the top-level parser the invokes the others below. - void Parse(nsACString& aRef); - - // The following methods parse the fragment as per the media - // fragments specification. 'aString' contains the remaining - // fragment data to be parsed. The method returns true - // if the parse was successful and leaves the remaining unparsed - // data in 'aString'. If the parse fails then false is returned - // and 'aString' is left as it was when called. - bool ParseNPT(nsDependentSubstring aString); - bool ParseNPTTime(nsDependentSubstring& aString, double& aTime); - bool ParseNPTSec(nsDependentSubstring& aString, double& aSec); - bool ParseNPTFraction(nsDependentSubstring& aString, double& aFraction); - bool ParseNPTMMSS(nsDependentSubstring& aString, double& aTime); - bool ParseNPTHHMMSS(nsDependentSubstring& aString, double& aTime); - bool ParseNPTHH(nsDependentSubstring& aString, uint32_t& aHour); - bool ParseNPTMM(nsDependentSubstring& aString, uint32_t& aMinute); - bool ParseNPTSS(nsDependentSubstring& aString, uint32_t& aSecond); - bool ParseXYWH(nsDependentSubstring aString); - bool ParseMozResolution(nsDependentSubstring aString); - - // Media fragment information. - Maybe<double> mStart; - Maybe<double> mEnd; - Maybe<nsIntRect> mClip; - ClipUnit mClipUnit; -}; - -} // namespace net -} // namespace mozilla - -#endif