void nsMediaFragmentURIParser::Parse(nsACString& aRef)
{
  // Create an array of possibly-invalid media fragments.
  nsTArray< std::pair<nsCString, nsCString> > fragments;
  nsCCharSeparatedTokenizer tokenizer(aRef, '&');

  while (tokenizer.hasMoreTokens()) {
    const nsCSubstring& nv = tokenizer.nextToken();
    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;
    } else 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));
    }
  }
}
double nsMediaFragmentURIParser::GetEndTime()
{
  for (PRUint32 i = 0; i < mFragments.Length(); ++i) {
    PRUint32 index = mFragments.Length() - i - 1;
    if (mFragments[index].mName.EqualsLiteral("t")) {
      double start = -1;
      double end = -1;
      nsDependentSubstring s(mFragments[index].mValue, 0);
      if (ParseNPT(s, start, end)) {
        return end;
      }
    }
  }
  return -1;
}