Bug 1431204 - Change calls to nsIURI.spec setter to use nsIURIMutator instead r=mayhemer

* changes call to use nsIURIMutator.setSpec()
* Add new NS_MutateURI constructor that takes new Mutator object
* Make nsSimpleNestedURI::Mutate() and nsNestedAboutURI::Mutate() return mutable URIs
* Make the finalizers for nsSimpleNestedURI and nsNestedAboutURI make the returned URIs immutable

MozReview-Commit-ID: 1kcv6zMxnv7

--HG--
extra : rebase_source : 99b13e9dbc8eaaa9615843b05e1539e19b527504
This commit is contained in:
Valentin Gosu 2018-01-19 15:19:42 +01:00
parent ea3dd6304c
commit da90b10e9f
17 changed files with 192 additions and 110 deletions

View File

@ -892,18 +892,20 @@ nsHostObjectProtocolHandler::NewURI(const nsACString& aSpec,
DataInfo* info = GetDataInfo(aSpec);
RefPtr<nsHostObjectURI> uri;
if (info && info->mObjectType == DataInfo::eBlobImpl) {
MOZ_ASSERT(info->mBlobImpl);
uri = new nsHostObjectURI(info->mPrincipal, info->mBlobImpl);
} else {
uri = new nsHostObjectURI(nullptr, nullptr);
}
rv = uri->SetSpec(aSpec);
nsCOMPtr<nsIURI> uri;
rv = NS_MutateURI(new nsHostObjectURI::Mutator())
.SetSpec(aSpec)
.Finalize(uri);
NS_ENSURE_SUCCESS(rv, rv);
NS_TryToSetImmutable(uri);
RefPtr<nsHostObjectURI> hostURI = static_cast<nsHostObjectURI*>(uri.get());
if (info && info->mObjectType == DataInfo::eBlobImpl) {
MOZ_ASSERT(info->mBlobImpl);
hostURI->mPrincipal = info->mPrincipal;
hostURI->mBlobImpl = info->mBlobImpl;
}
NS_TryToSetImmutable(hostURI);
uri.forget(aResult);
if (info && info->mObjectType == DataInfo::eBlobImpl) {
@ -1120,21 +1122,23 @@ nsFontTableProtocolHandler::NewURI(const nsACString& aSpec,
nsIURI *aBaseURI,
nsIURI **aResult)
{
RefPtr<nsIURI> uri;
nsresult rv;
nsCOMPtr<nsIURI> uri;
// Either you got here via a ref or a fonttable: uri
if (aSpec.Length() && aSpec.CharAt(0) == '#') {
nsresult rv = aBaseURI->CloneIgnoringRef(getter_AddRefs(uri));
rv = NS_MutateURI(aBaseURI)
.SetRef(aSpec)
.Finalize(uri);
NS_ENSURE_SUCCESS(rv, rv);
uri->SetRef(aSpec);
} else {
// Relative URIs (other than #ref) are not meaningful within the
// fonttable: scheme.
// If aSpec is a relative URI -other- than a bare #ref,
// this will leave uri empty, and we'll return a failure code below.
uri = new mozilla::net::nsSimpleURI();
nsresult rv = uri->SetSpec(aSpec);
rv = NS_MutateURI(new mozilla::net::nsSimpleURI::Mutator())
.SetSpec(aSpec)
.Finalize(uri);
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -1196,20 +1196,22 @@ nsJSProtocolHandler::NewURI(const nsACString &aSpec,
// CreateInstance.
nsCOMPtr<nsIURI> url = new nsJSURI(aBaseURI);
if (!aCharset || !nsCRT::strcasecmp("UTF-8", aCharset))
rv = url->SetSpec(aSpec);
else {
NS_MutateURI mutator(url);
if (!aCharset || !nsCRT::strcasecmp("UTF-8", aCharset)) {
mutator.SetSpec(aSpec);
} else {
nsAutoCString utf8Spec;
rv = EnsureUTF8Spec(PromiseFlatCString(aSpec), aCharset, utf8Spec);
if (NS_SUCCEEDED(rv)) {
if (utf8Spec.IsEmpty())
rv = url->SetSpec(aSpec);
else
rv = url->SetSpec(utf8Spec);
if (utf8Spec.IsEmpty()) {
mutator.SetSpec(aSpec);
} else {
mutator.SetSpec(utf8Spec);
}
}
}
rv = mutator.Finalize(url);
if (NS_FAILED(rv)) {
return rv;
}

View File

@ -630,16 +630,20 @@ URLWorker::Init(const nsAString& aURL, const Optional<nsAString>& aBase,
}
if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) {
RefPtr<nsStandardURL> baseURL;
nsCOMPtr<nsIURI> baseURL;
if (aBase.WasPassed()) {
baseURL = new nsStandardURL();
// XXXcatalinb: SetSpec only writes a warning to the console on urls
// without a valid scheme. I can't fix that because we've come to rely
// on that behaviour in a bunch of different places.
nsresult rv = baseURL->SetSpec(NS_ConvertUTF16toUTF8(aBase.Value()));
nsresult rv = NS_MutateURI(new nsStandardURL::Mutator())
.SetSpec(NS_ConvertUTF16toUTF8(aBase.Value()))
.Finalize(baseURL);
nsAutoCString baseScheme;
baseURL->GetScheme(baseScheme);
if (baseURL) {
baseURL->GetScheme(baseScheme);
}
if (NS_WARN_IF(NS_FAILED(rv)) || baseScheme.IsEmpty()) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aBase.Value());
return;
@ -707,8 +711,11 @@ URLWorker::SetHref(const nsAString& aHref, ErrorResult& aRv)
}
if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) {
mStdURL = new nsStandardURL();
aRv = mStdURL->SetSpec(NS_ConvertUTF16toUTF8(aHref));
nsCOMPtr<nsIURI> uri;
aRv = NS_MutateURI(new nsStandardURL::Mutator())
.SetSpec(NS_ConvertUTF16toUTF8(aHref))
.Finalize(uri);
mStdURL = static_cast<net::nsStandardURL*>(uri.get());
if (mURLProxy) {
mWorkerPrivate->AssertIsOnWorkerThread();

View File

@ -68,14 +68,9 @@ nsIconProtocolHandler::NewURI(const nsACString& aSpec,
nsIURI* aBaseURI,
nsIURI** result)
{
nsCOMPtr<nsIMozIconURI> uri = new nsMozIconURI();
if (!uri) return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = uri->SetSpec(aSpec);
if (NS_FAILED(rv)) return rv;
NS_ADDREF(*result = uri);
return NS_OK;
return NS_MutateURI(new nsMozIconURI::Mutator())
.SetSpec(aSpec)
.Finalize(result);
}
NS_IMETHODIMP

View File

@ -278,6 +278,12 @@ public:
explicit NS_MutateURI(nsIURI* aURI);
explicit NS_MutateURI(const char * aContractID);
explicit NS_MutateURI(nsIURIMutator* m)
{
mStatus = m ? NS_OK : NS_ERROR_NULL_POINTER;
mMutator = m;
}
NS_MutateURI& SetSpec(const nsACString& aSpec)
{
NS_ENSURE_SUCCESS(mStatus, *this);

View File

@ -196,6 +196,9 @@ nsSimpleNestedURI::Mutate(nsIURIMutator** aMutator)
if (NS_FAILED(rv)) {
return rv;
}
// StartClone calls SetMutable(false) but we need the mutator clone
// to be mutable
mutator->ResetMutable();
mutator.forget(aMutator);
return NS_OK;
}

View File

@ -77,13 +77,48 @@ public:
, public BaseURIMutator<nsSimpleNestedURI>
{
NS_DECL_ISUPPORTS
NS_DEFINE_NSIMUTATOR_COMMON
NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
explicit Mutator() { }
private:
virtual ~Mutator() { }
MOZ_MUST_USE NS_IMETHOD
Deserialize(const mozilla::ipc::URIParams& aParams) override
{
return InitFromIPCParams(aParams);
}
MOZ_MUST_USE NS_IMETHOD
Read(nsIObjectInputStream* aStream) override
{
return InitFromInputStream(aStream);
}
MOZ_MUST_USE NS_IMETHOD
Finalize(nsIURI** aURI) override
{
mURI->mMutable = false;
mURI.forget(aURI);
return NS_OK;
}
MOZ_MUST_USE NS_IMETHOD
SetSpec(const nsACString& aSpec, nsIURIMutator** aMutator) override
{
if (aMutator) {
NS_ADDREF(*aMutator = this);
}
return InitFromSpec(aSpec);
}
void ResetMutable()
{
if (mURI) {
mURI->mMutable = true;
}
}
friend class nsSimpleNestedURI;
};
};

View File

@ -113,11 +113,13 @@ nsAboutProtocolHandler::NewURI(const nsACString &aSpec,
*result = nullptr;
nsresult rv;
// Use a simple URI to parse out some stuff first
nsCOMPtr<nsIURI> url = do_CreateInstance(kSimpleURICID, &rv);
if (NS_FAILED(rv)) return rv;
rv = url->SetSpec(aSpec);
// Use a simple URI to parse out some stuff first
nsCOMPtr<nsIURI> url;
rv = NS_MutateURI(new nsSimpleURI::Mutator())
.SetSpec(aSpec)
.Finalize(url);
if (NS_FAILED(rv)) {
return rv;
}
@ -148,13 +150,10 @@ nsAboutProtocolHandler::NewURI(const nsACString &aSpec,
rv = NS_NewURI(getter_AddRefs(inner), spec);
NS_ENSURE_SUCCESS(rv, rv);
nsSimpleNestedURI* outer = new nsNestedAboutURI(inner, aBaseURI);
NS_ENSURE_TRUE(outer, NS_ERROR_OUT_OF_MEMORY);
// Take a ref to it in the COMPtr we plan to return
url = outer;
rv = outer->SetSpec(aSpec);
RefPtr<nsSimpleNestedURI> outer = new nsNestedAboutURI(inner, aBaseURI);
rv = NS_MutateURI(outer)
.SetSpec(aSpec)
.Finalize(url);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -298,21 +297,15 @@ nsSafeAboutProtocolHandler::NewURI(const nsACString &aSpec,
nsIURI *aBaseURI,
nsIURI **result)
{
nsresult rv;
nsCOMPtr<nsIURI> url = do_CreateInstance(kSimpleURICID, &rv);
if (NS_FAILED(rv)) return rv;
rv = url->SetSpec(aSpec);
nsresult rv = NS_MutateURI(new nsSimpleURI::Mutator())
.SetSpec(aSpec)
.Finalize(result);
if (NS_FAILED(rv)) {
return rv;
}
NS_TryToSetImmutable(url);
*result = nullptr;
url.swap(*result);
return rv;
NS_TryToSetImmutable(*result);
return NS_OK;
}
NS_IMETHODIMP
@ -437,6 +430,9 @@ nsNestedAboutURI::Mutate(nsIURIMutator** aMutator)
if (NS_FAILED(rv)) {
return rv;
}
// StartClone calls SetMutable(false) but we need the mutator clone
// to be mutable
mutator->ResetMutable();
mutator.forget(aMutator);
return NS_OK;
}

View File

@ -93,12 +93,47 @@ public:
{
NS_DECL_ISUPPORTS
NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
NS_DEFINE_NSIMUTATOR_COMMON
explicit Mutator() { }
private:
virtual ~Mutator() { }
MOZ_MUST_USE NS_IMETHOD
Deserialize(const mozilla::ipc::URIParams& aParams) override
{
return InitFromIPCParams(aParams);
}
MOZ_MUST_USE NS_IMETHOD
Read(nsIObjectInputStream* aStream) override
{
return InitFromInputStream(aStream);
}
MOZ_MUST_USE NS_IMETHOD
Finalize(nsIURI** aURI) override
{
mURI->mMutable = false;
mURI.forget(aURI);
return NS_OK;
}
MOZ_MUST_USE NS_IMETHOD
SetSpec(const nsACString& aSpec, nsIURIMutator** aMutator) override
{
if (aMutator) {
NS_ADDREF(*aMutator = this);
}
return InitFromSpec(aSpec);
}
void ResetMutable()
{
if (mURI) {
mURI->mMutable = true;
}
}
friend class nsNestedAboutURI;
};
};

View File

@ -9,8 +9,7 @@
#include "nsError.h"
#include "DataChannelChild.h"
#include "plstr.h"
static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
#include "nsSimpleURI.h"
////////////////////////////////////////////////////////////////////////////////
@ -64,7 +63,7 @@ nsDataHandler::NewURI(const nsACString &aSpec,
nsIURI *aBaseURI,
nsIURI **result) {
nsresult rv;
RefPtr<nsIURI> uri;
nsCOMPtr<nsIURI> uri;
nsCString spec(aSpec);
@ -94,10 +93,9 @@ nsDataHandler::NewURI(const nsACString &aSpec,
}
}
uri = do_CreateInstance(kSimpleURICID, &rv);
if (NS_FAILED(rv))
return rv;
rv = uri->SetSpec(spec);
rv = NS_MutateURI(new nsSimpleURI::Mutator())
.SetSpec(spec)
.Finalize(uri);
}
if (NS_FAILED(rv))

View File

@ -75,18 +75,19 @@ nsViewSourceHandler::NewURI(const nsACString &aSpec,
// We can't swap() from an RefPtr<nsSimpleNestedURI> to an nsIURI**,
// sadly.
nsSimpleNestedURI* ourURI = new nsSimpleNestedURI(innerURI);
nsCOMPtr<nsIURI> uri = ourURI;
if (!uri)
return NS_ERROR_OUT_OF_MEMORY;
RefPtr<nsSimpleNestedURI> ourURI = new nsSimpleNestedURI(innerURI);
rv = ourURI->SetSpec(asciiSpec);
if (NS_FAILED(rv))
nsCOMPtr<nsIURI> uri;
rv = NS_MutateURI(ourURI)
.SetSpec(asciiSpec)
.Finalize(uri);
if (NS_FAILED(rv)) {
return rv;
}
// Make the URI immutable so it's impossible to get it out of sync
// with its inner URI.
ourURI->SetMutable(false);
NS_TryToSetImmutable(uri);
uri.swap(*aResult);
return rv;

View File

@ -2,9 +2,7 @@
#include "mozilla/net/HttpAuthUtils.h"
#include "mozilla/Preferences.h"
#include "nsIURL.h"
#include "nsNetCID.h"
#include "nsComponentManagerUtils.h"
#include "nsNetUtil.h"
namespace mozilla {
namespace net {
@ -12,31 +10,29 @@ namespace net {
#define TEST_PREF "network.http_test.auth_utils"
TEST(TestHttpAuthUtils, Bug1351301) {
nsCOMPtr<nsIURL> url( do_CreateInstance(NS_STANDARDURL_CONTRACTID) );
ASSERT_TRUE(url) << "couldn't create URL";
nsCOMPtr<nsIURI> url;
nsAutoCString spec;
ASSERT_EQ(Preferences::SetCString(TEST_PREF, "bar.com"), NS_OK);
spec = "http://bar.com";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(auth::URIMatchesPrefPattern(url,TEST_PREF), true);
spec = "http://foo.bar.com";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(auth::URIMatchesPrefPattern(url,TEST_PREF), true);
spec = "http://foobar.com";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(auth::URIMatchesPrefPattern(url,TEST_PREF), false);
ASSERT_EQ(Preferences::SetCString(TEST_PREF, ".bar.com"), NS_OK);
spec = "http://foo.bar.com";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(auth::URIMatchesPrefPattern(url,TEST_PREF), true);
spec = "http://bar.com";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(auth::URIMatchesPrefPattern(url,TEST_PREF), false);
ASSERT_EQ(Preferences::ClearUser(TEST_PREF), NS_OK);

View File

@ -2,12 +2,12 @@
#include "nsCOMPtr.h"
#include "nsNetCID.h"
#include "nsIURL.h"
#include "nsString.h"
#include "nsComponentManagerUtils.h"
#include "../../base/nsProtocolProxyService.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/Preferences.h"
#include "nsNetUtil.h"
namespace mozilla {
namespace net {
@ -17,68 +17,66 @@ TEST(TestProtocolProxyService, LoadHostFilters) {
ASSERT_TRUE(ps);
mozilla::net::nsProtocolProxyService* pps = static_cast<mozilla::net::nsProtocolProxyService*>(ps.get());
nsCOMPtr<nsIURL> url( do_CreateInstance(NS_STANDARDURL_CONTRACTID) );
ASSERT_TRUE(url) << "couldn't create URL";
nsCOMPtr<nsIURI> url;
nsAutoCString spec;
auto CheckLoopbackURLs = [&](bool expected)
{
// loopback IPs are always filtered
spec = "http://127.0.0.1";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
spec = "http://[::1]";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
};
auto CheckURLs = [&](bool expected)
{
spec = "http://example.com";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
spec = "https://10.2.3.4";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 443), expected);
spec = "http://1.2.3.4";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
spec = "http://1.2.3.4:8080";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
spec = "http://[2001::1]";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
spec = "http://2.3.4.5:7777";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
spec = "http://[abcd::2]:123";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
spec = "http://bla.test.com";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
};
auto CheckPortDomain = [&](bool expected)
{
spec = "http://blabla.com:10";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
};
auto CheckLocalDomain = [&](bool expected)
{
spec = "http://test";
ASSERT_EQ(url->SetSpec(spec), NS_OK);
ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK);
ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
};

View File

@ -16,7 +16,7 @@ extern nsresult Test_NormalizeIPv4(const nsACString& host, nsCString& result);
TEST(TestStandardURL, Simple) {
nsCOMPtr<nsIURL> url( do_CreateInstance(NS_STANDARDURL_CONTRACTID) );
ASSERT_TRUE(url);
ASSERT_EQ(url->SetSpec(NS_LITERAL_CSTRING("http://example.com")), NS_OK);
ASSERT_EQ(url->SetSpecInternal(NS_LITERAL_CSTRING("http://example.com")), NS_OK);
nsAutoCString out;
@ -183,7 +183,7 @@ MOZ_GTEST_BENCH(TestStandardURL, Perf, [] {
nsAutoCString out;
for (int i = COUNT; i; --i) {
ASSERT_EQ(url->SetSpec(NS_LITERAL_CSTRING("http://example.com")), NS_OK);
ASSERT_EQ(url->SetSpecInternal(NS_LITERAL_CSTRING("http://example.com")), NS_OK);
ASSERT_EQ(url->GetSpec(out), NS_OK);
url->Resolve(NS_LITERAL_CSTRING("foo.html?q=45"), out);
url->SetScheme(NS_LITERAL_CSTRING("foo"));

View File

@ -625,7 +625,7 @@ function do_test_immutable(aTest) {
var URI = NetUtil.newURI(aTest.spec);
// All the non-readonly attributes on nsIURI.idl:
var propertiesToCheck = ["spec", "scheme", "userPass", "username", "password",
var propertiesToCheck = ["scheme", "userPass", "username", "password",
"hostPort", "host", "port", "pathQueryRef", "query", "ref"];
propertiesToCheck.forEach(function(aProperty) {

View File

@ -303,7 +303,7 @@ add_test(function test_hugeStringThrows()
let url = stringToURL("http://test:test@example.com");
let hugeString = new Array(maxLen + 1).fill("a").join("");
let properties = ["spec", "scheme", "userPass", "username",
let properties = ["scheme", "userPass", "username",
"password", "hostPort", "host", "pathQueryRef", "ref",
"query", "fileName", "filePath", "fileBaseName", "fileExtension"];
for (let prop of properties) {
@ -312,6 +312,10 @@ add_test(function test_hugeStringThrows()
`Passing a huge string to "${prop}" should throw`);
}
Assert.throws(() => { url = url.mutate().setSpec(hugeString).finalize(); },
/NS_ERROR_MALFORMED_URI/,
"Passing a huge string to setSpec should throw");
run_next_test();
});

View File

@ -29,6 +29,8 @@
#include "mozilla/Maybe.h"
#include "mozilla/Printf.h"
#include "mozilla/UniquePtr.h"
#include "nsNetCID.h"
#include "nsIURIMutator.h"
using namespace JS;
@ -127,12 +129,12 @@ TEST_F(TestStartupCache, WriteObject)
{
nsresult rv;
nsCOMPtr<nsIURI> obj
= do_CreateInstance("@mozilla.org/network/simple-uri;1");
ASSERT_TRUE(obj);
nsCOMPtr<nsIURI> obj;
NS_NAMED_LITERAL_CSTRING(spec, "http://www.mozilla.org");
rv = obj->SetSpec(spec);
rv = NS_MutateURI(NS_SIMPLEURIMUTATOR_CONTRACTID)
.SetSpec(spec)
.Finalize(obj);
EXPECT_TRUE(NS_SUCCEEDED(rv));
StartupCache* sc = StartupCache::GetSingleton();