Bug 1148544 - Figure out UA override once per LoadGroup and cache it, rather than once per channel. r=nwgh

This commit is contained in:
Dylan Roeh 2016-02-09 15:33:34 -06:00 committed by James Willcox
parent eb8def7734
commit 77573ada71
10 changed files with 95 additions and 13 deletions

View File

@ -58,7 +58,7 @@ interface nsILoadGroup : nsIRequest
* By the time this call ends, aRequest will have been removed from the
* loadgroup, even if this function throws an exception.
*/
void removeRequest(in nsIRequest aRequest,
void removeRequest(in nsIRequest aRequest,
in nsISupports aContext,
in nsresult aStatus);
@ -97,4 +97,10 @@ interface nsILoadGroup : nsIRequest
* the docShell has created the default request.)
*/
attribute nsLoadFlags defaultLoadFlags;
/**
* The cached user agent override created by UserAgentOverrides.jsm. Used
* for all sub-resource requests in the loadgroup.
*/
attribute ACString userAgentOverrideCache;
};

View File

@ -172,7 +172,7 @@ nsLoadGroup::GetName(nsACString &result)
result.Truncate();
return NS_OK;
}
return mDefaultLoadRequest->GetName(result);
}
@ -188,9 +188,9 @@ nsLoadGroup::GetStatus(nsresult *status)
{
if (NS_SUCCEEDED(mStatus) && mDefaultLoadRequest)
return mDefaultLoadRequest->GetStatus(status);
*status = mStatus;
return NS_OK;
return NS_OK;
}
static bool
@ -480,7 +480,7 @@ nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt)
rv = MergeLoadFlags(request, flags);
}
if (NS_FAILED(rv)) return rv;
//
// Add the request to the list of active requests...
//
@ -810,10 +810,24 @@ nsLoadGroup::SetDefaultLoadFlags(uint32_t aFlags)
return NS_OK;
}
NS_IMETHODIMP
nsLoadGroup::GetUserAgentOverrideCache(nsACString & aUserAgentOverrideCache)
{
aUserAgentOverrideCache = mUserAgentOverrideCache;
return NS_OK;
}
NS_IMETHODIMP
nsLoadGroup::SetUserAgentOverrideCache(const nsACString & aUserAgentOverrideCache)
{
mUserAgentOverrideCache = aUserAgentOverrideCache;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
void
void
nsLoadGroup::TelemetryReport()
{
if (mDefaultLoadIsTimed) {

View File

@ -29,7 +29,7 @@ class nsLoadGroup : public nsILoadGroup,
{
public:
NS_DECL_AGGREGATED
////////////////////////////////////////////////////////////////////////////
// nsIRequest methods:
NS_DECL_NSIREQUEST
@ -79,7 +79,7 @@ protected:
nsWeakPtr mObserver;
nsWeakPtr mParentLoadGroup;
nsresult mStatus;
int32_t mPriority;
bool mIsCanceling;
@ -92,6 +92,8 @@ protected:
/* For nsPILoadGroupInternal */
uint32_t mTimedNonCachedRequestsUntilOnEndPageLoad;
nsCString mUserAgentOverrideCache;
};
#endif // nsLoadGroup_h__

View File

@ -2464,6 +2464,41 @@ HttpBaseChannel::ShouldIntercept(nsIURI* aURI)
return shouldIntercept;
}
void
HttpBaseChannel::SetLoadGroupUserAgentOverride()
{
nsCOMPtr<nsIURI> uri;
GetURI(getter_AddRefs(uri));
nsAutoCString uriScheme;
if (uri) {
uri->GetScheme(uriScheme);
}
nsCOMPtr<nsILoadGroupChild> childLoadGroup = do_QueryInterface(mLoadGroup);
nsCOMPtr<nsILoadGroup> rootLoadGroup;
if (childLoadGroup) {
childLoadGroup->GetRootLoadGroup(getter_AddRefs(rootLoadGroup));
}
if (rootLoadGroup && !uriScheme.EqualsLiteral("file")) {
nsAutoCString ua;
if (nsContentUtils::IsNonSubresourceRequest(this)) {
gHttpHandler->OnUserAgentRequest(this);
GetRequestHeader(NS_LITERAL_CSTRING("User-Agent"), ua);
rootLoadGroup->SetUserAgentOverrideCache(ua);
} else {
GetRequestHeader(NS_LITERAL_CSTRING("User-Agent"), ua);
// Don't overwrite the UA if it is already set (eg by an XHR with explicit UA).
if (ua.IsEmpty()) {
rootLoadGroup->GetUserAgentOverrideCache(ua);
SetRequestHeader(NS_LITERAL_CSTRING("User-Agent"), ua, false);
}
}
} else {
// If the root loadgroup doesn't exist or if the channel's URI's scheme is "file",
// fall back on getting the UA override per channel.
gHttpHandler->OnUserAgentRequest(this);
}
}
//-----------------------------------------------------------------------------
// nsHttpChannel::nsITraceableChannel
//-----------------------------------------------------------------------------

View File

@ -353,6 +353,8 @@ protected:
// for a possible synthesized response instead.
bool ShouldIntercept(nsIURI* aURI = nullptr);
void SetLoadGroupUserAgentOverride();
friend class PrivateBrowsingChannel<HttpBaseChannel>;
friend class InterceptFailedOnStop;

View File

@ -1805,9 +1805,12 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
return NS_OK;
}
// Set user agent override
// Set user agent override from docshell
HttpBaseChannel::SetDocshellUserAgentOverride();
// Set user agent override from loadgroup
HttpBaseChannel::SetLoadGroupUserAgentOverride();
MOZ_ASSERT_IF(mPostRedirectChannelShouldUpgrade,
mPostRedirectChannelShouldIntercept);
bool shouldUpgrade = mPostRedirectChannelShouldUpgrade;

View File

@ -46,9 +46,9 @@ this.UserAgentOverrides = {
Services.prefs.addObserver(PREF_OVERRIDES_ENABLED, buildOverrides, false);
try {
Services.obs.addObserver(HTTP_on_modify_request, "http-on-modify-request", false);
Services.obs.addObserver(HTTP_on_useragent_request, "http-on-useragent-request", false);
} catch (x) {
// The http-on-modify-request notification is disallowed in content processes.
// The http-on-useragent-request notification is disallowed in content processes.
}
UserAgentUpdates.init(function(overrides) {
@ -118,7 +118,7 @@ this.UserAgentOverrides = {
Services.prefs.removeObserver(PREF_OVERRIDES_ENABLED, buildOverrides);
Services.obs.removeObserver(HTTP_on_modify_request, "http-on-modify-request");
Services.obs.removeObserver(HTTP_on_useragent_request, "http-on-useragent-request");
},
receiveMessage: function(aMessage) {
@ -169,7 +169,7 @@ function buildOverrides() {
}
}
function HTTP_on_modify_request(aSubject, aTopic, aData) {
function HTTP_on_useragent_request(aSubject, aTopic, aData) {
let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
for (let callback of gOverrideFunctions) {

View File

@ -5178,6 +5178,11 @@ nsHttpChannel::BeginConnect()
// notify "http-on-modify-request" observers
CallOnModifyRequestObservers();
// If mLoadGroup is null, e10s is enabled and this will be handled by HttpChannelChild.
if (mLoadGroup) {
HttpBaseChannel::SetLoadGroupUserAgentOverride();
}
// Check to see if we should redirect this channel elsewhere by
// nsIHttpChannel.redirectTo API request
if (mAPIRedirectToURI) {

View File

@ -275,6 +275,12 @@ public:
NotifyObservers(chan, NS_HTTP_ON_MODIFY_REQUEST_TOPIC);
}
// Called by the channel and cached in the loadGroup
void OnUserAgentRequest(nsIHttpChannel *chan)
{
NotifyObservers(chan, NS_HTTP_ON_USERAGENT_REQUEST_TOPIC);
}
// Called by the channel once headers are available
void OnExamineResponse(nsIHttpChannel *chan)
{

View File

@ -113,5 +113,14 @@ interface nsIHttpProtocolHandler : nsIProxiedProtocolHandler
*/
#define NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC "http-on-examine-cached-response"
/**
* Before an HTTP request corresponding to a channel with the LOAD_DOCUMENT_URI
* flag is sent to the server, this observer topic is notified. The observer of
* this topic can then choose to modify the user agent for this request before
* the request is actually sent to the server. Additionally, the modified user
* agent will be propagated to sub-resource requests from the same load group.
*/
#define NS_HTTP_ON_USERAGENT_REQUEST_TOPIC "http-on-useragent-request"
%}