// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Web.Hosting; namespace System.Web.WebPages { /// /// Extension methods used to determine what browser a visitor wants to be seen as using. /// public static class BrowserHelpers { /// /// Stock IE6 user agent string /// private const string DesktopUserAgent = "Mozilla/4.0 (compatible; MSIE 6.1; Windows XP)"; /// /// Stock Windows Mobile 6.0 user agent string /// private const string MobileUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile 6.0)"; private static readonly object _browserOverrideKey = new object(); private static readonly object _userAgentKey = new object(); /// /// Clears the set browser for the request. After clearing the browser the overridden browser will be the browser for the request. /// public static void ClearOverriddenBrowser(this HttpContextBase httpContext) { SetOverriddenBrowser(httpContext, userAgent: null); } // Default implementation to generate an HttpBrowserCapabilities object using the current HttpCapabilitiesProvider private static HttpBrowserCapabilitiesBase CreateOverriddenBrowser(string userAgent) { HttpBrowserCapabilities overriddenBrowser = new HttpContext(new UserAgentWorkerRequest(userAgent)).Request.Browser; return new HttpBrowserCapabilitiesWrapper(overriddenBrowser); } /// /// Gets the overridden browser for the request based on the overridden user agent. /// If no overridden user agent is set, returns the browser for the request. /// public static HttpBrowserCapabilitiesBase GetOverriddenBrowser(this HttpContextBase httpContext) { return GetOverriddenBrowser(httpContext, CreateOverriddenBrowser); } internal static HttpBrowserCapabilitiesBase GetOverriddenBrowser(this HttpContextBase httpContext, Func createBrowser) { HttpBrowserCapabilitiesBase overriddenBrowser = (HttpBrowserCapabilitiesBase)httpContext.Items[_browserOverrideKey]; if (overriddenBrowser == null) { string overriddenUserAgent = GetOverriddenUserAgent(httpContext); if (!String.Equals(overriddenUserAgent, httpContext.Request.UserAgent)) { overriddenBrowser = createBrowser(overriddenUserAgent); } else { overriddenBrowser = httpContext.Request.Browser; } httpContext.Items[_browserOverrideKey] = overriddenBrowser; } return overriddenBrowser; } /// /// Gets the overridden user agent for the request. If no overridden user agent is set, returns the user agent for the request. /// public static string GetOverriddenUserAgent(this HttpContextBase httpContext) { return (string)httpContext.Items[_userAgentKey] ?? BrowserOverrideStores.Current.GetOverriddenUserAgent(httpContext) ?? httpContext.Request.UserAgent; } /// /// Gets a string that varies based upon the type of the browser. Can be used to override /// System.Web.HttpApplication.GetVaryByCustomString to differentiate cache keys based on /// the overridden browser. /// public static string GetVaryByCustomStringForOverriddenBrowser(this HttpContext httpContext) { return GetVaryByCustomStringForOverriddenBrowser(new HttpContextWrapper(httpContext)); } /// /// Gets a string that varies based upon the type of the browser. Can be used to override /// System.Web.HttpApplication.GetVaryByCustomString to differentiate cache keys based on /// the overridden browser. /// public static string GetVaryByCustomStringForOverriddenBrowser(this HttpContextBase httpContext) { return GetVaryByCustomStringForOverriddenBrowser(httpContext, userAgent => CreateOverriddenBrowser(userAgent)); } internal static string GetVaryByCustomStringForOverriddenBrowser(this HttpContextBase httpContext, Func generateBrowser) { return GetOverriddenBrowser(httpContext, generateBrowser).Type; } /// /// Sets the overridden user agent for the request using a BrowserOverride. /// public static void SetOverriddenBrowser(this HttpContextBase httpContext, BrowserOverride browserOverride) { string userAgent = null; switch (browserOverride) { case BrowserOverride.Desktop: // bug:262389 override only if the request was not made from a browser or the browser is not of a desktop device if (httpContext.Request.Browser == null || httpContext.Request.Browser.IsMobileDevice) { userAgent = DesktopUserAgent; } break; case BrowserOverride.Mobile: if (httpContext.Request.Browser == null || !httpContext.Request.Browser.IsMobileDevice) { userAgent = MobileUserAgent; } break; } if (userAgent != null) { SetOverriddenBrowser(httpContext, userAgent); } else { ClearOverriddenBrowser(httpContext); } } /// /// Sets the overridden user agent for the request using a string /// public static void SetOverriddenBrowser(this HttpContextBase httpContext, string userAgent) { // Set the overridden user agent and clear the overridden browser // so that it can be generated from the new overridden user agent. httpContext.Items[_userAgentKey] = userAgent; httpContext.Items[_browserOverrideKey] = null; BrowserOverrideStores.Current.SetOverriddenUserAgent(httpContext, userAgent); } private sealed class UserAgentWorkerRequest : SimpleWorkerRequest { private readonly string _userAgent; public UserAgentWorkerRequest(string userAgent) : base(String.Empty, String.Empty, output: null) { _userAgent = userAgent; } public override string GetKnownRequestHeader(int index) { return index == HeaderUserAgent ? _userAgent : null; } } } }