Fix potential NRE accessing current application via Page.RealParent (#330)

* Fix potential NRE accessing current application via Page.RealParent

* Update Native Bindings Gallery to use MessagingCenter
This commit is contained in:
E.Z. Hart 2016-09-27 07:50:02 -06:00 коммит произвёл Rui Marinho
Родитель c83c830c68
Коммит 53e1d99a75
15 изменённых файлов: 127 добавлений и 121 удалений

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

@ -205,17 +205,8 @@ namespace Xamarin.Forms.ControlGallery.Android
var app = new App ();
var mdp = app.MainPage as MasterDetailPage;
var detail = mdp?.Detail as NavigationPage;
if (detail != null) {
detail.Pushed += (sender, args) => {
var nncgPage = args.Page as NestedNativeControlGalleryPage;
if (nncgPage != null) {
AddNativeControls (nncgPage);
}
};
}
// When the native control gallery loads up, it'll let us know so we can add the nested native controls
MessagingCenter.Subscribe<NestedNativeControlGalleryPage>(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls);
LoadApplication (app);
}
@ -327,29 +318,15 @@ namespace Xamarin.Forms.ControlGallery.Android
// uncomment to verify turning off title bar works. This is not intended to be dynamic really.
//Forms.SetTitleBarVisibility (AndroidTitleBarVisibility.Never);
var app = new App ();
var app = new App();
var mdp = app.MainPage as MasterDetailPage;
var detail = mdp?.Detail as NavigationPage;
if (detail != null) {
detail.Pushed += (sender, args) => {
var nncgPage = args.Page as NestedNativeControlGalleryPage;
// When the native control gallery loads up, it'll let us know so we can add the nested native controls
MessagingCenter.Subscribe<NestedNativeControlGalleryPage>(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls);
if (nncgPage != null) {
AddNativeControls (nncgPage);
}
// When the native binding gallery loads up, it'll let us know so we can set up the native bindings
MessagingCenter.Subscribe<NativeBindingGalleryPage >(this, NativeBindingGalleryPage.ReadyForNativeBindingsMessage, AddNativeBindings);
var nncgPage1 = args.Page as NativeBindingGalleryPage;
if (nncgPage1 != null)
{
AddNativeBindings(nncgPage1);
}
};
}
LoadApplication (app);
LoadApplication(app);
}
public override void OnConfigurationChanged (global::Android.Content.Res.Configuration newConfig)

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

@ -61,18 +61,8 @@ namespace Xamarin.Forms.ControlGallery.WP8
var app = new Controls.App ();
var mdp = app.MainPage as MasterDetailPage;
var detail = mdp?.Detail as NavigationPage;
if (detail != null) {
detail.Pushed += (sender, args) => {
var nncgPage = args.Page as NestedNativeControlGalleryPage;
if (nncgPage != null) {
AddNativeControls (nncgPage);
}
};
}
// When the native control gallery loads up, it'll let us know so we can add the nested native controls
MessagingCenter.Subscribe<NestedNativeControlGalleryPage>(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls);
LoadApplication (app);
}

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

@ -17,18 +17,8 @@ namespace Xamarin.Forms.ControlGallery.Windows
var app = new Controls.App ();
var mdp = app.MainPage as MasterDetailPage;
var detail = mdp?.Detail as NavigationPage;
if (detail != null) {
detail.Pushed += (sender, args) => {
var nncgPage = args.Page as NestedNativeControlGalleryPage;
if (nncgPage != null) {
AddNativeControls (nncgPage);
}
};
}
// When the native control gallery loads up, it'll let us know so we can add the nested native controls
MessagingCenter.Subscribe<NestedNativeControlGalleryPage>(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls);
LoadApplication (app);
}

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

@ -23,18 +23,8 @@ namespace Xamarin.Forms.ControlGallery.WindowsPhone
var app = new Controls.App ();
var mdp = app.MainPage as MasterDetailPage;
var detail = mdp?.Detail as NavigationPage;
if (detail != null) {
detail.Pushed += (sender, args) => {
var nncgPage = args.Page as NestedNativeControlGalleryPage;
if (nncgPage != null) {
AddNativeControls (nncgPage);
}
};
}
// When the native control gallery loads up, it'll let us know so we can add the nested native controls
MessagingCenter.Subscribe<NestedNativeControlGalleryPage>(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls);
LoadApplication (app);
}

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

@ -24,24 +24,11 @@ namespace Xamarin.Forms.ControlGallery.WindowsUniversal
var app = new Controls.App ();
var mdp = app.MainPage as MasterDetailPage;
// When the native control gallery loads up, it'll let us know so we can add the nested native controls
MessagingCenter.Subscribe<NestedNativeControlGalleryPage>(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls);
var detail = mdp?.Detail as NavigationPage;
if (detail != null) {
detail.Pushed += (sender, args) => {
var nncgPage = args.Page as NestedNativeControlGalleryPage;
if (nncgPage != null) {
AddNativeControls (nncgPage);
}
var nncgPage1 = args.Page as NativeBindingGalleryPage;
if (nncgPage1 != null) {
AddNativeBindings(nncgPage1);
}
};
}
// When the native binding gallery loads up, it'll let us know so we can set up the native bindings
MessagingCenter.Subscribe<NativeBindingGalleryPage >(this, NativeBindingGalleryPage.ReadyForNativeBindingsMessage, AddNativeBindings);
LoadApplication (app);
}

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

@ -151,27 +151,12 @@ namespace Xamarin.Forms.ControlGallery.iOS
var app = new App();
var mdp = app.MainPage as MasterDetailPage;
var detail = mdp?.Detail as NavigationPage;
if (detail != null)
{
detail.Pushed += (sender, args) =>
{
var nncgPage = args.Page as NestedNativeControlGalleryPage;
// When the native control gallery loads up, it'll let us know so we can add the nested native controls
MessagingCenter.Subscribe<NestedNativeControlGalleryPage>(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls);
MessagingCenter.Subscribe<Bugzilla40911>(this, Bugzilla40911.ReadyToSetUp40911Test, SetUp40911Test);
if (nncgPage != null)
{
AddNativeControls(nncgPage);
}
var nncgPage1 = args.Page as NativeBindingGalleryPage;
if (nncgPage1 != null)
{
AddNativeBindings(nncgPage1);
}
};
}
// When the native binding gallery loads up, it'll let us know so we can set up the native bindings
MessagingCenter.Subscribe<NativeBindingGalleryPage >(this, NativeBindingGalleryPage.ReadyForNativeBindingsMessage, AddNativeBindings);
LoadApplication(app);
return base.FinishedLaunching(uiApplication, launchOptions);
@ -321,6 +306,45 @@ namespace Xamarin.Forms.ControlGallery.iOS
sl?.Children.Add(colorPicker);
page.NativeControlsAdded = true;
}
#region Stuff for repro of Bugzilla case 40911
void SetUp40911Test(Bugzilla40911 page)
{
var button = new Button { Text = "Start" };
button.Clicked += (s, e) =>
{
StartPressed40911();
};
page.Layout.Children.Add(button);
}
public void StartPressed40911 ()
{
var loginViewController = new UIViewController { View = { BackgroundColor = UIColor.White } };
var button = UIButton.FromType (UIButtonType.RoundedRect);
button.SetTitle ("Login", UIControlState.Normal);
button.Frame = new CGRect (20, 100, 200, 44);
loginViewController.View.AddSubview (button);
button.TouchUpInside += (sender, e) => {
Xamarin.Forms.Application.Current.MainPage = new ContentPage {Content = new Label {Text = "40911 Success"} };
loginViewController.DismissViewController (true, null);
};
var window= UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
{
vc = vc.PresentedViewController;
}
vc.PresentViewController (loginViewController, true, null);
}
#endregion
}
public class ColorConverter : IValueConverter

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

@ -0,0 +1,41 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
#endif
namespace Xamarin.Forms.Controls
{
[Preserve (AllMembers = true)]
[Issue (IssueTracker.Bugzilla, 40911, "NRE with Facebook Login", PlatformAffected.iOS)]
public class Bugzilla40911 : TestContentPage
{
public StackLayout Layout { get; private set; }
public const string ReadyToSetUp40911Test = "ReadyToSetUp40911Test";
protected override void Init ()
{
Layout = new StackLayout();
Layout.Children.Add(new Label{Text = "This is an iOS-specific issue. If you're on another platform, you can ignore this." });
Content = Layout;
MessagingCenter.Send(this, ReadyToSetUp40911Test);
}
#if UITEST && __IOS__
[Test]
public void CanFinishLoginWithoutNRE ()
{
RunningApp.WaitForElement("Start");
RunningApp.Tap("Start");
RunningApp.WaitForElement("Login");
RunningApp.Tap("Login");
RunningApp.WaitForElement("40911 Success");
}
#endif
}
}

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

@ -108,6 +108,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla31806.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla40858.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla40824.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla40911.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla40955.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla41078.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla40998.cs" />

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

@ -10,6 +10,14 @@ namespace Xamarin.Forms.Controls
NestedNativeViewModel ViewModel { get; set; }
public const string ReadyForNativeBindingsMessage = "ReadyForNativeBindings";
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Send(this, ReadyForNativeBindingsMessage);
}
public NativeBindingGalleryPage()
{

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

@ -6,6 +6,14 @@ namespace Xamarin.Forms.Controls
public bool NativeControlsAdded { get; set; }
public const string ReadyForNativeControlsMessage = "ReadyForNativeControls";
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Send(this, ReadyForNativeControlsMessage);
}
public NestedNativeControlGalleryPage ()
{
Layout = new StackLayout { Padding = 20, VerticalOptions = LayoutOptions.FillAndExpand };

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

@ -238,7 +238,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
Page.Platform = this;
AddChild(Page, layout);
((Application)Page.RealParent).NavigationProxy.Inner = this;
Application.Current.NavigationProxy.Inner = this;
}
void AddChild(Page page, bool layout = false)

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

@ -413,7 +413,7 @@ namespace Xamarin.Forms.Platform.Android
Page.Platform = this;
AddChild(Page, layout);
((Application)Page.RealParent).NavigationProxy.Inner = this;
Application.Current.NavigationProxy.Inner = this;
_toolbarTracker.Target = newRoot;

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

@ -437,7 +437,7 @@ namespace Xamarin.Forms.Platform.WinPhone
_navModel.PushModal(newRoot);
SetCurrent(newRoot, false, true);
((Application)newRoot.RealParent).NavigationProxy.Inner = this;
Application.Current.NavigationProxy.Inner = this;
}
internal event EventHandler SizeChanged;

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

@ -100,7 +100,7 @@ namespace Xamarin.Forms.Platform.WinRT
_navModel.Push(newRoot, null);
newRoot.NavigationProxy.Inner = this;
SetCurrent(newRoot, false, true);
((Application)newRoot.RealParent).NavigationProxy.Inner = this;
Application.Current.NavigationProxy.Inner = this;
}
public IReadOnlyList<Page> NavigationStack

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

@ -149,16 +149,6 @@ namespace Xamarin.Forms.Platform.iOS
Page Page { get; set; }
Application TargetApplication
{
get
{
if (Page == null)
return null;
return Page.RealParent as Application;
}
}
void IDisposable.Dispose()
{
if (_disposed)
@ -304,7 +294,7 @@ namespace Xamarin.Forms.Platform.iOS
internal void DidAppear()
{
_animateModals = false;
TargetApplication.NavigationProxy.Inner = this;
Application.Current.NavigationProxy.Inner = this;
_animateModals = true;
}
@ -388,7 +378,7 @@ namespace Xamarin.Forms.Platform.iOS
Page.DescendantRemoved += HandleChildRemoved;
TargetApplication.NavigationProxy.Inner = this;
Application.Current.NavigationProxy.Inner = this;
}
internal void WillAppear()