From 53e1d99a751e7a9cb8ae3f67ac8f3630b2aea398 Mon Sep 17 00:00:00 2001 From: "E.Z. Hart" Date: Tue, 27 Sep 2016 07:50:02 -0600 Subject: 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 --- Xamarin.Forms.ControlGallery.Android/Activity1.cs | 39 +++---------- Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs | 14 +---- .../MainPage.xaml.cs | 14 +---- .../MainPage.xaml.cs | 14 +---- .../MainPage.xaml.cs | 23 ++------ Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs | 64 +++++++++++++++------- .../Bugzilla40911.cs | 41 ++++++++++++++ .../Xamarin.Forms.Controls.Issues.Shared.projitems | 1 + .../NativeBindingGalleryPage.cs | 8 +++ .../NestedNativeControlGalleryPage.cs | 8 +++ .../AppCompat/Platform.cs | 2 +- Xamarin.Forms.Platform.Android/Platform.cs | 2 +- Xamarin.Forms.Platform.WP8/Platform.cs | 2 +- Xamarin.Forms.Platform.WinRT/Platform.cs | 2 +- Xamarin.Forms.Platform.iOS/Platform.cs | 14 +---- 15 files changed, 127 insertions(+), 121 deletions(-) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla40911.cs diff --git a/Xamarin.Forms.ControlGallery.Android/Activity1.cs b/Xamarin.Forms.ControlGallery.Android/Activity1.cs index 35f877dc..ad3945ee 100644 --- a/Xamarin.Forms.ControlGallery.Android/Activity1.cs +++ b/Xamarin.Forms.ControlGallery.Android/Activity1.cs @@ -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(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(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(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) diff --git a/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs b/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs index e1ddb60f..a2b24287 100644 --- a/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs +++ b/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs @@ -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(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls); LoadApplication (app); } diff --git a/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml.cs b/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml.cs index d02dda0e..0446e394 100644 --- a/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml.cs +++ b/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml.cs @@ -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(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls); LoadApplication (app); } diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml.cs b/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml.cs index 1c34efd6..9a07cc50 100644 --- a/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml.cs +++ b/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml.cs @@ -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(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls); LoadApplication (app); } diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml.cs b/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml.cs index 84767a55..744e4d19 100644 --- a/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml.cs +++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml.cs @@ -24,24 +24,11 @@ namespace Xamarin.Forms.ControlGallery.WindowsUniversal 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); - } - - var nncgPage1 = args.Page as NativeBindingGalleryPage; - - if (nncgPage1 != null) { - AddNativeBindings(nncgPage1); - } - }; - } + // When the native control gallery loads up, it'll let us know so we can add the nested native controls + MessagingCenter.Subscribe(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls); + + // When the native binding gallery loads up, it'll let us know so we can set up the native bindings + MessagingCenter.Subscribe(this, NativeBindingGalleryPage.ReadyForNativeBindingsMessage, AddNativeBindings); LoadApplication (app); } diff --git a/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs b/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs index 7614796a..3eb36bfc 100644 --- a/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs +++ b/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs @@ -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; - - 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(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls); + MessagingCenter.Subscribe(this, Bugzilla40911.ReadyToSetUp40911Test, SetUp40911Test); - 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(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 diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla40911.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla40911.cs new file mode 100644 index 00000000..09035e80 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla40911.cs @@ -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 + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index 427a3845..c5f46d54 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -108,6 +108,7 @@ + diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.cs index 51d9b970..2941b4bb 100644 --- a/Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.cs +++ b/Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.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() { diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/NestedNativeControlGalleryPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/NestedNativeControlGalleryPage.cs index 9f596601..d93d2d66 100644 --- a/Xamarin.Forms.Controls/ControlGalleryPages/NestedNativeControlGalleryPage.cs +++ b/Xamarin.Forms.Controls/ControlGalleryPages/NestedNativeControlGalleryPage.cs @@ -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 }; diff --git a/Xamarin.Forms.Platform.Android/AppCompat/Platform.cs b/Xamarin.Forms.Platform.Android/AppCompat/Platform.cs index 0bad79b1..f656ff84 100644 --- a/Xamarin.Forms.Platform.Android/AppCompat/Platform.cs +++ b/Xamarin.Forms.Platform.Android/AppCompat/Platform.cs @@ -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) diff --git a/Xamarin.Forms.Platform.Android/Platform.cs b/Xamarin.Forms.Platform.Android/Platform.cs index 4561fa8f..5ac1e451 100644 --- a/Xamarin.Forms.Platform.Android/Platform.cs +++ b/Xamarin.Forms.Platform.Android/Platform.cs @@ -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; diff --git a/Xamarin.Forms.Platform.WP8/Platform.cs b/Xamarin.Forms.Platform.WP8/Platform.cs index be71df09..e1f4c9aa 100644 --- a/Xamarin.Forms.Platform.WP8/Platform.cs +++ b/Xamarin.Forms.Platform.WP8/Platform.cs @@ -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; diff --git a/Xamarin.Forms.Platform.WinRT/Platform.cs b/Xamarin.Forms.Platform.WinRT/Platform.cs index c16c896b..be146a9c 100644 --- a/Xamarin.Forms.Platform.WinRT/Platform.cs +++ b/Xamarin.Forms.Platform.WinRT/Platform.cs @@ -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 NavigationStack diff --git a/Xamarin.Forms.Platform.iOS/Platform.cs b/Xamarin.Forms.Platform.iOS/Platform.cs index 9ec4a8a8..04874db8 100644 --- a/Xamarin.Forms.Platform.iOS/Platform.cs +++ b/Xamarin.Forms.Platform.iOS/Platform.cs @@ -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() -- cgit v1.2.3