[linker] Adjust HttpClientHandler selection with the new (non BCL) location of the handlers

This commit is contained in:
Sebastien Pouliot 2019-04-01 21:23:56 -05:00
Родитель a9f8d7b379
Коммит 56d87eebba
3 изменённых файлов: 39 добавлений и 76 удалений

Просмотреть файл

@ -5,19 +5,10 @@ using System.Text;
#if MTOUCH || MMP
using Mono.Cecil;
using Xamarin.Linker;
#elif (MONOMAC || SYSTEM_NET_HTTP)
#else
using System.Net.Http;
#endif
#if XAMCORE_2_0 || SYSTEM_NET_HTTP
using Foundation;
using ObjCRuntime;
#elif MONOMAC && !MMP
using MonoMac.Foundation;
using MonoMac.ObjCRuntime;
#elif !MTOUCH && !MMP && !MMP_TEST
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
#endif
#if MMP || MMP_TEST || MTOUCH
@ -204,37 +195,29 @@ namespace ObjCRuntime {
}
}
#if (MONOMAC || SYSTEM_NET_HTTP)
[Preserve]
[Preserve] // always present but re-written by the linker
internal static HttpMessageHandler GetHttpMessageHandler ()
{
var options = RuntimeOptions.Read ();
if (options == null) {
#if __WATCHOS__
return new NSUrlSessionHandler ();
#else
return new HttpClientHandler ();
#endif
}
// all types will be present as this is executed only when the linker is not enabled
var handler_name = options.http_message_handler;
var t = Type.GetType (handler_name, false);
HttpMessageHandler handler = null;
if (t != null)
handler = Activator.CreateInstance (t) as HttpMessageHandler;
if (handler != null)
return handler;
var handler_name = options?.http_message_handler;
#if __WATCHOS__
Console.WriteLine ("{0} is not a valid HttpMessageHandler, defaulting to NSUrlSessionHandler", handler_name);
if (handler_name != NSUrlSessionHandlerValue)
Console.WriteLine ($"{handler_name} is not a valid HttpMessageHandler, defaulting to NSUrlSessionHandler");
return new NSUrlSessionHandler ();
#else
Console.WriteLine ("{0} is not a valid HttpMessageHandler, defaulting to System.Net.Http.HttpClientHandler", handler_name);
switch (handler_name) {
case CFNetworkHandlerValue:
return new CFNetworkHandler ();
case NSUrlSessionHandlerValue:
return new NSUrlSessionHandler ();
default:
if (handler_name != HttpClientHandlerValue)
Console.WriteLine ($"{handler_name} is not a valid HttpMessageHandler, defaulting to System.Net.Http.HttpClientHandler");
return new HttpClientHandler ();
#endif
}
#endif
}
#endif
// Use either Create() or Read().

Просмотреть файл

@ -121,6 +121,16 @@ namespace Introspection {
Console.WriteLine ($"Namespace candidate '{ns}'");
if (frameworks.TryGetValue (ns, out var f))
continue;
// skip System.Net.Http handlers (since we moved them out of the BCL)
switch (ns) {
case "System.Net.Http":
switch (t.Name) {
case "CFNetworkHandler":
case "NSUrlSessionHandler":
continue;
}
break;
}
// Either Skip method or Frameworks.cs needs to be updated
ReportError ("Unknown framework '{0}'", ns);
}

Просмотреть файл

@ -37,6 +37,16 @@ namespace Xamarin.Linker.Steps {
protected override string Name { get; } = "Default HttpMessageHandler setter";
protected override int ErrorCode { get; } = 2040;
Application App {
get {
#if MONOMAC
return Driver.App;
#else
return Options.Application;
#endif
}
}
public override bool IsActiveFor (AssemblyDefinition assembly)
{
switch (assembly.Name.Name) {
@ -44,7 +54,9 @@ namespace Xamarin.Linker.Steps {
case "Xamarin.Mac":
return context.Annotations.GetAction (assembly) == AssemblyAction.Link;
#else
case "System.Net.Http":
case "Xamarin.iOS":
case "Xamarin.TVOS":
case "Xamarin.WatchOS":
return context.Annotations.GetAction (assembly) == AssemblyAction.Link;
#endif
default:
@ -52,7 +64,6 @@ namespace Xamarin.Linker.Steps {
}
}
#if MONOMAC
protected override void Process (TypeDefinition type)
{
if (!type.Is ("ObjCRuntime", "RuntimeOptions"))
@ -61,7 +72,7 @@ namespace Xamarin.Linker.Steps {
MethodDefinition method = type.Methods.First (x => x.Name == "GetHttpMessageHandler" && !x.HasParameters);
AssemblyDefinition systemNetHTTPAssembly = context.GetAssemblies ().First (x => x.Name.Name == "System.Net.Http");
TypeDefinition handler = RuntimeOptions.GetHttpMessageHandler (Driver.App, Options.RuntimeOptions, systemNetHTTPAssembly.MainModule, type.Module);
TypeDefinition handler = RuntimeOptions.GetHttpMessageHandler (App, Options.RuntimeOptions, systemNetHTTPAssembly.MainModule, type.Module);
MethodReference handler_ctor = handler.Methods.First (x => x.IsConstructor && !x.HasParameters && !x.IsStatic);
// HttpClientHandler is defined not in Xamarin.Mac.dll so we need to import
@ -74,46 +85,5 @@ namespace Xamarin.Linker.Steps {
il.Emit (OpCodes.Ret);
method.Body = body;
}
#else
protected override void Process (TypeDefinition type)
{
if (!type.Is ("System.Net.Http", "HttpClient"))
return;
MethodDefinition default_ctor = null;
MethodDefinition full_ctor = null;
foreach (var m in type.Methods) {
if (m.IsStatic || !m.IsConstructor)
continue;
if (!m.HasParameters) {
default_ctor = m;
} else if (m.Parameters.Count == 2) {
full_ctor = m;
}
}
if (default_ctor == null || full_ctor == null)
throw new Exception ("Could not set the default HttpMessageHandler");
var handler = RuntimeOptions.GetHttpMessageHandler (Options.Application, Options.RuntimeOptions, type.Module);
MethodDefinition handler_ctor = null;
foreach (var m in handler.Methods) {
if (m.IsStatic || !m.IsConstructor || m.HasParameters)
continue;
handler_ctor = m;
break;
}
// re-write default ctor
var body = new MethodBody (default_ctor);
var il = body.GetILProcessor ();
il.Emit (OpCodes.Ldarg_0);
il.Emit (OpCodes.Newobj, handler_ctor);
il.Emit (OpCodes.Ldc_I4_1);
il.Emit (OpCodes.Call, full_ctor);
il.Emit (OpCodes.Ret);
default_ctor.Body = body;
}
#endif
}
}