//------------------------------------------------------------------------------
// <copyright file="ScriptManager.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

namespace System.Web.UI {
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Configuration;
    using System.Diagnostics.CodeAnalysis;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Globalization;
    using System.Linq;
    using System.Reflection;
    using System.Security;
    using System.Security.Permissions;
    using System.Text;
    using System.Web;
    using System.Web.Compilation;
    using System.Web.Configuration;
    using System.Web.Globalization;
    using System.Web.Handlers;
    using System.Web.Hosting;
    using System.Web.Resources;
    using System.Web.Script;
    using System.Web.Script.Serialization;
    using System.Web.Script.Services;
    using System.Web.Security.Cryptography;
    using System.Web.UI.Design;
    using System.Web.Util;

    [
    DefaultProperty("Scripts"),
    Designer("System.Web.UI.Design.ScriptManagerDesigner, " + AssemblyRef.SystemWebExtensionsDesign),
    NonVisualControl(),
    ParseChildren(true),
    PersistChildren(false),
    ToolboxBitmap(typeof(EmbeddedResourceFinder), "System.Web.Resources.ScriptManager.bmp")
    ]
    public class ScriptManager : Control, IPostBackDataHandler, IPostBackEventHandler, IControl, IScriptManager, IScriptManagerInternal {
        private readonly new IPage _page;
        private readonly IControl _control;
        private readonly ICompilationSection _appLevelCompilationSection;
        private readonly IDeploymentSection _deploymentSection;
        private readonly ICustomErrorsSection _customErrorsSection;
        private static bool _ajaxFrameworkAssemblyConfigChecked;
        private static Assembly _defaultAjaxFrameworkAssembly = null;
        private Assembly _ajaxFrameworkAssembly = DefaultAjaxFrameworkAssembly;

        private const int AsyncPostBackTimeoutDefault = 90;

        private ScriptMode _scriptMode;
        private string _scriptPath;
        private CompositeScriptReference _compositeScript;
        private ScriptReferenceCollection _scripts;
        private ServiceReferenceCollection _services;
        private bool? _isRestMethodCall;
        private bool? _isSecureConnection;
        private List<ScriptManagerProxy> _proxies;
        private AjaxFrameworkMode _ajaxFrameworkMode = AjaxFrameworkMode.Enabled;
        private bool _enablePartialRendering = true;
        private bool _supportsPartialRendering = true;
        internal bool _supportsPartialRenderingSetByUser;
        internal ScriptReferenceBase _applicationServicesReference;
        private string _appServicesInitializationScript;
        private bool _enableScriptGlobalization;
        private bool _enableScriptLocalization = true;
        private bool _enablePageMethods;
        private bool _loadScriptsBeforeUI = true;
        private bool _initCompleted;
        private bool _preRenderCompleted;
        private bool _isInAsyncPostBack;
        private int _asyncPostBackTimeout = AsyncPostBackTimeoutDefault;
        private bool _allowCustomErrorsRedirect = true;
        private string _asyncPostBackErrorMessage;
        private bool _zip;
        private bool _zipSet;
        private int _uniqueScriptCounter;
        private bool _enableCdn;
        private bool _enableCdnFallback = true;
        private HashSet<String> _scriptPathsDefiningSys = new HashSet<String>(StringComparer.OrdinalIgnoreCase);

        private static readonly object AsyncPostBackErrorEvent = new object();
        private static readonly object ResolveCompositeScriptReferenceEvent = new object();
        private static readonly object ResolveScriptReferenceEvent = new object();
        private static HashSet<String> _splitFrameworkScript;
        private ScriptRegistrationManager _scriptRegistration;
        private PageRequestManager _pageRequestManager;

        private ScriptControlManager _scriptControlManager;

        private ProfileServiceManager _profileServiceManager;
        private AuthenticationServiceManager _authenticationServiceManager;
        private RoleServiceManager _roleServiceManager;

        private BundleReflectionHelper _bundleReflectionHelper;

        // History fields
        private bool _enableSecureHistoryState = true;
        private bool _enableHistory;
        private bool _isNavigating;
        private string _clientNavigateHandler;
        // Using a hashtable here, which will be more efficiently serialized 
        // by the page state formatter than a Dictionary<string, object>
        // or een NameValueCollection.
        private Hashtable _initialState;
        private static readonly object NavigateEvent = new object();
        private bool _newPointCreated;

        static ScriptManager() {
            ClientScriptManager._scriptResourceMapping = new ScriptResourceMapping();
        }

        public ScriptManager() {
        }

        internal ScriptManager(IControl control,
                               IPage page,
                               ICompilationSection appLevelCompilationSection,
                               IDeploymentSection deploymentSection,
                               ICustomErrorsSection customErrorsSection,
                               Assembly ajaxFrameworkAssembly,
                               bool isSecureConnection) {
            _control = control;
            _page = page;
            _appLevelCompilationSection = appLevelCompilationSection;
            _deploymentSection = deploymentSection;
            _customErrorsSection = customErrorsSection;
            _ajaxFrameworkAssembly = ajaxFrameworkAssembly ?? DefaultAjaxFrameworkAssembly;
            _isSecureConnection = isSecureConnection;
        }

        [
        ResourceDescription("ScriptManager_AjaxFrameworkAssembly"),
        Browsable(false)
        ]
        public virtual Assembly AjaxFrameworkAssembly {
            get {
                // value is set to the static DefaultAjaxFrameworkAssembly one at constructor time,
                // so this property value can't change in the middle of a request.
                return _ajaxFrameworkAssembly;
            }
        }

        [
        DefaultValue(true),
        ResourceDescription("ScriptManager_AllowCustomErrorsRedirect"),
        Category("Behavior"),
        ]
        public bool AllowCustomErrorsRedirect {
            get {
                return _allowCustomErrorsRedirect;
            }
            set {
                _allowCustomErrorsRedirect = value;
            }
        }

        private ICompilationSection AppLevelCompilationSection {
            get {
                if (_appLevelCompilationSection != null) {
                    return _appLevelCompilationSection;
                }
                else {
                    return AppLevelCompilationSectionCache.Instance;
                }
            }
        }

        [
        DefaultValue(""),
        ResourceDescription("ScriptManager_AsyncPostBackErrorMessage"),
        Category("Behavior")
        ]
        public string AsyncPostBackErrorMessage {
            get {
                if (_asyncPostBackErrorMessage == null) {
                    return String.Empty;
                }
                return _asyncPostBackErrorMessage;
            }
            set {
                _asyncPostBackErrorMessage = value;
            }
        }

        // FxCop does not flag this as a violation, because it is an implicit implementation of
        // IScriptManagerInternal.AsyncPostBackSourceElementID.  
        // 
        [
        Browsable(false),
        SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")
        ]
        public string AsyncPostBackSourceElementID {
            get {
                return PageRequestManager.AsyncPostBackSourceElementID;
            }
        }

        [
        ResourceDescription("ScriptManager_AsyncPostBackTimeout"),
        Category("Behavior"),
        DefaultValue(AsyncPostBackTimeoutDefault)
        ]
        public int AsyncPostBackTimeout {
            get {
                return _asyncPostBackTimeout;
            }
            set {
                if (value < 0) {
                    throw new ArgumentOutOfRangeException("value");
                }
                _asyncPostBackTimeout = value;
            }
        }

        [
        ResourceDescription("ScriptManager_AuthenticationService"),
        Category("Behavior"),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        PersistenceMode(PersistenceMode.InnerProperty),
        MergableProperty(false),
        ]
        public AuthenticationServiceManager AuthenticationService {
            get {
                if (_authenticationServiceManager == null) {
                    _authenticationServiceManager = new AuthenticationServiceManager();
                }
                return _authenticationServiceManager;
            }
        }

        internal BundleReflectionHelper BundleReflectionHelper {
            get {
                if (_bundleReflectionHelper == null) {
                    _bundleReflectionHelper = new BundleReflectionHelper();
                }
                return _bundleReflectionHelper;
            }
            set {
                _bundleReflectionHelper = value;
            }
        }

        public static ScriptResourceMapping ScriptResourceMapping {
            get {
                return (ScriptResourceMapping)ClientScriptManager._scriptResourceMapping;
            }
        }

        [
        ResourceDescription("ScriptManager_ClientNavigateHandler"),
        Category("Behavior"),
        DefaultValue("")
        ]
        public string ClientNavigateHandler {
            get {
                return _clientNavigateHandler ?? String.Empty;
            }
            set {
                _clientNavigateHandler = value;
            }
        }

        [
        ResourceDescription("ScriptManager_CompositeScript"),
        Category("Behavior"),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        PersistenceMode(PersistenceMode.InnerProperty),
        MergableProperty(false),
        ]
        public CompositeScriptReference CompositeScript {
            get {
                if (_compositeScript == null) {
                    _compositeScript = new CompositeScriptReference();
                }
                return _compositeScript;
            }
        }

        internal IControl Control {
            get {
                if (_control != null) {
                    return _control;
                }
                else {
                    return this;
                }
            }
        }

        internal ICustomErrorsSection CustomErrorsSection {
            [SecurityCritical()]
            get {
                if (_customErrorsSection != null) {
                    return _customErrorsSection;
                }
                else {
                    return GetCustomErrorsSectionWithAssert();
                }
            }
        }

        internal static Assembly DefaultAjaxFrameworkAssembly {
            get {
                if ((_defaultAjaxFrameworkAssembly == null) && !_ajaxFrameworkAssemblyConfigChecked && AssemblyCache._useCompilationSection) {
                    IEnumerable<Assembly> referencedAssemblies;
                    // In a hosted environment we want to get the assemblies from the BuildManager. This will include
                    // dynamically added assemblies through the PreAppStart phase.
                    // In non-hosted scenarios (VS designer) we want to look the assemblies directly from the config system
                    // since the PreAppStart phase will not execute.
                    if (HostingEnvironment.IsHosted) {
                        referencedAssemblies = BuildManager.GetReferencedAssemblies().OfType<Assembly>();
                    }
                    else {
                        CompilationSection compilationSection = RuntimeConfig.GetAppConfig().Compilation;
                        referencedAssemblies = compilationSection.Assemblies.OfType<AssemblyInfo>().SelectMany(assemblyInfo => assemblyInfo.AssemblyInternal);
                    }

                    foreach (Assembly assembly in referencedAssemblies) {
                        if (assembly != AssemblyCache.SystemWebExtensions) {
                            AjaxFrameworkAssemblyAttribute attribute =
                                AssemblyCache.GetAjaxFrameworkAssemblyAttribute(assembly);
                            if (attribute != null) {
                                _defaultAjaxFrameworkAssembly = attribute.GetDefaultAjaxFrameworkAssembly(assembly);
                                break;
                            }
                        }
                        _ajaxFrameworkAssemblyConfigChecked = true;
                    }
                    _ajaxFrameworkAssemblyConfigChecked = true;
                }
                return _defaultAjaxFrameworkAssembly ?? AssemblyCache.SystemWebExtensions;
            }
            set {
                if (value == null) {
                    throw new ArgumentNullException("value");
                }
                _defaultAjaxFrameworkAssembly = value;
            }
        }

        private IDeploymentSection DeploymentSection {
            get {
                if (_deploymentSection != null) {
                    return _deploymentSection;
                }
                else {
                    return DeploymentSectionCache.Instance;
                }
            }
        }

        internal bool DeploymentSectionRetail {
            get {
                return DeploymentSection.Retail;
            }
        }

        [
        ResourceDescription("ScriptManager_EmptyPageUrl"),
        Category("Appearance"),
        Editor(typeof(UrlEditor), typeof(UITypeEditor)),
        DefaultValue(""),
        UrlProperty,
        SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Consistent with other asp.net url properties.")
        ]
        public virtual string EmptyPageUrl {
            get {
                return ViewState["EmptyPageUrl"] as string ?? string.Empty;
            }
            set {
                ViewState["EmptyPageUrl"] = value;
            }
        }

        [
        ResourceDescription("ScriptManager_EnableCdn"),
        Category("Behavior"),
        DefaultValue(false),
        ]
        public bool EnableCdn {
            get {
                return _enableCdn;
            }
            set {
                if (_preRenderCompleted) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotChangeEnableCdn);
                }
                _enableCdn = value;
            }
        }

        [
        ResourceDescription("ScriptManager_EnableCdnFallback"),
        Category("Behavior"),
        DefaultValue(true)
        ]
        public bool EnableCdnFallback {
            get {
                return _enableCdnFallback;
            }
            set {
                if (_preRenderCompleted) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotChangeEnableCdnFallback);
                }
                _enableCdnFallback = value;
            }
        }

        [
        ResourceDescription("ScriptManager_EnableHistory"),
        Category("Behavior"),
        DefaultValue(false),
        ]
        public bool EnableHistory {
            get {
                return _enableHistory;
            }
            set {
                if (_initCompleted) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotChangeEnableHistory);
                }
                _enableHistory = value;
            }
        }

        [
        ResourceDescription("ScriptManager_AjaxFrameworkMode"),
        Category("Behavior"),
        DefaultValue(AjaxFrameworkMode.Enabled),
        ]
        public AjaxFrameworkMode AjaxFrameworkMode {
            get {
                return _ajaxFrameworkMode;
            }
            set {
                if (value < AjaxFrameworkMode.Enabled || value > AjaxFrameworkMode.Explicit) {
                    throw new ArgumentOutOfRangeException("value");
                }
                if (_initCompleted) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotChangeAjaxFrameworkMode);
                }
                _ajaxFrameworkMode = value;
            }
        }

        [
        ResourceDescription("ScriptManager_EnablePageMethods"),
        Category("Behavior"),
        DefaultValue(false),
        ]
        public bool EnablePageMethods {
            get {
                return _enablePageMethods;
            }
            set {
                _enablePageMethods = value;
            }
        }

        [
        ResourceDescription("ScriptManager_EnablePartialRendering"),
        Category("Behavior"),
        DefaultValue(true),
        ]
        public bool EnablePartialRendering {
            get {
                return _enablePartialRendering;
            }
            set {
                if (_initCompleted) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotChangeEnablePartialRendering);
                }
                _enablePartialRendering = value;
            }
        }

        [
        ResourceDescription("ScriptManager_EnableScriptGlobalization"),
        Category("Behavior"),
        DefaultValue(false),
        ]
        public bool EnableScriptGlobalization {
            get {
                return _enableScriptGlobalization;
            }
            set {
                if (_initCompleted) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotChangeEnableScriptGlobalization);
                }
                _enableScriptGlobalization = value;
            }
        }

        [
        ResourceDescription("ScriptManager_EnableScriptLocalization"),
        Category("Behavior"),
        DefaultValue(true),
        ]
        public bool EnableScriptLocalization {
            get {
                return _enableScriptLocalization;
            }
            set {
                _enableScriptLocalization = value;
            }
        }

        [
        ResourceDescription("ScriptManager_EnableSecureHistoryState"),
        Category("Behavior"),
        DefaultValue(true),
        ]
        public bool EnableSecureHistoryState {
            get {
                return _enableSecureHistoryState;
            }
            set {
                _enableSecureHistoryState = value;
            }
        }

        internal bool HasAuthenticationServiceManager {
            get {
                return this._authenticationServiceManager != null;
            }
        }

        internal bool HasProfileServiceManager {
            get {
                return this._profileServiceManager != null;
            }
        }

        internal bool HasRoleServiceManager {
            get {
                return this._roleServiceManager != null;
            }
        }

        [Browsable(false)]
        public bool IsDebuggingEnabled {
            get {
                // Returns false when:
                // - Deployment mode is set to retail (override all other settings)
                // - ScriptMode is set to Auto or Inherit, and debugging it not enabled in web.config
                // - ScriptMode is set to Release

                if (DeploymentSectionRetail) {
                    return false;
                }
                if (ScriptMode == ScriptMode.Auto || ScriptMode == ScriptMode.Inherit) {
                    return AppLevelCompilationSection.Debug;
                }
                return (ScriptMode == ScriptMode.Debug);
            }
        }

        [
        Browsable(false),
        SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")
        ]
        public bool IsInAsyncPostBack {
            get {
                return _isInAsyncPostBack;
            }
        }

        [
        Browsable(false),
        SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")
        ]
        public bool IsNavigating {
            get {
                return _isNavigating;
            }
        }

        internal bool IsRestMethodCall {
            get {
                if (!_isRestMethodCall.HasValue) {
                    _isRestMethodCall = (Context != null) && RestHandlerFactory.IsRestMethodCall(Context.Request);
                }
                return _isRestMethodCall.Value;
            }
        }

        internal bool IsSecureConnection {
            get {
                if (!_isSecureConnection.HasValue) {
                    _isSecureConnection = (Context != null) && (Context.Request != null) && Context.Request.IsSecureConnection;
                }
                return _isSecureConnection.Value;
            }
        }

        internal IPage IPage {
            get {
                if (_page != null) {
                    return _page;
                }
                else {
                    Page page = Page;
                    if (page == null) {
                        throw new InvalidOperationException(AtlasWeb.Common_PageCannotBeNull);
                    }
                    return new PageWrapper(page);
                }
            }
        }

        // DevDiv bugs #46710: Ability to specify whether scripts are loaded inline at the top of the form (before UI), or via ScriptLoader (after UI).
        [
        ResourceDescription("ScriptManager_LoadScriptsBeforeUI"),
        Category("Behavior"),
        DefaultValue(true),
        ]
        public bool LoadScriptsBeforeUI {
            get {
                return _loadScriptsBeforeUI;
            }
            set {
                _loadScriptsBeforeUI = value;
            }
        }

        private PageRequestManager PageRequestManager {
            get {
                if (_pageRequestManager == null) {
                    _pageRequestManager = new PageRequestManager(this);
                }
                return _pageRequestManager;
            }
        }

        [
        ResourceDescription("ScriptManager_ProfileService"),
        Category("Behavior"),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        PersistenceMode(PersistenceMode.InnerProperty),
        MergableProperty(false),
        ]
        public ProfileServiceManager ProfileService {
            get {
                if (_profileServiceManager == null) {
                    _profileServiceManager = new ProfileServiceManager();
                }
                return _profileServiceManager;
            }
        }

        internal List<ScriptManagerProxy> Proxies {
            get {
                if (_proxies == null) {
                    _proxies = new List<ScriptManagerProxy>();
                }
                return _proxies;
            }
        }

        [
        ResourceDescription("ScriptManager_RoleService"),
        Category("Behavior"),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        PersistenceMode(PersistenceMode.InnerProperty),
        MergableProperty(false),
        ]
        public RoleServiceManager RoleService {
            get {
                if (_roleServiceManager == null) {
                    _roleServiceManager = new RoleServiceManager();
                }
                return _roleServiceManager;
            }
        }

        internal ScriptControlManager ScriptControlManager {
            get {
                if (_scriptControlManager == null) {
                    _scriptControlManager = new ScriptControlManager(this);
                }
                return _scriptControlManager;
            }
        }

        [
        ResourceDescription("ScriptManager_ScriptMode"),
        Category("Behavior"),
        DefaultValue(ScriptMode.Auto),
        ]
        public ScriptMode ScriptMode {
            get {
                return _scriptMode;
            }
            set {
                if (value < ScriptMode.Auto || value > ScriptMode.Release) {
                    throw new ArgumentOutOfRangeException("value");
                }
                _scriptMode = value;
            }
        }

        internal ScriptRegistrationManager ScriptRegistration {
            get {
                if (_scriptRegistration == null) {
                    _scriptRegistration = new ScriptRegistrationManager(this);
                }
                return _scriptRegistration;
            }
        }

        [
        ResourceDescription("ScriptManager_Scripts"),
        Category("Behavior"),
        Editor("System.Web.UI.Design.CollectionEditorBase, " +
            AssemblyRef.SystemWebExtensionsDesign, typeof(UITypeEditor)),
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty),
        MergableProperty(false),
        ]
        public ScriptReferenceCollection Scripts {
            get {
                if (_scripts == null) {
                    _scripts = new ScriptReferenceCollection();
                }
                return _scripts;
            }
        }

        [
        ResourceDescription("ScriptManager_ScriptPath"),
        Category("Behavior"),
        DefaultValue(""),
        Obsolete("This property is obsolete. Set the Path property on each individual ScriptReference instead."),
        ]
        public string ScriptPath {
            get {
                return (_scriptPath == null) ? String.Empty : _scriptPath;
            }
            set {
                _scriptPath = value;
            }
        }

        [
        ResourceDescription("ScriptManager_Services"),
        Category("Behavior"),
        Editor("System.Web.UI.Design.ServiceReferenceCollectionEditor, " +
            AssemblyRef.SystemWebExtensionsDesign, typeof(UITypeEditor)),
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty),
        MergableProperty(false),
        ]
        public ServiceReferenceCollection Services {
            get {
                if (_services == null) {
                    _services = new ServiceReferenceCollection();
                }
                return _services;
            }
        }

        private static HashSet<String> SplitFrameworkScripts {
            get {
                if (_splitFrameworkScript == null) {
                    HashSet<String> scripts = new HashSet<String>();
                    scripts.Add("MicrosoftAjaxComponentModel.js");
                    scripts.Add("MicrosoftAjaxComponentModel.debug.js");
                    scripts.Add("MicrosoftAjaxCore.js");
                    scripts.Add("MicrosoftAjaxCore.debug.js");
                    scripts.Add("MicrosoftAjaxGlobalization.js");
                    scripts.Add("MicrosoftAjaxGlobalization.debug.js");
                    scripts.Add("MicrosoftAjaxHistory.js");
                    scripts.Add("MicrosoftAjaxHistory.debug.js");
                    scripts.Add("MicrosoftAjaxNetwork.js");
                    scripts.Add("MicrosoftAjaxNetwork.debug.js");
                    scripts.Add("MicrosoftAjaxSerialization.js");
                    scripts.Add("MicrosoftAjaxSerialization.debug.js");
                    scripts.Add("MicrosoftAjaxWebServices.js");
                    scripts.Add("MicrosoftAjaxWebServices.debug.js");
                    _splitFrameworkScript = scripts;
                }
                return _splitFrameworkScript;
            }
        }

        [
        Browsable(false),
        DefaultValue(true),
        SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")
        ]
        public bool SupportsPartialRendering {
            get {
                if (!EnablePartialRendering) {
                    // If the user doesn't even want partial rendering then
                    // we definitely don't support it.
                    return false;
                }
                return _supportsPartialRendering;
            }
            set {
                if (!EnablePartialRendering) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotSetSupportsPartialRenderingWhenDisabled);
                }
                if (_initCompleted) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotChangeSupportsPartialRendering);
                }
                _supportsPartialRendering = value;

                // Mark that this was explicitly set. We'll set this back to false if we
                // explicitly set the value of this property.
                _supportsPartialRenderingSetByUser = true;
            }
        }

        [
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never)
        ]
        public override bool Visible {
            get {
                return base.Visible;
            }
            set {
                throw new NotImplementedException();
            }
        }

        internal bool Zip {
            get {
                if (!_zipSet) {
                    _zip = HeaderUtility.IsEncodingInAcceptList(IPage.Request.Headers["Accept-encoding"], "gzip");
                    _zipSet = true;
                }
                return _zip;
            }
            set {
                _zip = value;
                _zipSet = true;
            }
        }

        [
        Category("Action"),
        ResourceDescription("ScriptManager_AsyncPostBackError")
        ]
        public event EventHandler<AsyncPostBackErrorEventArgs> AsyncPostBackError {
            add {
                Events.AddHandler(AsyncPostBackErrorEvent, value);
            }
            remove {
                Events.RemoveHandler(AsyncPostBackErrorEvent, value);
            }
        }

        [
        Category("Action"),
        ResourceDescription("ScriptManager_Navigate"),
        ]
        public event EventHandler<HistoryEventArgs> Navigate {
            add {
                Events.AddHandler(NavigateEvent, value);
            }
            remove {
                Events.RemoveHandler(NavigateEvent, value);
            }
        }

        [
        Category("Action"),
        ResourceDescription("ScriptManager_ResolveCompositeScriptReference"),
        ]
        public event EventHandler<CompositeScriptReferenceEventArgs> ResolveCompositeScriptReference {
            add {
                Events.AddHandler(ResolveCompositeScriptReferenceEvent, value);
            }
            remove {
                Events.RemoveHandler(ResolveCompositeScriptReferenceEvent, value);
            }
        }

        [
        Category("Action"),
        ResourceDescription("ScriptManager_ResolveScriptReference"),
        ]
        public event EventHandler<ScriptReferenceEventArgs> ResolveScriptReference {
            add {
                Events.AddHandler(ResolveScriptReferenceEvent, value);
            }
            remove {
                Events.RemoveHandler(ResolveScriptReferenceEvent, value);
            }
        }

        public void AddHistoryPoint(string key, string value) {
            AddHistoryPoint(key, value, null);
        }

        public void AddHistoryPoint(string key, string value, string title) {
            PrepareNewHistoryPoint();
            SetStateValue(key, value);
            SetPageTitle(title);
        }

        public void AddHistoryPoint(NameValueCollection state, string title) {
            PrepareNewHistoryPoint();
            foreach (string key in state) {
                SetStateValue(key, state[key]);
            }
            SetPageTitle(title);
        }

        private void AddFrameworkLoadedCheck() {
            // Add check for Sys to give better error message when the framework failed to load.
            IPage.ClientScript.RegisterClientScriptBlock(typeof(ScriptManager), "FrameworkLoadedCheck",
                ClientScriptManager.ClientScriptStart + "if (typeof(Sys) === 'undefined') throw new Error('" +
                HttpUtility.JavaScriptStringEncode(AtlasWeb.ScriptManager_FrameworkFailedToLoad) +
                "');\r\n" + ClientScriptManager.ClientScriptEnd,
                addScriptTags: false);
        }

        private ScriptReferenceBase AddFrameworkScript(ScriptReference frameworkScript, List<ScriptReferenceBase> scripts, bool webFormsWithoutAjax) {
            int scriptIndex = 0;
            ScriptReferenceBase frameworkScriptBase = frameworkScript;
            // PERF: If scripts.Count <= scriptIndex, then there are no user-specified scripts that might match
            // the current framework script, so we don't even need to look, except for composite references.
            if (scripts.Count != 0) {
                // For each framework script we want to register, try to find it in the list of user-specified scripts.
                // If it's there, move it to the top of the list. If it's not there, add it with our default settings.
                // If multiple user-specified scripts match a framework script, the first one is moved to the top
                // of the list, and later ones will be removed via RemoveDuplicates().

                // In the scenarios when MicrosoftWebForms.js is used (partial rendering is enabled), and MicrosoftAjax.js
                // is disabled, MicrosoftWebForms.js cannot be used unless the users define and registere beforehand 
                // some equivalant script to MicrosoftAjax.js. So if there is MicrosoftWebForms.js in the list of 
                // user-specified scripts, we take no action and respect the order of the scripts that the users 
                // specified. Otherwise, we insert MicrosoftWebForms.js at the end of the user-specified script list.
                string frameworkScriptName = frameworkScript.EffectiveResourceName;
                string frameworkScriptPath = null;
                if (String.IsNullOrEmpty(frameworkScriptName)) {
                    frameworkScriptPath = frameworkScript.EffectivePath;
                }
                Assembly frameworkAssembly = frameworkScript.GetAssembly(this);
                for (int i = 0; i < scripts.Count; i++) {
                    ScriptReferenceBase script = scripts[i];
                    ScriptReference sr = script as ScriptReference;
                    if ((sr != null) &&
                        ((!String.IsNullOrEmpty(frameworkScriptName) &&
                        (sr.EffectiveResourceName == frameworkScriptName)) &&
                        (sr.GetAssembly(this) == frameworkAssembly) ||
                        (!String.IsNullOrEmpty(frameworkScriptPath) &&
                        sr.ScriptInfo.Path == frameworkScriptPath))) {

                        // If the found script is already on the top of the list, we dont need to remove then insert it back.
                        if (webFormsWithoutAjax || (i == 0)) {
                            script.AlwaysLoadBeforeUI = true;
                            return script;
                        }

                        frameworkScriptBase = script;
                        scripts.Remove(script);
                        break;
                    }
                    else {
                        CompositeScriptReference csr = script as CompositeScriptReference;
                        if (csr != null) {
                            bool found = false;
                            foreach (ScriptReference scriptReference in csr.Scripts) {
                                if (((!String.IsNullOrEmpty(frameworkScriptName) &&
                                    (scriptReference.EffectiveResourceName == frameworkScriptName)) &&
                                    (scriptReference.GetAssembly(this) == frameworkAssembly) ||
                                    (!String.IsNullOrEmpty(frameworkScriptPath) &&
                                    scriptReference.ScriptInfo.Path == frameworkScriptPath))) {

                                    // If the found script is already on the top of the list, we dont need to remove then insert it back.
                                    if (webFormsWithoutAjax || (i == 0)) {
                                        script.AlwaysLoadBeforeUI = true;
                                        return script;
                                    }
                                    // Even composite references are moved to the top if they contain an fx script.
                                    frameworkScriptBase = script;
                                    scripts.Remove(script);
                                    found = true;
                                    break;
                                }
                            }
                            if (found) {
                                break;
                            }
                        }
                    }
                }
                if (webFormsWithoutAjax) {
                    scriptIndex = scripts.Count;
                }
            }

            frameworkScriptBase.AlwaysLoadBeforeUI = true;
            scripts.Insert(scriptIndex, frameworkScriptBase);
            return frameworkScriptBase;
        }

        // Called by ScriptManagerDesigner.GetScriptReferences()
        internal void AddFrameworkScripts(List<ScriptReferenceBase> scripts) {
            // The 0 and 1 scriptIndex parameter to AddFrameworkScript() is how
            // we guarantee that the Atlas framework scripts get inserted
            // consecutively as the first script to be registered. If we add
            // more optional framework scripts we will have to increment the index
            // dynamically for each script so that there are no gaps between the
            // Atlas scripts.
            // Add MicrosoftAjaxApplicationServices.js first,
            // then MicrosoftAjaxWebForms.js, then MicrosoftAjax.js. So that the insert index is always at 0.
            // This is to fix the issue in DevDiv 664653, where there is only one composite script with both
            // MicrosoftAjaxWebForms.js and MicrosoftAjax.js, and inserting at index 1 is out of bound.
            AjaxFrameworkMode mode = AjaxFrameworkMode;
            if (mode != AjaxFrameworkMode.Disabled) {
                _appServicesInitializationScript = GetApplicationServicesInitializationScript();
                // only add the script explicitly in enabled mode -- in explicit mode, we will
                // register the initialization script only after we find the reference that was included
                // explicitly.
                if ((mode == AjaxFrameworkMode.Enabled) && !String.IsNullOrEmpty(_appServicesInitializationScript)) {
                    ScriptReference appServices = new ScriptReference("MicrosoftAjaxApplicationServices.js", this, this);
                    _applicationServicesReference = AddFrameworkScript(appServices, scripts, false);
                }
            }
            if (SupportsPartialRendering && (mode != AjaxFrameworkMode.Disabled)) {
                ScriptReference atlasWebForms = new ScriptReference("MicrosoftAjaxWebForms.js", this, this);
                AddFrameworkScript(atlasWebForms, scripts, (AjaxFrameworkMode == AjaxFrameworkMode.Explicit));
            }
            if (mode == AjaxFrameworkMode.Enabled) {
                ScriptReference atlasCore = new ScriptReference("MicrosoftAjax.js", this, this);
                atlasCore.IsDefiningSys = true;
                _scriptPathsDefiningSys.Add(atlasCore.EffectivePath);
                AddFrameworkScript(atlasCore, scripts, false);
            }
        }

        // Add ScriptReferences from Scripts collections of ScriptManager and ScriptManagerProxies
        // Called by ScriptManagerDesigner.GetScriptReferences().
        internal void AddScriptCollections(List<ScriptReferenceBase> scripts, IEnumerable<ScriptManagerProxy> proxies) {
            if ((_compositeScript != null) && (_compositeScript.Scripts.Count != 0)) {
                _compositeScript.ClientUrlResolver = Control;
                _compositeScript.ContainingControl = this;
                _compositeScript.IsStaticReference = true;
                scripts.Add(_compositeScript);
            }
            // Register user-specified scripts from the ScriptManager
            // PERF: Use field directly to avoid creating List if not already created
            if (_scripts != null) {
                foreach (ScriptReference scriptReference in _scripts) {
                    // Fix for Dev11 Bug # 406984 : When user explicitly adds the MicrosoftAjax.[debug].js OR MicrosoftAjaxCore.[debug].js, we want to mark them as defining Sys so that
                    // we can register the FrameworkLoadedCheck scripts after them.
                    if (scriptReference.IsAjaxFrameworkScript(this) && (scriptReference.Name.StartsWith("MicrosoftAjax.", StringComparison.OrdinalIgnoreCase) || scriptReference.Name.StartsWith("MicrosoftAjaxCore.", StringComparison.OrdinalIgnoreCase))) {
                        scriptReference.IsDefiningSys = true;
                        _scriptPathsDefiningSys.Add(scriptReference.EffectivePath);
                    }
                    scriptReference.ClientUrlResolver = Control;
                    scriptReference.ContainingControl = this;
                    scriptReference.IsStaticReference = true;
                    scripts.Add(scriptReference);
                }
            }

            // Register user-specified scripts from ScriptManagerProxy controls, if any
            if (proxies != null) {
                foreach (ScriptManagerProxy proxy in proxies) {
                    proxy.CollectScripts(scripts);
                }
            }
        }

        internal string CreateUniqueScriptKey() {
            _uniqueScriptCounter++;
            return "UniqueScript_" + _uniqueScriptCounter.ToString(CultureInfo.InvariantCulture);
        }

        private string GetApplicationServicesInitializationScript() {
            StringBuilder sb = null;

            // Script that configures the application service proxies. For example setting the path properties.
            // If the services are disabled and none of the service manager properties are set, the sb will be null.
            ProfileServiceManager.ConfigureProfileService(ref sb, Context, this, _proxies);
            AuthenticationServiceManager.ConfigureAuthenticationService(ref sb, Context, this, _proxies);
            RoleServiceManager.ConfigureRoleService(ref sb, Context, this, _proxies);

            if (sb != null && sb.Length > 0) {
                return sb.ToString();
            }
            return null;
        }

        public static ScriptManager GetCurrent(Page page) {
            if (page == null) {
                throw new ArgumentNullException("page");
            }

            return page.Items[typeof(ScriptManager)] as ScriptManager;
        }

        // AspNetHostingPermission attributes must be copied to this method, to satisfy FxCop rule
        // CA2114:MethodSecurityShouldBeASupersetOfType.
        [
        ConfigurationPermission(SecurityAction.Assert, Unrestricted = true),
        SecurityCritical()
        ]
        private static ICustomErrorsSection GetCustomErrorsSectionWithAssert() {
            return new CustomErrorsSectionWrapper(
                (CustomErrorsSection)WebConfigurationManager.GetSection("system.web/customErrors"));
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Depends on registered resources so order of execution is important.")]
        public ReadOnlyCollection<RegisteredArrayDeclaration> GetRegisteredArrayDeclarations() {
            return new ReadOnlyCollection<RegisteredArrayDeclaration>(ScriptRegistration.ScriptArrays);
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Depends on registered resources so order of execution is important.")]
        public ReadOnlyCollection<RegisteredScript> GetRegisteredClientScriptBlocks() {
            // includes RegisterClientScriptBlock, RegisterClientScriptInclude, RegisterClientScriptResource
            return new ReadOnlyCollection<RegisteredScript>(ScriptRegistration.ScriptBlocks);
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Depends on registered resources so order of execution is important.")]
        public ReadOnlyCollection<RegisteredDisposeScript> GetRegisteredDisposeScripts() {
            return new ReadOnlyCollection<RegisteredDisposeScript>(ScriptRegistration.ScriptDisposes);
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Depends on registered resources so order of execution is important.")]
        public ReadOnlyCollection<RegisteredExpandoAttribute> GetRegisteredExpandoAttributes() {
            return new ReadOnlyCollection<RegisteredExpandoAttribute>(ScriptRegistration.ScriptExpandos);
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Depends on registered resources so order of execution is important.")]
        public ReadOnlyCollection<RegisteredHiddenField> GetRegisteredHiddenFields() {
            return new ReadOnlyCollection<RegisteredHiddenField>(ScriptRegistration.ScriptHiddenFields);
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Depends on registered resources so order of execution is important.")]
        public ReadOnlyCollection<RegisteredScript> GetRegisteredOnSubmitStatements() {
            return new ReadOnlyCollection<RegisteredScript>(ScriptRegistration.ScriptSubmitStatements);
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Depends on registered resources so order of execution is important.")]
        public ReadOnlyCollection<RegisteredScript> GetRegisteredStartupScripts() {
            return new ReadOnlyCollection<RegisteredScript>(ScriptRegistration.ScriptStartupBlocks);
        }

        internal string GetScriptResourceUrl(string resourceName, Assembly assembly) {
            return ScriptResourceHandler.GetScriptResourceUrl(
                assembly,
                resourceName,
                (EnableScriptLocalization ? CultureInfo.CurrentUICulture : CultureInfo.InvariantCulture),
                Zip);
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
            Justification = "Getting the state string is a heavy operation.")]
        public string GetStateString() {
            if (EnableSecureHistoryState) {
                StatePersister persister = new StatePersister(Page);
                return persister.Serialize(_initialState);
            }
            else if (_initialState == null) {
                return String.Empty;
            }
            else {
                StringBuilder sb = new StringBuilder();
                bool first = true;
                foreach (DictionaryEntry kvp in _initialState) {
                    if (!first) {
                        sb.Append('&');
                    }
                    else {
                        first = false;
                    }
                    sb.Append(HttpUtility.UrlEncode((string)kvp.Key));
                    sb.Append('=');
                    sb.Append(HttpUtility.UrlEncode((string)kvp.Value));
                }
                return sb.ToString();
            }
        }

        private void LoadHistoryState(string serverState) {
            NameValueCollection state;
            if (String.IsNullOrEmpty(serverState)) {
                _initialState = new Hashtable(StringComparer.Ordinal);
                state = new NameValueCollection();
            }
            else if (EnableSecureHistoryState) {
                StatePersister persister = new StatePersister(Page);
                _initialState = (Hashtable)persister.Deserialize(serverState);

                state = new NameValueCollection();
                foreach (DictionaryEntry entry in _initialState) {
                    state.Add((string)entry.Key, (string)entry.Value);
                }
            }
            else {
                state = HttpUtility.ParseQueryString(serverState);
                _initialState = new Hashtable(state.Count, StringComparer.Ordinal);

                foreach (string key in state) {
                    _initialState.Add(key, state[key]);
                }
            }
            HistoryEventArgs args = new HistoryEventArgs(state);
            RaiseNavigate(args);
        }

        protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) {
            if (IsInAsyncPostBack) {
                PageRequestManager.LoadPostData(postDataKey, postCollection);
            }
            else if (EnableHistory && (AjaxFrameworkMode != AjaxFrameworkMode.Disabled)) {
                // get current state string if it exists
                string serverState = postCollection[postDataKey];
                LoadHistoryState(serverState);
            }

            return false;
        }

        private bool NeedToLoadBeforeUI(ScriptReference script, AjaxFrameworkMode ajaxMode) {
            return script.IsFromSystemWeb() ||
                (ajaxMode == AjaxFrameworkMode.Explicit &&
                (script.IsAjaxFrameworkScript(this) && SplitFrameworkScripts.Contains(script.EffectiveResourceName)));
        }

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
        protected internal virtual void OnAsyncPostBackError(AsyncPostBackErrorEventArgs e) {
            EventHandler<AsyncPostBackErrorEventArgs> handler =
                (EventHandler<AsyncPostBackErrorEventArgs>)Events[AsyncPostBackErrorEvent];
            if (handler != null) {
                handler(this, e);
            }
        }

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
        protected internal override void OnInit(EventArgs e) {
            base.OnInit(e);

            if (!DesignMode) {
                // Ensure the current ajax framework assembly has a higher version number than System.Web.Extensions.
                Assembly ajaxFrameworkAssembly = AjaxFrameworkAssembly;
                if ((ajaxFrameworkAssembly != null) && (ajaxFrameworkAssembly != AssemblyCache.SystemWebExtensions)) {
                    if (AssemblyCache.GetVersion(ajaxFrameworkAssembly) <=
                        AssemblyCache.GetVersion(AssemblyCache.SystemWebExtensions)) {
                        // Must have a higher version number
                        throw new InvalidOperationException(
                            String.Format(CultureInfo.CurrentUICulture, AtlasWeb.ScriptManager_MustHaveGreaterVersion,
                                ajaxFrameworkAssembly, AssemblyCache.GetVersion(AssemblyCache.SystemWebExtensions)));
                    }
                }

                IPage page = IPage;
                ScriptManager existingInstance = ScriptManager.GetCurrent(Page);

                if (existingInstance != null) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_OnlyOneScriptManager);
                }
                page.Items[typeof(IScriptManager)] = this;
                page.Items[typeof(ScriptManager)] = this;

                page.InitComplete += OnPageInitComplete;
                page.PreRenderComplete += OnPagePreRenderComplete;

                if (page.IsPostBack) {
                    _isInAsyncPostBack = PageRequestManager.IsAsyncPostBackRequest(page.Request);
                }

                // Delegate to PageRequestManager to hook up error handling for async posts
                PageRequestManager.OnInit();

                page.PreRender += ScriptControlManager.OnPagePreRender;
            }
        }

        private void RaiseNavigate(HistoryEventArgs e) {
            EventHandler<HistoryEventArgs> handler = (EventHandler<HistoryEventArgs>)Events[NavigateEvent];
            if (handler != null) {
                handler(this, e);
            }
            foreach (ScriptManagerProxy proxy in Proxies) {
                handler = proxy.NavigateEvent;
                if (handler != null) {
                    handler(this, e);
                }
            }
        }

        private void OnPagePreRenderComplete(object sender, EventArgs e) {
            _preRenderCompleted = true;
            if (!IsInAsyncPostBack) {
                if (SupportsPartialRendering && (AjaxFrameworkMode != AjaxFrameworkMode.Disabled)) {
                    // Force ASP.NET to include the __doPostBack function. If we don't do
                    // this then on the client we might not be able to override the function
                    // (since it won't be defined).
                    // We also need to force it to include the ASP.NET WebForms.js since it
                    // has other required functionality.
                    IPage.ClientScript.GetPostBackEventReference(new PostBackOptions(this, null, null, false, false, false, false, true, null));
                }
                // on GET request we register the glob block...
                RegisterGlobalizationScriptBlock();
                // all script references, declared and from script controls...
                RegisterScripts();
                // and all service references.
                RegisterServices();
            }
            else {
                // on async postbacks we only need to register script control references and inline references.
                RegisterScripts();
                if (EnableHistory && (AjaxFrameworkMode != AjaxFrameworkMode.Disabled)) {
                    // Send empty object as null to the client
                    if ((_initialState != null) && (_initialState.Count == 0)) {
                        _initialState = null;
                    }
                    if (_newPointCreated) {
                        RegisterDataItem(this, GetStateString(), false);
                    }
                }
            }
        }

        private void OnPageInitComplete(object sender, EventArgs e) {
            if (IPage.IsPostBack) {
                if (IsInAsyncPostBack && !SupportsPartialRendering) {
                    throw new InvalidOperationException(AtlasWeb.ScriptManager_AsyncPostBackNotInPartialRenderingMode);
                }
            }

            _initCompleted = true;

            if (EnableHistory && (AjaxFrameworkMode != AjaxFrameworkMode.Disabled)) {
                RegisterAsyncPostBackControl(this);
                if (IPage.IsPostBack) {
                    // Currently navigation is the only postback that ScriptManager handles
                    // so we can assume that if the event target is the script manager, then
                    // we're navigating.
                    _isNavigating = IPage.Request[System.Web.UI.Page.postEventSourceID] == this.UniqueID;
                }
            }
        }

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
        protected internal override void OnPreRender(EventArgs e) {
            base.OnPreRender(e);

            if (IsInAsyncPostBack) {
                PageRequestManager.OnPreRender();
            }
        }

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
        protected virtual void OnResolveCompositeScriptReference(CompositeScriptReferenceEventArgs e) {
            EventHandler<CompositeScriptReferenceEventArgs> handler =
                (EventHandler<CompositeScriptReferenceEventArgs>)Events[ResolveCompositeScriptReferenceEvent];
            if (handler != null) {
                handler(this, e);
            }
        }

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
        protected virtual void OnResolveScriptReference(ScriptReferenceEventArgs e) {
            EventHandler<ScriptReferenceEventArgs> handler =
                (EventHandler<ScriptReferenceEventArgs>)Events[ResolveScriptReferenceEvent];
            if (handler != null) {
                handler(this, e);
            }
        }

        private void PrepareNewHistoryPoint() {
            if (!EnableHistory) {
                throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotAddHistoryPointWithHistoryDisabled);
            }
            if (!IsInAsyncPostBack) {
                throw new InvalidOperationException(AtlasWeb.ScriptManager_CannotAddHistoryPointOutsideOfAsyncPostBack);
            }
            _newPointCreated = true;
            if (_initialState == null) {
                _initialState = new Hashtable(StringComparer.Ordinal);
            }
        }

        [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate",
            Justification = "Matches IPostBackEventHandler interface.")]
        protected virtual void RaisePostBackEvent(string eventArgument) {
            LoadHistoryState(eventArgument);
        }

        [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate",
            Justification = "Matches IPostBackDataHandler interface.")]
        protected virtual void RaisePostDataChangedEvent() {
        }

        // 




        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The overload specifically exists to strengthen the support for passing in a Page parameter.")]
        public static void RegisterArrayDeclaration(Page page, string arrayName, string arrayValue) {
            ScriptRegistrationManager.RegisterArrayDeclaration(page, arrayName, arrayValue);
        }

        public static void RegisterArrayDeclaration(Control control, string arrayName, string arrayValue) {
            ScriptRegistrationManager.RegisterArrayDeclaration(control, arrayName, arrayValue);
        }

        // Registers a control as causing an async postback instead of a regular postback
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
        public void RegisterAsyncPostBackControl(Control control) {
            PageRequestManager.RegisterAsyncPostBackControl(control);
        }

        // Internal virtual for testing.  Cannot mock static RegisterClientScriptBlock().
        internal virtual void RegisterClientScriptBlockInternal(Control control, Type type, string key, string script, bool addScriptTags) {
            RegisterClientScriptBlock(control, type, key, script, addScriptTags);
        }

        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The overload specifically exists to strengthen the support for passing in a Page parameter.")]
        public static void RegisterClientScriptBlock(Page page, Type type, string key, string script, bool addScriptTags) {
            ScriptRegistrationManager.RegisterClientScriptBlock(page, type, key, script, addScriptTags);
        }

        public static void RegisterClientScriptBlock(Control control, Type type, string key, string script, bool addScriptTags) {
            ScriptRegistrationManager.RegisterClientScriptBlock(control, type, key, script, addScriptTags);
        }

        // Internal virtual for testing.  Cannot mock static RegisterClientScriptInclude().
        internal virtual void RegisterClientScriptIncludeInternal(Control control, Type type, string key, string url) {
            RegisterClientScriptInclude(control, type, key, url);
        }

        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "Needs to take same parameters as ClientScriptManager.RegisterClientScriptInclude()." +
            "We could provide an overload that takes a System.Uri parameter, but then FxCop rule " +
            "StringUriOverloadsCallSystemUriOverloads would require that the string overload call the Uri overload. " +
            "But we cannot do this, because the ClientScriptManager API allows any string, even invalid Uris. " +
            "We cannot start throwing exceptions on input we previously passed to the browser. So it does not make " +
            "sense to add an overload that takes System.Uri.")]
        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The overload specifically exists to strengthen the support for passing in a Page parameter.")]
        public static void RegisterClientScriptInclude(Page page, Type type, string key, string url) {
            ScriptRegistrationManager.RegisterClientScriptInclude(page, type, key, url);
        }

        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "Needs to take same parameters as ClientScriptManager.RegisterClientScriptInclude()." +
            "We could provide an overload that takes a System.Uri parameter, but then FxCop rule " +
            "StringUriOverloadsCallSystemUriOverloads would require that the string overload call the Uri overload. " +
            "But we cannot do this, because the ClientScriptManager API allows any string, even invalid Uris. " +
            "We cannot start throwing exceptions on input we previously passed to the browser. So it does not make " +
            "sense to add an overload that takes System.Uri.")]
        public static void RegisterClientScriptInclude(Control control, Type type, string key, string url) {
            ScriptRegistrationManager.RegisterClientScriptInclude(control, type, key, url);
        }

        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The overload specifically exists to strengthen the support for passing in a Page parameter.")]
        public static void RegisterClientScriptResource(Page page, Type type, string resourceName) {
            ScriptRegistrationManager.RegisterClientScriptResource(page, type, resourceName);
        }

        public static void RegisterClientScriptResource(Control control, Type type, string resourceName) {
            ScriptRegistrationManager.RegisterClientScriptResource(control, type, resourceName);
        }

        // Only if we have a script manager on the page and we can resolve a path for the resource definition 
        // then can we add it to the script definitions so script references will be de-duped
        private static bool TryRegisterNamedClientScriptResourceUsingScriptReference(Page page, string resourceName) {
            if (page != null) {
                ScriptManager sm = GetCurrent(page);
                ScriptResourceDefinition def = ScriptManager.ScriptResourceMapping.GetDefinition(resourceName);
                if (sm != null && def != null) {
                        sm.Scripts.Add(new ScriptReference() { Name = resourceName });
                        return true;
                }
            }

            return false;
        }

        public static void RegisterNamedClientScriptResource(Control control, string resourceName) {
            // Try to use ScriptManager Scripts collection if we can(for de-dupe logic), otherwise fall back to RegisterClientScriptResource
            if (control != null && TryRegisterNamedClientScriptResourceUsingScriptReference(control.Page, resourceName)) {
                return;
            }
            RegisterClientScriptResource(control, typeof(ScriptManager), resourceName);
        }

        public static void RegisterNamedClientScriptResource(Page page, string resourceName) {
            // Try to use ScriptManager Scripts collection if we can(for de-dupe logic), otherwise fall back to RegisterClientScriptResource
            if (TryRegisterNamedClientScriptResourceUsingScriptReference(page, resourceName)) {
                return;
            }
            RegisterClientScriptResource(page, typeof(ScriptManager), resourceName);
        }

        public void RegisterDataItem(Control control, string dataItem) {
            RegisterDataItem(control, dataItem, false);
        }

        public void RegisterDataItem(Control control, string dataItem, bool isJsonSerialized) {
            PageRequestManager.RegisterDataItem(control, dataItem, isJsonSerialized);
        }

        public void RegisterDispose(Control control, string disposeScript) {
            if (SupportsPartialRendering && (AjaxFrameworkMode != AjaxFrameworkMode.Disabled)) {
                // DevDiv Bugs 124041: Do not register if SupportsPartialRendering=false
                // It would cause a script error since PageRequestManager will not exist on the client.
                ScriptRegistration.RegisterDispose(control, disposeScript);
            }
        }

        public static void RegisterExpandoAttribute(Control control, string controlId, string attributeName, string attributeValue, bool encode) {
            ScriptRegistrationManager.RegisterExpandoAttribute(control, controlId, attributeName, attributeValue, encode);
        }

        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
        public void RegisterExtenderControl<TExtenderControl>(TExtenderControl extenderControl, Control targetControl)
            where TExtenderControl : Control, IExtenderControl {
            ScriptControlManager.RegisterExtenderControl(extenderControl, targetControl);
        }

        private void RegisterGlobalizationScriptBlock() {
            if (EnableScriptGlobalization && (AjaxFrameworkMode != AjaxFrameworkMode.Disabled)) {
                Tuple<String, String> entry = ClientCultureInfo.GetClientCultureScriptBlock(CultureInfo.CurrentCulture);
                if ((entry != null) && !String.IsNullOrEmpty(entry.Item1)) {
                    if (IsDebuggingEnabled && (AjaxFrameworkMode == AjaxFrameworkMode.Explicit)) {
                        string script = "Type._checkDependency('MicrosoftAjaxGlobalization.js', 'ScriptManager.EnableScriptGlobalization');\r\n";
                        ScriptRegistrationManager.RegisterStartupScript(this, typeof(ScriptManager), "CultureInfoScriptCheck", script, true);
                    }
                    ScriptRegistrationManager.RegisterClientScriptBlock(this, typeof(ScriptManager), "CultureInfo", entry.Item1, true);
                    if (!String.IsNullOrEmpty(entry.Item2)) {
                        ScriptReference reference = new ScriptReference(entry.Item2, null);
#pragma warning disable 618
                        // ScriptPath is obsolete but still functional
                        reference.IgnoreScriptPath = true;
#pragma warning restore 618
                        reference.AlwaysLoadBeforeUI = true;
                        // added to Script collection instead of directly registered so that it goes through
                        // script resolution, and is resolved for debug/release version, etc.
                        // It can also be explicitly declared to customize it.
                        // e.g. <asp:ScriptReference Name="Date.HijriCalendar.js" Path="foo.js"/>
                        Scripts.Add(reference);
                    }
                }
            }
        }

        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The overload specifically exists to strengthen the support for passing in a Page parameter.")]
        public static void RegisterHiddenField(Page page, string hiddenFieldName, string hiddenFieldInitialValue) {
            ScriptRegistrationManager.RegisterHiddenField(page, hiddenFieldName, hiddenFieldInitialValue);
        }

        public static void RegisterHiddenField(Control control, string hiddenFieldName, string hiddenFieldInitialValue) {
            ScriptRegistrationManager.RegisterHiddenField(control, hiddenFieldName, hiddenFieldInitialValue);
        }

        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The overload specifically exists to strengthen the support for passing in a Page parameter.")]
        public static void RegisterOnSubmitStatement(Page page, Type type, string key, string script) {
            ScriptRegistrationManager.RegisterOnSubmitStatement(page, type, key, script);
        }

        public static void RegisterOnSubmitStatement(Control control, Type type, string key, string script) {
            ScriptRegistrationManager.RegisterOnSubmitStatement(control, type, key, script);
        }

        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
        public void RegisterScriptControl<TScriptControl>(TScriptControl scriptControl)
            where TScriptControl : Control, IScriptControl {
            ScriptControlManager.RegisterScriptControl(scriptControl);
        }

        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
        public void RegisterScriptDescriptors(IExtenderControl extenderControl) {
            ScriptControlManager.RegisterScriptDescriptors(extenderControl);
        }

        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
        public void RegisterScriptDescriptors(IScriptControl scriptControl) {
            ScriptControlManager.RegisterScriptDescriptors(scriptControl);
        }

        // Registers a control as causing a regular postback instead of an async postback
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
        public void RegisterPostBackControl(Control control) {
            PageRequestManager.RegisterPostBackControl(control);
        }

        private static string GetEffectivePath(ScriptReferenceBase scriptRef) {
            string effectivePath = scriptRef.Path;
            if (String.IsNullOrEmpty(effectivePath)) {
                // Also try using Effective path for ScriptReferences, which is the case for framework scripts
                ScriptReference sref = scriptRef as ScriptReference;
                if (sref != null) {
                    effectivePath = sref.EffectivePath;
                }
            }
            return effectivePath;
        }

        // If bundling is supported, look for references to bundles, eliminate duplicates, and get the true bundle url for the reference
        internal List<ScriptReferenceBase> ProcessBundleReferences(List<ScriptReferenceBase> scripts) {
            // If we have a bundle resolver, look through all the scripts and see which are bundles
            object resolver = BundleReflectionHelper.BundleResolver;
            if (resolver != null) {
                HashSet<string> virtualPathsInBundles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

                // For each bundle, expand and remember every path inside
                foreach (ScriptReferenceBase scriptRef in scripts) {
                    string effectivePath = GetEffectivePath(scriptRef);
                    if (BundleReflectionHelper.IsBundleVirtualPath(effectivePath)) {
                        scriptRef.IsBundleReference = true;

                        IEnumerable<string> bundleContents = BundleReflectionHelper.GetBundleContents(effectivePath);
                        if (bundleContents != null) {
                            foreach (string path in bundleContents) {
                                virtualPathsInBundles.Add(path);
                                if (_scriptPathsDefiningSys.Contains(path)) {
                                    scriptRef.IsDefiningSys = true;
                                }
                            }
                        }
                    }
                }

                // No bundles so we are done
                if (virtualPathsInBundles.Count == 0) {
                    return scripts;
                }

                // Go through the scripts and remove any references to scripts inside of bundles
                List<ScriptReferenceBase> collapsedReferences = new List<ScriptReferenceBase>();
                foreach (ScriptReferenceBase scriptRef in scripts) {
                    string effectivePath = GetEffectivePath(scriptRef);
                    if (scriptRef.IsBundleReference) {
                        collapsedReferences.Add(scriptRef);
                    }
                    else {
                        if (!virtualPathsInBundles.Contains(effectivePath)) {
                            collapsedReferences.Add(scriptRef);
                        }
                    }
                }

                return collapsedReferences;
            }

            return scripts;
        }

        private void RegisterScripts() {
            List<ScriptReferenceBase> scripts = new List<ScriptReferenceBase>();

            // Add ScriptReferences from Scripts collections of ScriptManager and ScriptManagerProxies
            // PERF: Use _proxies field directly to avoid creating List if not already created
            AddScriptCollections(scripts, _proxies);

            // Add ScriptReferences registered by ScriptControls and ExtenderControls
            ScriptControlManager.AddScriptReferences(scripts);

            // Inject Atlas Framework scripts
            AddFrameworkScripts(scripts);

            // Allow custom resolve work to happen
            foreach (ScriptReferenceBase script in scripts) {
                ScriptReference sr = script as ScriptReference;
                if (sr != null) {
                    OnResolveScriptReference(new ScriptReferenceEventArgs(sr));
                }
                else {
                    CompositeScriptReference csr = script as CompositeScriptReference;
                    if (csr != null) {
                        OnResolveCompositeScriptReference(new CompositeScriptReferenceEventArgs(csr));
                    }
                }
            }
            // Remove duplicate Name+Assembly references
            List<ScriptReferenceBase> uniqueScripts = RemoveDuplicates(scripts, AjaxFrameworkMode,
                                LoadScriptsBeforeUI, (IsInAsyncPostBack ? null : IPage.ClientScript),
                                ref _applicationServicesReference);

            // Remove any scripts that are contained inside of any bundles
            uniqueScripts = ProcessBundleReferences(uniqueScripts);

            // Register the final list of unique scripts
            RegisterUniqueScripts(uniqueScripts);
        }

        private void RegisterUniqueScripts(List<ScriptReferenceBase> uniqueScripts) {
            bool loadCheckRegistered = !(IsDebuggingEnabled && !IsInAsyncPostBack);
            bool hasAppServicesScript = !String.IsNullOrEmpty(_appServicesInitializationScript);
            bool loadScriptsBeforeUI = this.LoadScriptsBeforeUI;
            AjaxFrameworkMode mode = AjaxFrameworkMode;
            foreach (ScriptReferenceBase script in uniqueScripts) {
                string url = script.GetUrl(this, Zip);
                string key = url;
                if (loadScriptsBeforeUI || script.AlwaysLoadBeforeUI) {
                    RegisterClientScriptIncludeInternal(script.ContainingControl, typeof(ScriptManager), key, url);
                }
                else {
                    // this method of building the script tag matches exactly ClientScriptManager.RegisterClientScriptInclude
                    string scriptTag = "\r\n<script src=\"" + HttpUtility.HtmlAttributeEncode(url) + "\" type=\"text/javascript\"></script>";
                    RegisterStartupScriptInternal(script.ContainingControl, typeof(ScriptManager), url, scriptTag, false);
                }

                RegisterFallbackScript(script, key);

                // configure app services and check framework right after framework script is included & before other scripts
                if ((!loadCheckRegistered || hasAppServicesScript) && script.IsAjaxFrameworkScript(this) && (mode != AjaxFrameworkMode.Disabled)) {
                    // In debug mode, detect if the framework loaded properly before we reference Sys in any way.
                    if (!loadCheckRegistered && script.IsDefiningSys) {
                        AddFrameworkLoadedCheck();
                        loadCheckRegistered = true;
                    }

                    if (hasAppServicesScript && (script == _applicationServicesReference)) {
                        this.IPage.ClientScript.RegisterClientScriptBlock(typeof(ScriptManager),
                            "AppServicesConfig",
                            _appServicesInitializationScript,
                            true);
                        hasAppServicesScript = false;
                    }
                }
            }
            // note: in explicit mode it is possible at this point that hasAppServicesScript is still true
            // because the dev did not reference appservices.js. By design, we will treat this scenario
            // as if app services are not intended to be used.
            // In Enabled mode it isn't possible that the script is not included and there is init script,
            // because we add it if it doesn't already exist.
        }

        /// <summary>
        /// Registers a script that causes the local copy of a script to load in the event the Cdn is unavailable.
        /// </summary>
        /// <param name="script"></param>
        private void RegisterFallbackScript(ScriptReferenceBase script, string key) {
            if (!EnableCdn || !EnableCdnFallback) {
                return;
            }

            // If we are using Cdn, register a fallback script for the ScriptReference it is available.
            var scriptReference = script as ScriptReference;
            if (scriptReference != null) {
                var scriptInfo = scriptReference.ScriptInfo;
                if (!String.IsNullOrEmpty(scriptInfo.LoadSuccessExpression)) {
                    string fallbackPath = scriptReference.GetUrlInternal(this, Zip, useCdnPath: false);
                    if (String.IsNullOrEmpty(fallbackPath)) {
                        return;
                    }

                    if (_isInAsyncPostBack) {
                        // For async postbacks, we need to register the script with the ScriptRegistrationManager. document.write won't work.
                        ScriptRegistrationManager.RegisterFallbackScriptForAjaxPostbacks(script.ContainingControl, typeof(ScriptManager),
                            key, scriptInfo.LoadSuccessExpression, fallbackPath);
                    }
                    else {
                        RegisterClientScriptBlockInternal(script.ContainingControl, typeof(ScriptManager), scriptInfo.LoadSuccessExpression,
                            String.Format(CultureInfo.InvariantCulture, "({0})||document.write('<script type=\"text/javascript\" src=\"{1}\"><\\/script>');", scriptInfo.LoadSuccessExpression, fallbackPath),
                            addScriptTags: true);
                    }
                }
            }
        }

        private void RegisterServices() {
            // Do not attempt to resolve inline service references on PageMethod requests.
            if (_services != null) {
                foreach (ServiceReference serviceReference in _services) {
                    serviceReference.Register(this, this);
                }
            }

            if (_proxies != null) {
                foreach (ScriptManagerProxy proxy in _proxies) {
                    proxy.RegisterServices(this);
                }
            }

            if (EnablePageMethods) {
                string pageMethods = PageClientProxyGenerator.GetClientProxyScript(Context, IPage, IsDebuggingEnabled);
                if (!String.IsNullOrEmpty(pageMethods)) {
                    RegisterClientScriptBlockInternal(this, typeof(ScriptManager), pageMethods, pageMethods, true);
                }
            }
        }

        private static void RegisterResourceWithClientScriptManager(IClientScriptManager clientScriptManager, Assembly assembly, String key) {
            // Tells the ClientScriptManager that ScriptManager has registered an assembly resource, 'key' from 'assembly',
            // so that it does not register it again if it were registered with RegisterClientScriptResource. This allows
            // script references to override them, allowing devs to take advantage of setting a 'path' to override them or
            // to use ScriptCombining to combine them.
            // RegisteredResourcesToSuppress is a Dictionary of Dictionaries. The outer dictionary key is assembly,
            // the inner key is resource.
            Dictionary<Assembly, Dictionary<String, Object>> suppressedResources = clientScriptManager.RegisteredResourcesToSuppress;
            Debug.Assert(suppressedResources != null, "ClientScriptManager.RegisteredResourcesToSuppress is not expected to return null.");
            Dictionary<String, Object> resourcesForAssembly;
            if (!suppressedResources.TryGetValue(assembly, out resourcesForAssembly)) {
                resourcesForAssembly = new Dictionary<String, Object>();
                suppressedResources[assembly] = resourcesForAssembly;
            }
            resourcesForAssembly[key] = true;
        }

        // Called by ScriptManagerDesigner.GetScriptReferences().
        internal List<ScriptReferenceBase> RemoveDuplicates(List<ScriptReferenceBase> scripts,
            AjaxFrameworkMode ajaxFrameworkMode, bool loadScriptsBeforeUI, IClientScriptManager clientScriptManager,
            ref ScriptReferenceBase applicationServicesReference) {
            // ClientScriptManager.RegisterClientScriptInclude() does not register multiple scripts
            // with the same type and key.  We use the url as the key, so multiple scripts with
            // the same final url are handled by ClientScriptManager.  In ScriptManager, we only
            // need to remove ScriptReferences that we consider "the same" but that will generate
            // different urls.  For example, Name+Assembly+Path and Name+Assembly will generate
            // different urls, but we consider them to represent the same script.  For this purpose,
            // two scripts are considered "the same" iff Name is non-empty, and they have the same
            // Name and Assembly.

            // This method also removes all the script reference with name equals MicrosoftAjax.js and 
            // assembly equals System.Web.Extensions when MicrosoftAjax is disabled (MicrosoftAjaxMode == Disabled)

            // Scenario:
            // Two references from two new instances of the same component that are each in different
            // UpdatePanels, during an async post, where one update panel is updating and the other is not.
            // If we remove one of the references because we consider one a duplicate of the other, the
            // reference remaining may be for the control in the update panel that is not updating, and
            // it wouldn't be included (incorrectly).
            // So, references from components can only be considered duplicate against static
            // script references. The returned list may contain duplicates, but they will be duplicates
            // across script controls, which may potentially live in different update panels.
            // When rendering the partial update content, duplicate paths are handled and only one is output.

            // PERF: Optimize for the following common cases.
            // - One ScriptReference (i.e. MicrosoftAjax.js).
            // - Two unique ScriptReferences (i.e. MicrosoftAjax.js and MicrosoftAjaxWebForms.js).  It is
            //   unlikely there will be two non-unique ScriptReferences, since the first ScriptReference is always
            //   MicrosoftAjax.js.
            // - Reduced cost from 0.43% to 0.04% in ScriptManager\HelloWorld\Scenario.aspx.
            int numScripts = scripts.Count;
            if (ajaxFrameworkMode == AjaxFrameworkMode.Enabled) {
                if (numScripts == 1) {
                    ScriptReference script1 = scripts[0] as ScriptReference;
                    if (script1 != null) {
                        if (clientScriptManager != null) {
                            if (!String.IsNullOrEmpty(script1.EffectiveResourceName)) {
                                RegisterResourceWithClientScriptManager(clientScriptManager, script1.GetAssembly(this), script1.EffectiveResourceName);
                            }
                        }
                        return scripts;
                    }
                }
                else if (numScripts == 2) {
                    ScriptReference script1 = scripts[0] as ScriptReference;
                    ScriptReference script2 = scripts[1] as ScriptReference;
                    if ((script1 != null) && (script2 != null) &&
                        ((script1.EffectiveResourceName != script2.EffectiveResourceName) || (script1.Assembly != script2.Assembly))) {
                        if (clientScriptManager != null) {
                            if (!String.IsNullOrEmpty(script1.EffectiveResourceName)) {
                                RegisterResourceWithClientScriptManager(clientScriptManager, script1.GetAssembly(this), script1.EffectiveResourceName);
                            }
                            if (!String.IsNullOrEmpty(script2.EffectiveResourceName)) {
                                RegisterResourceWithClientScriptManager(clientScriptManager, script2.GetAssembly(this), script2.EffectiveResourceName);
                            }
                        }
                        return scripts;
                    }
                }
            }

            // PERF: HybridDictionary is significantly more performant than Dictionary<K,V>, since the number
            // of scripts will frequently be small.  Reduced cost from 1.49% to 0.43% in
            // ScriptManager\HelloWorld\Scenario.aspx.
            HybridDictionary uniqueScriptDict = new HybridDictionary(numScripts);
            List<ScriptReferenceBase> filteredScriptList = new List<ScriptReferenceBase>(numScripts);

            // CompositeScriptReferences are always included, so scan them first
            foreach (ScriptReferenceBase script in scripts) {
                var csr = script as CompositeScriptReference;
                if (csr != null) {
                    bool loadBeforeUI = false;
                    foreach (ScriptReference sr in csr.Scripts) {
                        // Previously, we weren't removing duplicate path-based scripts
                        // because the script registration was using the url as the key,
                        // which resulted in duplicates effectively being removed later.
                        // With composite script references, this ceases to be true.
                        Tuple<string, Assembly> key = (String.IsNullOrEmpty(sr.EffectiveResourceName)) ?
                            new Tuple<string, Assembly>(sr.EffectivePath, null) :
                            new Tuple<string, Assembly>(sr.EffectiveResourceName, sr.GetAssembly(this));
                        if (uniqueScriptDict.Contains(key)) {
                            // A script reference declared multiple times in one or 
                            // multiple composite script references throws.
                            throw new InvalidOperationException(
                                AtlasWeb.ScriptManager_CannotRegisterScriptInMultipleCompositeReferences);
                        }
                        else {
                            if ((clientScriptManager != null) && (key.Item2 != null)) {
                                // its a resource script, tell ClientScriptManager about it so it suppresses any
                                // calls to RegisterClientScriptResource
                                RegisterResourceWithClientScriptManager(clientScriptManager, key.Item2, key.Item1);
                            }
                            if ((ajaxFrameworkMode == AjaxFrameworkMode.Explicit) && sr.IsAjaxFrameworkScript(this) &&
                                (applicationServicesReference == null) &&
                                sr.EffectiveResourceName.StartsWith("MicrosoftAjaxApplicationServices.", StringComparison.Ordinal)) {
                                applicationServicesReference = csr;
                            }
                            if (!loadScriptsBeforeUI && !loadBeforeUI && NeedToLoadBeforeUI(sr, ajaxFrameworkMode)) {
                                csr.AlwaysLoadBeforeUI = true;
                                loadBeforeUI = true;
                            }
                            uniqueScriptDict.Add(key, sr);
                        }
                    }
                }
            }

            foreach (ScriptReferenceBase script in scripts) {
                var csr = script as CompositeScriptReference;
                if (csr != null) {
                    filteredScriptList.Add(csr);
                }
                else {
                    var sr = script as ScriptReference;
                    if (sr != null) {
                        Tuple<string, Assembly> key = (String.IsNullOrEmpty(sr.EffectiveResourceName)) ?
                            new Tuple<string, Assembly>(sr.EffectivePath, null) :
                            new Tuple<string, Assembly>(sr.EffectiveResourceName, sr.GetAssembly(this));
                        // skip over duplicates, and skip over MicrosoftAjax.[debug.].js if the mode is Explicit
                        if (!((ajaxFrameworkMode == AjaxFrameworkMode.Explicit) && sr.IsAjaxFrameworkScript(this) &&
                            (sr.EffectiveResourceName.StartsWith("MicrosoftAjax.", StringComparison.Ordinal))) && !uniqueScriptDict.Contains(key)) {
                            if (sr.IsStaticReference) {
                                // only static script references are compared against for duplicates.
                                uniqueScriptDict.Add(key, sr);
                            }
                            if ((ajaxFrameworkMode == AjaxFrameworkMode.Explicit) && sr.IsAjaxFrameworkScript(this) &&
                                (applicationServicesReference == null) &&
                                sr.EffectiveResourceName.StartsWith("MicrosoftAjaxApplicationServices.", StringComparison.Ordinal)) {
                                applicationServicesReference = sr;
                            }
                            if (!loadScriptsBeforeUI && NeedToLoadBeforeUI(sr, ajaxFrameworkMode)) {
                                sr.AlwaysLoadBeforeUI = true;
                            }
                            if ((clientScriptManager != null) && (key.Item2 != null)) {
                                // its a resource script, tell ClientScriptManager about it so it suppresses any
                                // calls to RegisterClientScriptResource
                                RegisterResourceWithClientScriptManager(clientScriptManager, key.Item2, key.Item1);
                            }
                            filteredScriptList.Add(sr);
                        }
                    }
                }
            }
            return filteredScriptList;
        }

        // Internal virtual for testing.  Cannot mock static RegisterStartupScript().
        internal virtual void RegisterStartupScriptInternal(Control control, Type type, string key, string script, bool addScriptTags) {
            RegisterStartupScript(control, type, key, script, addScriptTags);
        }

        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The overload specifically exists to strengthen the support for passing in a Page parameter.")]
        public static void RegisterStartupScript(Page page, Type type, string key, string script, bool addScriptTags) {
            ScriptRegistrationManager.RegisterStartupScript(page, type, key, script, addScriptTags);
        }

        public static void RegisterStartupScript(Control control, Type type, string key, string script, bool addScriptTags) {
            ScriptRegistrationManager.RegisterStartupScript(control, type, key, script, addScriptTags);
        }

        protected internal override void Render(HtmlTextWriter writer) {
            if (!IsInAsyncPostBack && (AjaxFrameworkMode != AjaxFrameworkMode.Disabled)) {
                if (!((IControl)this).DesignMode && SupportsPartialRendering) {
                    PageRequestManager.Render(writer);
                }

                if (EnableHistory && !DesignMode && (IPage != null)) {
                    // Render hidden field for the script manager
                    writer.AddAttribute(HtmlTextWriterAttribute.Type, "hidden");
                    writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
                    writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
                    writer.RenderBeginTag(HtmlTextWriterTag.Input);
                    writer.RenderEndTag();

                    // Render initialization script
                    // Dev10 540269: History startup script moved to directly rendered script so that
                    // (1) is occurs before the iframe is rendered
                    // (2) after the state hidden field
                    // A ClientScript block would violate #2, and StartupScript violates #1.
                    // Navigation handler remains as a StartupScript since the handler may be defined inline within the page.
                    JavaScriptSerializer serializer = new JavaScriptSerializer(new SimpleTypeResolver());
                    writer.Write(ClientScriptManager.ClientScriptStart);
                    if (IsDebuggingEnabled && (AjaxFrameworkMode == AjaxFrameworkMode.Explicit)) {
                        writer.WriteLine("Type._checkDependency('MicrosoftAjaxHistory.js', 'ScriptManager.EnableHistory');");
                    }
                    writer.Write("Sys.Application.setServerId(");
                    writer.Write(serializer.Serialize(ClientID));
                    writer.Write(", ");
                    writer.Write(serializer.Serialize(UniqueID));
                    writer.WriteLine(");");
                    if ((_initialState != null) && (_initialState.Count != 0)) {
                        writer.Write("Sys.Application.setServerState('");
                        writer.Write(HttpUtility.JavaScriptStringEncode(GetStateString()));
                        writer.WriteLine("');");
                    }
                    writer.WriteLine("Sys.Application._enableHistoryInScriptManager();");
                    writer.Write(ClientScriptManager.ClientScriptEnd);

                    if (!String.IsNullOrEmpty(ClientNavigateHandler)) {
                        string script = "Sys.Application.add_navigate(" + ClientNavigateHandler + ");";
                        ScriptManager.RegisterStartupScript(this, typeof(ScriptManager), "HistoryNavigate", script, true);
                    }

                    HttpBrowserCapabilitiesBase browserCaps = IPage.Request.Browser;
                    // Generating the iframe on the server-side allows access to its document
                    // without access denied errors. This enables the title to be updated in history.
                    // DevDiv 13920: Output the iframe even if it looks like IE8+ since it could be in a lower document mode
                    if (browserCaps.Browser.Equals("IE", StringComparison.OrdinalIgnoreCase)) {
                        // DevDivBugs 196735
                        // Empty page title causes us to name the first server history point after
                        // the last thing navigated to, which is the url of the frame. That shows some
                        // garbled characters in the history list in case it contains multibyte chars in IE. 
                        // We never want the page title to be empty.
                        if (String.IsNullOrEmpty(IPage.Title)) {
                            IPage.Title = AtlasWeb.ScriptManager_PageUntitled;
                        }
                        string iFrameUrl = (EmptyPageUrl.Length == 0) ?
                            ScriptResourceHandler.GetEmptyPageUrl(IPage.Title) :
                            EmptyPageUrl +
                                ((EmptyPageUrl.IndexOf('?') != -1) ? "&title=" : "?title=") +
                                IPage.Title;
                        writer.AddAttribute(HtmlTextWriterAttribute.Id, "__historyFrame");
                        writer.AddAttribute(HtmlTextWriterAttribute.Src, iFrameUrl);
                        writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
                        writer.RenderBeginTag(HtmlTextWriterTag.Iframe);
                        writer.RenderEndTag();
                    }
                }
            }
            base.Render(writer);
        }

        public void SetFocus(Control control) {
            PageRequestManager.SetFocus(control);
        }

        private void SetPageTitle(string title) {
            if ((Page != null) && (Page.Header != null)) {
                Page.Title = title;
            }
        }

        [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID")]
        public void SetFocus(string clientID) {
            PageRequestManager.SetFocus(clientID);
        }

        private void SetStateValue(string key, string value) {
            if (value == null) {
                if (_initialState.ContainsKey(key)) {
                    _initialState.Remove(key);
                }
            }
            else {
                if (_initialState.ContainsKey(key)) {
                    _initialState[key] = value;
                }
                else {
                    _initialState.Add(key, value);
                }
            }
        }

        #region IControl Members
        HttpContextBase IControl.Context {
            get {
                return new System.Web.HttpContextWrapper(Context);
            }
        }

        bool IControl.DesignMode {
            get {
                return DesignMode;
            }
        }
        #endregion

        #region IScriptManagerInternal Members
        void IScriptManagerInternal.RegisterProxy(ScriptManagerProxy proxy) {
            // Under normal circumstances a ScriptManagerProxy will only register once per page lifecycle.
            // However, a malicious page developer could trick a proxy into registering more than once,
            // and this is guarding against that.
            if (!Proxies.Contains(proxy)) {
                Proxies.Add(proxy);
            }
        }

        void IScriptManagerInternal.RegisterUpdatePanel(UpdatePanel updatePanel) {
            PageRequestManager.RegisterUpdatePanel(updatePanel);
        }

        void IScriptManagerInternal.UnregisterUpdatePanel(UpdatePanel updatePanel) {
            PageRequestManager.UnregisterUpdatePanel(updatePanel);
        }
        #endregion

        #region IPostBackDataHandler Members
        bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) {
            return LoadPostData(postDataKey, postCollection);
        }

        void IPostBackDataHandler.RaisePostDataChangedEvent() {
            RaisePostDataChangedEvent();
        }
        #endregion

        #region IPostBackEventHandler Members
        void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) {
            RaisePostBackEvent(eventArgument);
        }
        #endregion

        #region IScriptManager Members
        void IScriptManager.RegisterArrayDeclaration(Control control, string arrayName, string arrayValue) {
            RegisterArrayDeclaration(control, arrayName, arrayValue);
        }

        void IScriptManager.RegisterClientScriptBlock(Control control, Type type, string key, string script, bool addScriptTags) {
            RegisterClientScriptBlock(control, type, key, script, addScriptTags);
        }

        void IScriptManager.RegisterClientScriptInclude(Control control, Type type, string key, string url) {
            RegisterClientScriptInclude(control, type, key, url);
        }

        void IScriptManager.RegisterClientScriptResource(Control control, Type type, string resourceName) {
            RegisterClientScriptResource(control, type, resourceName);
        }

        void IScriptManager.RegisterDispose(Control control, string disposeScript) {
            RegisterDispose(control, disposeScript);
        }

        void IScriptManager.RegisterExpandoAttribute(Control control, string controlId, string attributeName, string attributeValue, bool encode) {
            RegisterExpandoAttribute(control, controlId, attributeName, attributeValue, encode);
        }

        void IScriptManager.RegisterHiddenField(Control control, string hiddenFieldName, string hiddenFieldValue) {
            RegisterHiddenField(control, hiddenFieldName, hiddenFieldValue);
        }

        void IScriptManager.RegisterOnSubmitStatement(Control control, Type type, string key, string script) {
            RegisterOnSubmitStatement(control, type, key, script);
        }

        void IScriptManager.RegisterPostBackControl(Control control) {
            RegisterPostBackControl(control);
        }

        void IScriptManager.RegisterStartupScript(Control control, Type type, string key, string script, bool addScriptTags) {
            RegisterStartupScript(control, type, key, script, addScriptTags);
        }

        void IScriptManager.SetFocusInternal(string clientID) {
            PageRequestManager.SetFocusInternal(clientID);
        }

        bool IScriptManager.IsSecureConnection {
            get {
                return IsSecureConnection;
            }
        }
        #endregion

        // The following class will hijack the page's state persister with its current
        // settings so the history server state will be just as safe as the viewstate.
        private class StatePersister : PageStatePersister {
            public StatePersister(Page page) : base(page) { }

            public override void Load() {
                throw new NotImplementedException();
            }
            public override void Save() {
                throw new NotImplementedException();
            }

            public string Serialize(object state) {
                return StateFormatter2.Serialize(state, Purpose.WebForms_ScriptManager_HistoryState);
            }

            public object Deserialize(string serialized) {
                return StateFormatter2.Deserialize(serialized, Purpose.WebForms_ScriptManager_HistoryState);
            }
        }
    }
}
