//generate the code from the parsed BrowserDefinitionTree //compile it, and install it in the gac internal void GenerateCode(AssemblyBuilder assemblyBuilder) { ProcessBrowserFiles(true /*useVirtualPath*/, BrowserCapabilitiesCompiler.AppBrowsersVirtualDir.VirtualPathString); ProcessCustomBrowserFiles(true /*useVirtualPath*/, BrowserCapabilitiesCompiler.AppBrowsersVirtualDir.VirtualPathString); CodeCompileUnit ccu = new CodeCompileUnit(); Debug.Assert(BrowserTree != null); ArrayList customTreeRoots = new ArrayList(); for (int i = 0; i < CustomTreeNames.Count; i++) { customTreeRoots.Add((BrowserDefinition)(((BrowserTree)CustomTreeList[i])[CustomTreeNames[i]])); } // namespace ASP CodeNamespace cnamespace = new CodeNamespace(BaseCodeDomTreeGenerator.defaultNamespace); //GEN: using System; cnamespace.Imports.Add(new CodeNamespaceImport("System")); //GEN: using System.Web; cnamespace.Imports.Add(new CodeNamespaceImport("System.Web")); //GEN: using System.Web.Configuration; cnamespace.Imports.Add(new CodeNamespaceImport("System.Web.Configuration")); //GEN: using System.Reflection; cnamespace.Imports.Add(new CodeNamespaceImport("System.Reflection")); //GEN: class BrowserCapabilitiesFactory ccu.Namespaces.Add(cnamespace); Type baseType = BrowserCapabilitiesCompiler.GetBrowserCapabilitiesFactoryBaseType(); CodeTypeDeclaration factoryType = new CodeTypeDeclaration(); factoryType.Attributes = MemberAttributes.Private; factoryType.IsClass = true; factoryType.Name = TypeName; factoryType.BaseTypes.Add(new CodeTypeReference(baseType)); cnamespace.Types.Add(factoryType); BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic; BrowserDefinition bd = null; //GEN: protected override object ConfigureBrowserCapabilities(NameValueCollection headers, HttpBrowserCapabilities browserCaps) CodeMemberMethod method = new CodeMemberMethod(); method.Attributes = MemberAttributes.Override | MemberAttributes.Public; method.ReturnType = new CodeTypeReference(typeof(void)); method.Name = "ConfigureCustomCapabilities"; CodeParameterDeclarationExpression cpde = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers"); method.Parameters.Add(cpde); cpde = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), "browserCaps"); method.Parameters.Add(cpde); factoryType.Members.Add(method); for (int i = 0; i < customTreeRoots.Count; i++) { GenerateSingleProcessCall((BrowserDefinition)customTreeRoots[i], method); } foreach (DictionaryEntry entry in _browserOverrides) { object key = entry.Key; BrowserDefinition firstBrowserDefinition = (BrowserDefinition)BrowserTree[GetFirstItemFromKey(_browserOverrides, key)]; string parentName = firstBrowserDefinition.ParentName; // if ((!TargetFrameworkUtil.HasMethod(baseType, parentName + "ProcessBrowsers", flags)) || (!TargetFrameworkUtil.HasMethod(baseType, parentName + "ProcessGateways", flags))) { String parentID = firstBrowserDefinition.ParentID; if (firstBrowserDefinition != null) { throw new ConfigurationErrorsException(SR.GetString(SR.Browser_parentID_Not_Found, parentID), firstBrowserDefinition.XmlNode); } else { throw new ConfigurationErrorsException(SR.GetString(SR.Browser_parentID_Not_Found, parentID)); } } bool isBrowserDefinition = true; if (firstBrowserDefinition is GatewayDefinition) { isBrowserDefinition = false; } //GenerateMethodsToOverrideBrowsers //Gen: protected override void Xxx_ProcessChildBrowsers(bool ignoreApplicationBrowsers, MNameValueCollection headers, HttpBrowserCapabilities browserCaps) ; string methodName = parentName + (isBrowserDefinition ? "ProcessBrowsers" : "ProcessGateways"); CodeMemberMethod cmm = new CodeMemberMethod(); cmm.Name = methodName; cmm.ReturnType = new CodeTypeReference(typeof(void)); cmm.Attributes = MemberAttributes.Family | MemberAttributes.Override; if (isBrowserDefinition) { cpde = new CodeParameterDeclarationExpression(typeof(bool), BrowserCapabilitiesCodeGenerator.IgnoreApplicationBrowserVariableName); cmm.Parameters.Add(cpde); } cpde = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers"); cmm.Parameters.Add(cpde); cpde = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), browserCapsVariable); cmm.Parameters.Add(cpde); factoryType.Members.Add(cmm); ArrayList overrides = (ArrayList)_browserOverrides[key]; CodeStatementCollection statements = cmm.Statements; bool ignoreApplicationBrowsersVarRefGenerated = false; foreach (string browserID in overrides) { bd = (BrowserDefinition)BrowserTree[browserID]; if (bd is GatewayDefinition || bd.IsRefID) { GenerateSingleProcessCall(bd, cmm); } else { if (!ignoreApplicationBrowsersVarRefGenerated) { Debug.Assert(isBrowserDefinition); // Gen: if (ignoreApplicationBrowsers) { // } // else { // ... // } CodeConditionStatement istatement = new CodeConditionStatement(); istatement.Condition = new CodeVariableReferenceExpression(BrowserCapabilitiesCodeGenerator.IgnoreApplicationBrowserVariableName); cmm.Statements.Add(istatement); statements = istatement.FalseStatements; ignoreApplicationBrowsersVarRefGenerated = true; } statements = GenerateTrackedSingleProcessCall(statements, bd, cmm); if (_baseInstance == null) { // If we are targeting 4.0 or using the ASP.BrowserCapsFactory assembly generated by // aspnet_regbrowsers.exe, we can simply just instantiate the type. // If not, then we need to use the type BrowserCapabilitiesFactory35 that contains code // from the 2.0 version of BrowserCapabilitiesFactory. This is because "baseType" is the 4.0 type // that contains the new 4.0 definitions. // (Dev10 bug 795509) if (MultiTargetingUtil.IsTargetFramework40OrAbove || baseType.Assembly == BrowserCapabilitiesCompiler.AspBrowserCapsFactoryAssembly) { _baseInstance = (BrowserCapabilitiesFactoryBase)Activator.CreateInstance(baseType); } else { _baseInstance = new BrowserCapabilitiesFactory35(); } } int parentDepth = (int)((Triplet)_baseInstance.InternalGetBrowserElements()[parentName]).Third; AddBrowserToCollectionRecursive(bd, parentDepth + 1); } } } foreach (DictionaryEntry entry in _defaultBrowserOverrides) { object key = entry.Key; BrowserDefinition firstDefaultBrowserDefinition = (BrowserDefinition)DefaultTree[GetFirstItemFromKey(_defaultBrowserOverrides, key)]; string parentName = firstDefaultBrowserDefinition.ParentName; if (baseType.GetMethod("Default" + parentName + "ProcessBrowsers", flags) == null) { String parentID = firstDefaultBrowserDefinition.ParentID; if (firstDefaultBrowserDefinition != null) { throw new ConfigurationErrorsException(SR.GetString(SR.DefaultBrowser_parentID_Not_Found, parentID), firstDefaultBrowserDefinition.XmlNode); } } string methodName = "Default" + parentName + "ProcessBrowsers"; CodeMemberMethod cmm = new CodeMemberMethod(); cmm.Name = methodName; cmm.ReturnType = new CodeTypeReference(typeof(void)); cmm.Attributes = MemberAttributes.Family | MemberAttributes.Override; cpde = new CodeParameterDeclarationExpression(typeof(bool), BrowserCapabilitiesCodeGenerator.IgnoreApplicationBrowserVariableName); cmm.Parameters.Add(cpde); cpde = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers"); cmm.Parameters.Add(cpde); cpde = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), browserCapsVariable); cmm.Parameters.Add(cpde); factoryType.Members.Add(cmm); ArrayList overrides = (ArrayList)_defaultBrowserOverrides[key]; CodeConditionStatement istatement = new CodeConditionStatement(); istatement.Condition = new CodeVariableReferenceExpression(BrowserCapabilitiesCodeGenerator.IgnoreApplicationBrowserVariableName); cmm.Statements.Add(istatement); CodeStatementCollection statements = istatement.FalseStatements; foreach(string browserID in overrides) { bd = (BrowserDefinition)DefaultTree[browserID]; Debug.Assert(!(bd is GatewayDefinition)); if(bd.IsRefID) { GenerateSingleProcessCall(bd, cmm, "Default"); } else { statements = GenerateTrackedSingleProcessCall(statements, bd, cmm, "Default"); } } } // Generate process method for the browser elements foreach (DictionaryEntry entry in BrowserTree) { bd = entry.Value as BrowserDefinition; Debug.Assert(bd != null); GenerateProcessMethod(bd, factoryType); } for (int i = 0; i < customTreeRoots.Count; i++) { foreach (DictionaryEntry entry in (BrowserTree)CustomTreeList[i]) { bd = entry.Value as BrowserDefinition; Debug.Assert(bd != null); GenerateProcessMethod(bd, factoryType); } } // Generate process method for the default browser elements foreach (DictionaryEntry entry in DefaultTree) { bd = entry.Value as BrowserDefinition; Debug.Assert(bd != null); GenerateProcessMethod(bd, factoryType, "Default"); } GenerateOverrideMatchedHeaders(factoryType); GenerateOverrideBrowserElements(factoryType); Assembly assembly = BrowserCapabilitiesCompiler.GetBrowserCapabilitiesFactoryBaseType().Assembly; assemblyBuilder.AddAssemblyReference(assembly, ccu); assemblyBuilder.AddCodeCompileUnit(_buildProvider, ccu); }
internal void GenerateCode(AssemblyBuilder assemblyBuilder) { base.ProcessBrowserFiles(true, BrowserCapabilitiesCompiler.AppBrowsersVirtualDir.VirtualPathString); base.ProcessCustomBrowserFiles(true, BrowserCapabilitiesCompiler.AppBrowsersVirtualDir.VirtualPathString); CodeCompileUnit ccu = new CodeCompileUnit(); ArrayList list = new ArrayList(); for (int i = 0; i < base.CustomTreeNames.Count; i++) { list.Add((BrowserDefinition) ((BrowserTree) base.CustomTreeList[i])[base.CustomTreeNames[i]]); } CodeNamespace namespace2 = new CodeNamespace("ASP"); namespace2.Imports.Add(new CodeNamespaceImport("System")); namespace2.Imports.Add(new CodeNamespaceImport("System.Web")); namespace2.Imports.Add(new CodeNamespaceImport("System.Web.Configuration")); namespace2.Imports.Add(new CodeNamespaceImport("System.Reflection")); ccu.Namespaces.Add(namespace2); Type browserCapabilitiesFactoryBaseType = BrowserCapabilitiesCompiler.GetBrowserCapabilitiesFactoryBaseType(); CodeTypeDeclaration declaration = new CodeTypeDeclaration { Attributes = MemberAttributes.Private, IsClass = true, Name = this.TypeName }; declaration.BaseTypes.Add(new CodeTypeReference(browserCapabilitiesFactoryBaseType)); namespace2.Types.Add(declaration); BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase; BrowserDefinition bd = null; CodeMemberMethod method = new CodeMemberMethod { Attributes = MemberAttributes.Public | MemberAttributes.Override, ReturnType = new CodeTypeReference(typeof(void)), Name = "ConfigureCustomCapabilities" }; CodeParameterDeclarationExpression expression = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers"); method.Parameters.Add(expression); expression = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), "browserCaps"); method.Parameters.Add(expression); declaration.Members.Add(method); for (int j = 0; j < list.Count; j++) { base.GenerateSingleProcessCall((BrowserDefinition) list[j], method); } foreach (DictionaryEntry entry in this._browserOverrides) { object key = entry.Key; BrowserDefinition definition2 = (BrowserDefinition) base.BrowserTree[GetFirstItemFromKey(this._browserOverrides, key)]; string parentName = definition2.ParentName; if (!TargetFrameworkUtil.HasMethod(browserCapabilitiesFactoryBaseType, parentName + "ProcessBrowsers", bindingAttr) || !TargetFrameworkUtil.HasMethod(browserCapabilitiesFactoryBaseType, parentName + "ProcessGateways", bindingAttr)) { string parentID = definition2.ParentID; if (definition2 != null) { throw new ConfigurationErrorsException(System.Web.SR.GetString("Browser_parentID_Not_Found", new object[] { parentID }), definition2.XmlNode); } throw new ConfigurationErrorsException(System.Web.SR.GetString("Browser_parentID_Not_Found", new object[] { parentID })); } bool flag = true; if (definition2 is GatewayDefinition) { flag = false; } string str3 = parentName + (flag ? "ProcessBrowsers" : "ProcessGateways"); CodeMemberMethod method2 = new CodeMemberMethod { Name = str3, ReturnType = new CodeTypeReference(typeof(void)), Attributes = MemberAttributes.Family | MemberAttributes.Override }; if (flag) { expression = new CodeParameterDeclarationExpression(typeof(bool), "ignoreApplicationBrowsers"); method2.Parameters.Add(expression); } expression = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers"); method2.Parameters.Add(expression); expression = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), "browserCaps"); method2.Parameters.Add(expression); declaration.Members.Add(method2); ArrayList list2 = (ArrayList) this._browserOverrides[key]; CodeStatementCollection stmts = method2.Statements; bool flag2 = false; foreach (string str4 in list2) { bd = (BrowserDefinition) base.BrowserTree[str4]; if ((bd is GatewayDefinition) || bd.IsRefID) { base.GenerateSingleProcessCall(bd, method2); } else { if (!flag2) { CodeConditionStatement statement = new CodeConditionStatement { Condition = new CodeVariableReferenceExpression("ignoreApplicationBrowsers") }; method2.Statements.Add(statement); stmts = statement.FalseStatements; flag2 = true; } stmts = base.GenerateTrackedSingleProcessCall(stmts, bd, method2); if (this._baseInstance == null) { if (MultiTargetingUtil.IsTargetFramework40OrAbove || (browserCapabilitiesFactoryBaseType.Assembly == BrowserCapabilitiesCompiler.AspBrowserCapsFactoryAssembly)) { this._baseInstance = (BrowserCapabilitiesFactoryBase) Activator.CreateInstance(browserCapabilitiesFactoryBaseType); } else { this._baseInstance = new BrowserCapabilitiesFactory35(); } } int third = (int) ((Triplet) this._baseInstance.InternalGetBrowserElements()[parentName]).Third; base.AddBrowserToCollectionRecursive(bd, third + 1); } } } foreach (DictionaryEntry entry2 in this._defaultBrowserOverrides) { object obj3 = entry2.Key; BrowserDefinition definition3 = (BrowserDefinition) base.DefaultTree[GetFirstItemFromKey(this._defaultBrowserOverrides, obj3)]; string str5 = definition3.ParentName; if (browserCapabilitiesFactoryBaseType.GetMethod("Default" + str5 + "ProcessBrowsers", bindingAttr) == null) { string str6 = definition3.ParentID; if (definition3 != null) { throw new ConfigurationErrorsException(System.Web.SR.GetString("DefaultBrowser_parentID_Not_Found", new object[] { str6 }), definition3.XmlNode); } } string str7 = "Default" + str5 + "ProcessBrowsers"; CodeMemberMethod method3 = new CodeMemberMethod { Name = str7, ReturnType = new CodeTypeReference(typeof(void)), Attributes = MemberAttributes.Family | MemberAttributes.Override }; expression = new CodeParameterDeclarationExpression(typeof(bool), "ignoreApplicationBrowsers"); method3.Parameters.Add(expression); expression = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers"); method3.Parameters.Add(expression); expression = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), "browserCaps"); method3.Parameters.Add(expression); declaration.Members.Add(method3); ArrayList list3 = (ArrayList) this._defaultBrowserOverrides[obj3]; CodeConditionStatement statement2 = new CodeConditionStatement { Condition = new CodeVariableReferenceExpression("ignoreApplicationBrowsers") }; method3.Statements.Add(statement2); CodeStatementCollection falseStatements = statement2.FalseStatements; foreach (string str8 in list3) { bd = (BrowserDefinition) base.DefaultTree[str8]; if (bd.IsRefID) { base.GenerateSingleProcessCall(bd, method3, "Default"); } else { falseStatements = base.GenerateTrackedSingleProcessCall(falseStatements, bd, method3, "Default"); } } } foreach (DictionaryEntry entry3 in base.BrowserTree) { bd = entry3.Value as BrowserDefinition; base.GenerateProcessMethod(bd, declaration); } for (int k = 0; k < list.Count; k++) { foreach (DictionaryEntry entry4 in (BrowserTree) base.CustomTreeList[k]) { bd = entry4.Value as BrowserDefinition; base.GenerateProcessMethod(bd, declaration); } } foreach (DictionaryEntry entry5 in base.DefaultTree) { bd = entry5.Value as BrowserDefinition; base.GenerateProcessMethod(bd, declaration, "Default"); } base.GenerateOverrideMatchedHeaders(declaration); base.GenerateOverrideBrowserElements(declaration); Assembly a = BrowserCapabilitiesCompiler.GetBrowserCapabilitiesFactoryBaseType().Assembly; assemblyBuilder.AddAssemblyReference(a, ccu); assemblyBuilder.AddCodeCompileUnit(this._buildProvider, ccu); }
// // Actually computes the browser capabilities // internal HttpCapabilitiesBase Evaluate(HttpRequest request) { HttpCapabilitiesBase result; CacheInternal cacheInternal = System.Web.HttpRuntime.CacheInternal; // // 1) grab UA and do optimistic cache lookup (if UA is in dependency list) // string userAgent = GetUserAgent(request); string userAgentCacheKey = userAgent; // Use the shorten userAgent as the cache key. Debug.Assert(UserAgentCacheKeyLength != 0); // Trim the useragent string based on <browserCaps> config if (userAgentCacheKey != null && userAgentCacheKey.Length > UserAgentCacheKeyLength) { userAgentCacheKey = userAgentCacheKey.Substring(0, UserAgentCacheKeyLength); } bool doFullCacheKeyLookup = false; string optimisticCacheKey = _cacheKeyPrefix + userAgentCacheKey; object optimisticCacheResult = cacheInternal.Get(optimisticCacheKey); // optimize for common case (desktop browser) result = optimisticCacheResult as HttpCapabilitiesBase; if (result != null) { return(result); } // // 1.1) optimistic cache entry could tell us to do full cache lookup // if (optimisticCacheResult == _disableOptimisticCachingSingleton) { doFullCacheKeyLookup = true; } else { // cache it and respect _cachetime result = EvaluateFinal(request, true); // Optimized cache key is disabled if the request matches any headers defined within identifications. if (result.UseOptimizedCacheKey) { // Use the same browserCap result if one with the same capabilities can be found in the cache. // This is to reduce the number of identical browserCap instances being cached. CacheBrowserCapResult(ref result); // Cache the result using the optimisicCacheKey cacheInternal.UtcInsert(optimisticCacheKey, result, null, Cache.NoAbsoluteExpiration, _cachetime); return(result); } } // // 2) either: // // We've never seen the UA before (parse all headers to // determine if the new UA also carries modile device // httpheaders). // // It's a mobile UA (so parse all headers) and do full // cache lookup // // UA isn't in dependency list (customer custom caps section) // IDictionaryEnumerator de = _variables.GetEnumerator(); StringBuilder sb = new StringBuilder(_cacheKeyPrefix); InternalSecurityPermissions.AspNetHostingPermissionLevelLow.Assert(); while (de.MoveNext()) { string key = (string)de.Key; string value; if (key.Length == 0) { value = userAgent; } else { value = request.ServerVariables[key]; } if (value != null) { sb.Append(value); } } CodeAccessPermission.RevertAssert(); sb.Append(BrowserCapabilitiesFactoryBase.GetBrowserCapKey(BrowserCapFactory.InternalGetMatchedHeaders(), request)); string fullCacheKey = sb.ToString(); // // Only do full cache lookup if the optimistic cache // result was _disableOptimisticCachingSingleton or // if UserAgent wasn't in the cap var list. // if (userAgent == null || doFullCacheKeyLookup) { result = cacheInternal.Get(fullCacheKey) as HttpCapabilitiesBase; if (result != null) { return(result); } } result = EvaluateFinal(request, false); // Use the same browserCap result if one with the same matched nodes can be found in the cache. // This is to reduce the number of identical browserCap instances being cached. CacheBrowserCapResult(ref result); // cache it and respect _cachetime cacheInternal.UtcInsert(fullCacheKey, result, null, Cache.NoAbsoluteExpiration, _cachetime); if (optimisticCacheKey != null) { cacheInternal.UtcInsert(optimisticCacheKey, _disableOptimisticCachingSingleton, null, Cache.NoAbsoluteExpiration, _cachetime); } return(result); }
internal HttpCapabilitiesBase Evaluate(HttpRequest request) { CacheInternal cacheInternal = HttpRuntime.CacheInternal; string userAgent = GetUserAgent(request); string str2 = userAgent; if ((str2 != null) && (str2.Length > this.UserAgentCacheKeyLength)) { str2 = str2.Substring(0, this.UserAgentCacheKeyLength); } bool flag = false; string key = this._cacheKeyPrefix + str2; object obj2 = cacheInternal.Get(key); HttpCapabilitiesBase result = obj2 as HttpCapabilitiesBase; if (result == null) { if (obj2 == _disableOptimisticCachingSingleton) { flag = true; } else { result = this.EvaluateFinal(request, true); if (result.UseOptimizedCacheKey) { this.CacheBrowserCapResult(ref result); cacheInternal.UtcInsert(key, result, null, Cache.NoAbsoluteExpiration, this._cachetime); return(result); } } IDictionaryEnumerator enumerator = this._variables.GetEnumerator(); StringBuilder builder = new StringBuilder(this._cacheKeyPrefix); InternalSecurityPermissions.AspNetHostingPermissionLevelLow.Assert(); while (enumerator.MoveNext()) { string str5; string str4 = (string)enumerator.Key; if (str4.Length == 0) { str5 = userAgent; } else { str5 = request.ServerVariables[str4]; } if (str5 != null) { builder.Append(str5); } } CodeAccessPermission.RevertAssert(); builder.Append(BrowserCapabilitiesFactoryBase.GetBrowserCapKey(this.BrowserCapFactory.InternalGetMatchedHeaders(), request)); string str6 = builder.ToString(); if ((userAgent == null) || flag) { result = cacheInternal.Get(str6) as HttpCapabilitiesBase; if (result != null) { return(result); } } result = this.EvaluateFinal(request, false); this.CacheBrowserCapResult(ref result); cacheInternal.UtcInsert(str6, result, null, Cache.NoAbsoluteExpiration, this._cachetime); if (key != null) { cacheInternal.UtcInsert(key, _disableOptimisticCachingSingleton, null, Cache.NoAbsoluteExpiration, this._cachetime); } } return(result); }