This class is used to ensure that only one instance of GeckoWebBrowser is allowed to navigate at a time. We don't know for sure that this constraint is (or always will be) necessary, but at least as long as we're doing Application.DoEvents() in various places it's probably a good idea. See BL-77. It is designed for dependency-injection as an application-wide singleton. To achieve the purpose, all users of GeckoWebBrowser.Navigate must make use of the Navigate() or NavigateIfIdle() methods of this class to perform navigation. This class will serialize the navigations. Each navigation should occur eventually, except that if navigation is already in progress, NavigateIfIdle will just return false. This is intended for Idle loop tasks which should simply be attempted again later if the system is not really idle (since a navigation is in progress). Doing all this is challenging because the various possible events that might signal that navigation is complete are not reliable. Moreover it seems that the IsBusy flag (ReadyState, in later versions of Gecko) is also not reliable, and sometimes indicates that a browser is busy long after it has finished doing anything we recognize. We therefore use a timer to make sure we notice pretty soon if IsBusy becomes false without any of the events being raised. We will also notice at once that IsBusy has become false (or the target browser has been disposed) if a new request is received. As a last resort, rather than freeze the program or even the thumbnailing forever, if two seconds goes by and the browser is still busy doing one navigation we give up and forget that one and allow others to proceed.
        public void Isolation_AfterLongDelay_GivesUpAndMovesOn()
        {
            var browser = new BrowserStub();
            string target = "http://any old web address";
            var isolator = new NavigationIsolator();
            isolator.Navigate(browser, target);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target));

            var browser2 = new BrowserStub();
            string target2 = "http://some other web address";
            isolator.Navigate(browser2, target2);
            var browser3 = new BrowserStub();
            string target3 = "http://yet another web address";
            isolator.Navigate(browser3, target3);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target), "Second navigation should not have proceeded at once");
            var start = DateTime.Now;
            while (DateTime.Now - start < new TimeSpan(0, 0, 0, 2, 300))
                Application.DoEvents(); // allow timer to tick.
            Assert.That(() => browser2.NavigateTarget, Is.EqualTo(target2), "Second navigation should have proceeded eventually");

            browser2.NormalTermination(); // the second request.
            Assert.That(() => browser3.NavigateTarget, Is.EqualTo(target3), "Third navigation should have proceeded when second finished");

            browser3.NormalTermination(); // hopefully from the third.
            Assert.That(browser3.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
示例#2
0
        public ApplicationContainer()
        {
            var builder = new ContainerBuilder();

            //builder.RegisterModule<WhiteboxProfilingModule>();

            //default to InstancePerDependency, i.e., they it will make a new
            //one each time someone asks for one
            builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());

            builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            .Where(t => t.GetInterfaces().Contains(typeof(ICommand))).InstancePerLifetimeScope();

            builder.Register(c => LocalizationManager).SingleInstance();

            if (Settings.Default.MruProjects == null)
            {
                Settings.Default.MruProjects = new MostRecentPathsList();
            }
            builder.RegisterInstance(Settings.Default.MruProjects).SingleInstance();

            //this is to prevent some problems we were getting while waiting for a browser to navigate and being forced to call Application.DoEvents().
            //HtmlThumbnailer & ConfigurationDialog, at least, use this.
            // June 2018: we decided that actually no code other than the Browser class even needs to know that
            // this thing exists, so lots of code using this can be removed. But that will be done with BL-6069.
            builder.Register(c => NavigationIsolator.GetOrCreateTheOneNavigationIsolator()).InstancePerLifetimeScope();

            builder.Register <HtmlThumbNailer>(c => new HtmlThumbNailer(c.Resolve <NavigationIsolator>())).SingleInstance();
            builder.Register <BookThumbNailer>(c => new BookThumbNailer(c.Resolve <HtmlThumbNailer>())).SingleInstance();

            _container = builder.Build();

            Application.ApplicationExit += OnApplicationExit;
        }
示例#3
0
 public AboutMemory(NavigationIsolator isolator)
 {
     InitializeComponent();
     _browser1.Isolator            = isolator;
     _browser1.ContextMenuProvider = x => { return(true); };            // replace standard menu commands with none
     FirstLinkUrl  = "https://developer.mozilla.org/en-US/docs/Mozilla/Performance/about:memory";
     SecondLinkUrl = "https://developer.mozilla.org/en-US/docs/Mozilla/Performance/GC_and_CC_logs";
 }
示例#4
0
 public AboutMemory(NavigationIsolator isolator)
 {
     InitializeComponent();
     _browser1.Isolator = isolator;
     _browser1.ContextMenuProvider = x => { return true; }; // replace standard menu commands with none
     FirstLinkUrl = "https://developer.mozilla.org/en-US/docs/Mozilla/Performance/about:memory";
     SecondLinkUrl = "https://developer.mozilla.org/en-US/docs/Mozilla/Performance/GC_and_CC_logs";
 }
 public void IdleNavigation_WhenNothingHappening_ProceedsAtOnce()
 {
     var browser = new BrowserStub();
     string target = "http://any old web address";
     var isolator = new NavigationIsolator();
     Assert.That(isolator.NavigateIfIdle(browser, target), Is.True);
     Assert.That(browser.NavigateTarget, Is.EqualTo(target));
     browser.NormalTermination();
     Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed after navigation completes");
 }
 public void IdleNavigation_NavigationInProgress_ReturnsFalse_NeverProceeds()
 {
     var browser = new BrowserStub();
     string target = "http://any old web address";
     var isolator = new NavigationIsolator();
     isolator.Navigate(browser, target);
     Assert.That(browser.NavigateTarget, Is.EqualTo(target));
     string target2 = "http://some other web address";
     Assert.That(isolator.NavigateIfIdle(browser, target2), Is.False);
     browser.NormalTermination();
     Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed after navigation completes");
     Assert.That(browser.NavigateTarget, Is.EqualTo(target), "failed idle navigation should not happen");
 }
示例#7
0
        public HtmlThumbNailer(NavigationIsolator isolator)
        {
            if (_theOnlyOneAllowed != null)
            {
                Debug.Fail("Something tried to make a second HtmlThumbnailer; there should only be one.");
                throw new ApplicationException("Something tried to make a second HtmlThumbnailer; there should only be one.");
            }

            _theOnlyOneAllowed = this;

            _isolator = isolator;

            _syncControl = new Control();
            _syncControl.CreateControl();
        }
        public HtmlThumbNailer(NavigationIsolator isolator)
        {
            if (_theOnlyOneAllowed != null)
            {
                Debug.Fail("Something tried to make a second HtmlThumbnailer; there should only be one.");
                throw new ApplicationException("Something tried to make a second HtmlThumbnailer; there should only be one.");
            }

            _theOnlyOneAllowed = this;

            _isolator = isolator;

            _syncControl = new Control();
            _syncControl.CreateControl();
        }
        public void NoLongerBusy_EvenWithoutEvent_IsNoticed()
        {
            var browser = new BrowserStub();
            string target = "http://any old web address";
            var isolator = new NavigationIsolator();
            isolator.Navigate(browser, target);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target));
            string target2 = "http://some other web address";
            isolator.Navigate(browser, target2);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target), "Second navigation should not have proceeded at once");
            browser.IsBusy = false; // finished but did not raise event.
            var start = DateTime.Now;
            while (DateTime.Now - start < new TimeSpan(0, 0,0, 0, 150))
                Application.DoEvents(); // allow timer to tick.
            Assert.That(() => browser.NavigateTarget, Is.EqualTo(target2), "Second navigation should have proceeded soon after first no longer busy");

            browser.NormalTermination();
            Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
        public void SingleTask_AfterLongDelay_AllowsIdleNavigation()
        {
            var browser = new BrowserStub();
            string target = "http://any old web address";
            var isolator = new NavigationIsolator();
            isolator.Navigate(browser, target);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target));

            string target2 = "http://some other web address";
            var start = DateTime.Now;
            var success = false;
            while (!success && DateTime.Now - start < new TimeSpan(0, 0, 0, 2, 300))
            {
                success = isolator.NavigateIfIdle(browser, target2);
                Application.DoEvents(); // allow timer to tick.
            }
            Assert.That(() => browser.NavigateTarget, Is.EqualTo(target2), "Idle navigation should have proceeded eventually");
            Assert.That(success, "NavigateIfIdle should eventually succeed");

            browser.NormalTermination(); // possibly the long-delayed notification of the first nav, but more likely the idle navigation.
            Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
        public void RegularNavigation_DelayedProperlyByIdleNavigation()
        {
            var browser = new BrowserStub();
            string target = "http://any old web address";
            var isolator = new NavigationIsolator();
            Assert.That(isolator.NavigateIfIdle(browser, target), Is.True);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target));

            string target2 = "http://some other web address";
            isolator.Navigate(browser, target2);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target), "Second navigation should not have proceeded at once");

            browser.NormalTermination();
            Assert.That(browser.NavigateTarget, Is.EqualTo(target2), "Second navigation should have proceeded when first completed");

            browser.NormalTermination();
            Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
        public void SameBrowser_ReplacesPending()
        {
            var isolator = new NavigationIsolator();
            var browser = new BrowserStub();
            string target = "http://whatever";
            isolator.Navigate(browser, target);

            var browser2 = new BrowserStub();
            string target2A = "http://first";
            isolator.Navigate(browser2, target2A);
            string target2B = "http://second";
            isolator.Navigate(browser2, target2B);
            // Signal the first browser to finish.
            browser.NormalTermination();
            Assert.That(() => browser2.NavigateTarget, Is.EqualTo(target2B), "Second navigation should have proceeded with its second choice");
            // Signal the second browser to finish.
            browser2.NormalTermination();

            Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
            Assert.That(browser2.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
示例#13
0
 private NavigationIsolator()
 {
     Debug.Assert(NavigationIsolator._sTheOneNavigationIsolator == null,
                  "There should only be one NavigationIsolator... that's the whole point of it.");
     NavigationIsolator._sTheOneNavigationIsolator = this;
 }
        public void TwoPendingNavigations_WithNavigatedEvents_AreHandledCorrectly()
        {
            var browser = new BrowserStub();
            string target = "http://any old web address";
            var isolator = new NavigationIsolator();
            isolator.Navigate(browser, target);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target));
            var browser2 = new BrowserStub();
            string target2 = "http://some other web address";
            isolator.Navigate(browser2, target2);
            var browser3 = new BrowserStub();
            string target3 = "http://yet another other web address";
            isolator.Navigate(browser3, target3);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target), "Second and third navigation should not have proceeded at once");

            browser.NormalTermination();
            Assert.That(browser2.NavigateTarget, Is.EqualTo(target2), "Second navigation should have proceeded when first completed (but third should not)");

            browser2.NormalTermination();
            Assert.That(browser3.NavigateTarget, Is.EqualTo(target3), "Third navigation should have proceeded when second completed");

            browser3.NormalTermination();
            Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
        public void SecondNavigation_OnSameBrowser_HappensWhenFirstRaisesNavigated()
        {
            var browser = new BrowserStub();
            string target = "http://any old web address";
            var isolator = new NavigationIsolator();
            isolator.Navigate(browser, target);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target));
            string target2 = "http://some other web address";
            isolator.Navigate(browser, target2);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target), "Second navigation should not have proceeded at once");

            browser.NormalTermination();
            Assert.That(browser.NavigateTarget, Is.EqualTo(target2), "Second navigation should have proceeded when first completed");

            browser.NormalTermination();
            Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
        public void SpuriousNavigatedEvents_AreIgnored()
        {
            var browser = new BrowserStub();
            string target = "http://any old web address";
            var isolator = new NavigationIsolator();
            isolator.Navigate(browser, target);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target));
            string target2 = "http://some other web address";
            isolator.Navigate(browser, target2);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target), "Second navigation should not have proceeded at once");

            browser.RaiseNavigated(this, new EventArgs()); // got the event notification, but still busy.
            Assert.That(browser.NavigateTarget, Is.EqualTo(target), "Second navigation should not have proceeded even on Navigated while browser still busy");

            browser.NormalTermination();
            Assert.That(browser.NavigateTarget, Is.EqualTo(target2), "Second navigation should have proceeded when first completed (and browser no longer busy)");

            browser.NormalTermination();
            Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
        public void SecondRequest_WhenFirstNoLongerBusy_ProceedsAtOnce()
        {
            var browser = new BrowserStub();
            string target = "http://any old web address";
            var isolator = new NavigationIsolator();
            isolator.Navigate(browser, target);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target));
            browser.IsBusy = false; // clear state without raising event
            string target2 = "http://some other web address";
            isolator.Navigate(browser, target2);
            Assert.That(browser.NavigateTarget, Is.EqualTo(target2), "Second navigation should have proceeded since browser is already not busy");

            browser.NormalTermination();
            Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed once last navigation completed");
        }
 public void SimpleNavigation_JustHappens()
 {
     var browser = new BrowserStub();
     string target = "http://any old web address";
     var isolator = new NavigationIsolator();
     isolator.Navigate(browser, target);
     Assert.That(browser.NavigateTarget, Is.EqualTo(target));
     browser.NormalTermination();
     Assert.That(browser.EventHandlerCount, Is.EqualTo(0), "event handlers should be removed after navigation completes");
 }