C# Issue WebBrowserReadyState - knowing when page has refreshed - page-refresh

I hope this isn't a stupid question. However I am writing a program at the moment which is a front end for a website booking system.
When I navigate to a specific link it remembers previous information on the page - So I have to make it load the page and then refresh - It's a bit messy doing this, so I have created another form which comes up during the loading called pleasew.cs. It will show "pleasew" for the first while loop and then I am assuming that "WebBrowserReadyState" is set to "Complete." and it more or less then closes the "pleasew" form before it's completed the refresh. Is there anything I can do to reset "WebBrowserReadyState" before it refreshes? Or is there another solution at all?
Many Thanks for looking
Here is the code:
private void button7_Click_1(object sender, EventArgs e)
{
webBrowser1.Navigate("www.test.co.uk");
pleasew pleasewait = new pleasew();
pleasewait.Show();
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
webBrowser1.Refresh();
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
pleasewait.Hide();
}

If I understand your problem right, you beleive the readystate doesn't get out of complete status when you do your refresh. Have you debugged to be certain it never enters the second while loop? Maybe because it's a refresh, it loads up from the cache, and that's the source of your confusion.
Try doing a second Navigate instead of Refresh and see what happens.

Related

How to test if Xamarin Android app closes

I am writing my first Android app, using Xamarin. I have an Exit button that, when clicked, closes the app. I want a test in Xamarin UITest that verifies clicking the button closes the app. I messed around with it for a while and finally found something that allows the test to pass.
In the app:
exitButton.Click += (o, e) =>
{
int pid = Android.OS.Process.MyPid();
Android.OS.Process.KillProcess(pid);
};
In UITest:
[Test]
public void ExitButtonClosesTheScreen()
{
try
{
app.Tap(c => c.Button("exitButton"));
Assert.Fail("App remains open.");
}
catch (System.Exception e)
{
Assert.AreEqual("The underlying connection was closed: The connection was closed unexpectedly.", e.InnerException.InnerException.InnerException.Message);
}
}
The test now passes so I guess I'm happy. My question is, is this really the best way to do this? Or is there a better way that I wasn't able to find?
Edit: Unfortunately, this is not the answer. This method allows the test to pass in VS but fails when I run it in App Center. Is there another way to run this test? Or is this something that is simply not testable with UITest? Thank you.
First of all the right code for closing the Application as per me is using finish affinity
In an Activity:
this.FinishAffinity();
In a Fragment:
this.Activity.FinishAffinity();
After doing this AppCenter should be able to figure that your app is closed.
I did a brief read up on this the other day for something similar and I am certain that the ActivityManager class would be the best way to go about this.
https://developer.xamarin.com/api/type/Android.App.ActivityManager/
There is a method within this class called RunningAppProcesses which returns a list of application processes that are running on the device - and from there I guess you can assert if your app process is on the list or not.
Hope this helps
After almost 4 years, i've encountered with the same issue.
I will do it this way in your case:
[Test]
public void ExitButtonClosesTheScreen()
{
app.Tap(c => c.Marked("exitButton"));
/** I asume exitButton click action will just exit,
no popups or alerts appear before exiting. **/
app.WaitForNoElement(q => q.Marked("exitButton"),
"Timeout waiting for element exitButton",
new TimeSpan(0, 0, 30));
AppResult[] result = app.Query();
Assert.IsTrue(result.Length == 0);
}
app.Query() returns all views visible by default, unless a query is especified by a lambda expression, as you should alredy know.
If the Application is gone, the Views visible will be 0, and as such, app.query() will return and array lenght of 0.
For WaitForNoElement's timeout I use a TimeSpan of 30 seconds, but you can use whatever timeout you prefer for this operation, i just considered 30 seconds will be ok.

IIOS IPAD No Unload,beforeunloador, paghide events

I have a MVC web database application where the records are basically documents with items.
Documents are locked, not items and they locked by code when the user looks in any of 4 or 5 different screens for any given document.
there is a 10 minute time out on the record locks. The user does not do anything with the record for 10 minutes and another can take the record. There is code that detects the lock was lost and taken by someone else. It works fine and is technically sound.
The workflow of the application relies on the lock being released when the user leaves the screen or closes the browser, or if they press the refresh button.
These are work fine on windows and android but not on ipad.
I understand there is no
beforeunload
on ios but I though there was
unload
or
pageHide
neither of these work.
Here is my code.
var isOnIOS = navigator.userAgent.match(/iPad/i)||
navigator.userAgent.match(/iPhone/i); var eventName = isOnIOS ?
"pageHide" : "beforeunload";
window.addEventListener(eventName, function (event) {
ReleaseRecordLock(); } );
This code works on all mentioned platforms except that the events don't fire on IOS.
It looks to me that this is deliberate on Apple's part so I an not thinking it will change.
So now the question.
What can I do to ensure that these records get unlocked if a user changes screens or closes the browser. If they don't no users will be able to access the document for 10 minutes which will not be acceptable.
Thanks
Edit... I don't need pop ups or notification. I just need reliable unlocking
As mentioned above none of the events that are supposed to work actually fire. pageHide and unload do nothing.
I found mentions of how to get around this problem but no details so I though I would detail it here.
This solutions works with areas and standard sites.
My solution to get around part of this was to detect if the browser is running on IOS and if so to change the link in the menu.
<li>
#{
if(Request.UserAgent.Contains("iPad") || Request.UserAgent.Contains("iPhone"))
{
<a onclick="IOSReleaseLock('controller', 'action')" href="javascript:void(0);">LinkText</a>
}
else
{
#Html.ActionLink("link Text","action","controller",new { Area = "Tasks" },null);
}
}
</li>
Every single link in the application has to have a function called IOSReleaseLock() available or the solution will not work. Not all pages lock records, only those that actually change documents. Reports, and basic website functions such as change password, log out, and the sys admin stuff do not need record locks.
At this point I have 2 versions of IOSReleaseLock()
This is the version that is used on pages that do not required unlocking.
function IOSReleaseLock(_controller, _action)
{
var url = '/__controller__/__action__/';
url = url.replace('__controller__', _controller);
url = url.replace('__action__', _action);
window.location.href = url;
}
This is the version that is placed on pages that required unlocking.
function IOSReleaseLock(_controller, _action )
{
var url = '/__controller__/__action__/';
url = url.replace('__controller__', _controller);
url = url.replace('__action__', _action);
UnloadingRecordLockRelease();
window.location.href = url;
}
Every link has a wrapper so every single page must load a version of IOSReleaseLock(). This includes your /home/index or where ever your application starts. If you miss one then once you are on that page your menu system links will not work anymore.
Pages that require the UnloadingRecordLockRelease() function load that version and the pages that do not require unlocking load the first version.
On IOS every time you click a link, IOSReleaseLock() is called. This may seem to be obvious, but for clarity, the version of IOSReleaseLock() that executes is the version that is on the current page, not the version on the page you are going to.
So as long as the user stays on the site and does not close the browser then the records are unlocked correctly.
When the user logs out all records are unlocked but I have no solution for when the browser tab is closed or when the browser is closed without the user logging out.

jQuery UI Focus Issue

I am getting Issue
unable to get property'_focusTabbable'of undefined or null reference
I am using Jquery-ui-1.10.2.custom.js
Here I am getting issue in
if ( !$.ui.dialog.overlayInstances ) {
// Prevent use of anchors and inputs.
// We use a delay in case the overlay is created from an
// event that we're going to be cancelling. (#2804)
this._delay(function() {
// Handle .dialog().dialog("close") (#4065)
if ( $.ui.dialog.overlayInstances ) {
this.document.bind( "focusin.dialog", function( event ) {
if ( !that._allowInteraction( event ) ) {
event.preventDefault();
**$(".ui-dialog:visible:last .ui-dialog-content")
.data( widgetFullName )._focusTabbable();**
}
});
}
});
}
This bug arises when you open a dialog and then, in an action button of this dialog, call a method that opens a second dialog. When you attempt to close the second dialog, the bug appears.
To prevent this from happening, close the first dialog immediately, and then call the second dialog.
$('#dialog1').dialog({
buttons: {
'No': function () {
$(this).dialog('close')
},
'Yes': function () {
// This works
$(this).dialog('close');
// Open second dialog
OpenSecondDialog()
// This doesn't work. A bug will arise when attempting to close the second dialog
$(this).dialog('close');
}
}
});
I'm opening one dialog and then another to confirm changes which were done in the first dialog. When confirming it doesn't close the first dialog which was opened. So I'm just destroying everything to get rid of the focus issue.
$(".ui-dialog-content").dialog('destroy');
I just put this one in the confirm function of the last dialog so it destroys all my dialogs (since they have the same class).
Just for future reference (and in case anyone else experiences this problem), I got the same error in jQuery UI 1.10.3 when re-opening a dialog after partial postbacks in asp.net. I found out that this was due to a variable $.ui.dialog.overlayInstances that is supposed to evaluate to 1 before the dialog is closed. Since every time the dialog is opened the variable is increased by 1, when the user pressed the close button my value often evaluated to 2 or more. My solution was to reset $.ui.dialog.overlayInstances to 1 every time I opened the dialog. So:
$("#myDiv").dialog("open");
$.ui.dialog.overlayInstances = 1;
I was working jquery-ui-1.12.1 and encountered the same error and as Emyr pointed out this bug has been fixed.
My first workaround used George Beiers approach. Close dialog1 before creating dialog2, then I would restore dialog1 after closing dialog2. The result didn't look so well but it cleared the error in every browser except Internet Explorer.
Turns out there was a function that was attempting to closed my dialog1(already closed) before closing dialog2. Once I reordered the code I was able to keep dialog1 open while I displayed dialog2.
My suggestion if you are having trouble fixing this issue is to add a console log message on the beforeClose and open events to keep an eye for odd behavior.
I remember that error.
For me was
I tried to open a modal by code, then I opened other modal also by code...
They opened well... but if tried again, I received that error.
I had to close the first modal before open a new one.

JavaFX WebEngine timeout handling

I'm wondering if anyone has figured out a way to properly handle timeouts in the JavaFX 8 (jdk 1.8.0_31) WebView. The problem is the following:
Consider you have an instance of WebView and you tell it to load a specific URL. Furthermore, you want to process the document once it's loaded, so you attach a listener to the stateProperty of the LoadWorker of the WebEngine powering the web view. However, a certain website times out during loading, which causes the stateProperty to transition into Worker.State.RUNNING and remain stuck there.
The web engine is then completely stuck. I want to implement a system that detects a timeout and cancels the load. To that end, I was thinking of adding a listener to the progressProperty and using some form of Timer. The idea is the following:
We start a load request on the web view. A timeout timer starts running immediately. On every progress update, the timer is reset. If the progress reaches 100%, the timer is invalidated and stopped. However, if the timer finishes (because there are no progress updates in a certain time frame we assume a time out), the load request is cancelled and an error is thrown.
Does anyone know the best way to implement this?
Kind regards
UPDATE
I've produced a code snippet with behavior described in the question. The only thing still troubling me is that I can't cancel the LoadWorker: calling LoadWorker#cancel hangs (the function never returns).
public class TimeOutWebEngine implements Runnable{
private final WebEngine engine = new WebEngine();
private ScheduledExecutorService exec;
private ScheduledFuture<?> future;
private long timeOutPeriod;
private TimeUnit timeOutTimeUnit;
public TimeOutWebEngine() {
engine.getLoadWorker().progressProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
if (future != null) future.cancel(false);
if (newValue.doubleValue() < 1.0) scheduleTimer();
else cleanUp();
});
}
public void load(String s, long timeOutPeriod, TimeUnit timeOutTimeUnit){
this.timeOutPeriod = timeOutPeriod;
this.timeOutTimeUnit = timeOutTimeUnit;
exec = Executors.newSingleThreadScheduledExecutor();
engine.load(s);
}
private void scheduleTimer(){
future = exec.schedule(TimeOutWebEngine.this, timeOutPeriod, timeOutTimeUnit);
}
private void cleanUp(){
future = null;
exec.shutdownNow();
}
#Override
public void run() {
System.err.println("TIMED OUT");
// This function call stalls...
// engine.getLoadWorker().cancel();
cleanUp();
}
}
I don't think that you can handle timeouts properly now. Looks at this method. As you can see it has hardcoded value for setReadTimeout method. Is it mean that SocketTimeoutException exception will be raised after one hour of loading site. And state will be changed to FAILED only after that event.
So, you have only one way now: try to hack this problem use Timers as you described above.
P.S.
Try to create issue in JavaFX issue tracker. May be anyone fixed it after 5 years...
I have the same problem and used a simple PauseTransition. Same behavior, not so complicated. =)

Strange crash when using the new PageCurl effect reading a PDF with MonoTouch and iOS 5.0

I get a strange crash when using the new PageCurl effect reading a PDF with MonoTouch and iOS 5.0.
I've made a simple test case project for MonoDevelop 2.8 and uploaded on GitHub here:
https://github.com/Emasoft/IpaziaPDFReader
It seems that something is getting GCd too early and killing the application, but I can't find what. I've tried to dispose everything in many ways, but in vain. I've already submitted the project tarball to the Xamarin team, but they weren't able to solve the problem.
Is there something broken in the iOS NavigationController memory management? Or am I missing something?
Any help is appreciated, thanks!
UPDATE: I've tried to remove all subviews and sublayers before disposing the objects in all classes, but it still crashing. The only way I found to avoid the crash is to NEVER dispose of the PDF pages, adding them to a List before releasing them, but this is not a viable solution, because in that way memory is consumed rapidly for PDF with many pages and the app crashes anyway when unable to allocate memory for the next page.
Another way to avoid the crashes is to dispose of the PDF pages BEFORE turning the pages, forcing the dispose method on the page controller before creating a new page controller, but in this way the current page will become blank and the transition curls an useless empty page. No solution seems to work.
I've updated project on GitHub with the 3 different solutions I've tried (look in the PageDataSource class), you can uncomment them one at time to see the problems.
//SOLUTION 1
void ForcingPageControllerDispose (BookPageController oldPageController)
{
// --- IF YOU UNCOMMENT THIS, THE CRASHES GO AWAY, BUT THE PAGE IN THE TRANSITION IS BLANK, SO IS NOT VIABLE
currentPageController.View.RemoveFromSuperview ();
currentPageController.Dispose ();
}
//SOLUTION 2
void DisposeThePageControllerWhenDidFinishAnimating (BookPageController oldPageController, UIPageViewController pageViewController)
{
// --- IF YOU UNCOMMENT THIS, THE CRASHES STILL HAPPEN
pageViewController.DidFinishAnimating += delegate(object sender, UIPageViewFinishedAnimationEventArgs e) {
if (currentPageController != null) {
currentPageController.View.RemoveFromSuperview ();
currentPageController.Dispose ();
Console.WriteLine ("currentPageController disposed for page: " + currentPageController.PageIndex);
}
};
}
//SOLUTION 3
void BackupUnusedPagesToAvoidBeingGCd (BookPageController oldPageController)
{
// --- IF YOU UNCOMMENT THIS, THE CRASHES GO AWAY, BUT THE PAGES ARE NOT GARBAGE COLLECTED AND AFTER MANY PAGES IPHONE IS OUT OF MEMORY AND IT CRASHES THE APP
if (parentController.book_page_controllers_reference_list.Contains (currentPageController) == false)
parentController.book_page_controllers_reference_list.Add (currentPageController);
}
I've already submitted the project tarball to the Xamarin team, but they weren't able to solve the problem.
I'm pretty sure the person assigned to your case will come up with the solution. The bigger the test case the more time it can take.
From a quick view the following, in your AppDelegate.cs, is wrong:
PageTurnViewController viewController = new PageTurnViewController ("PageTurnViewController", null);
window.AddSubview (viewController.View);
since the local viewController instance won't have any reference to it once FinishedLaunching returns and the GC will be able to collect it. However it's needed (on the native side) for keep the View fully valid. This can lead to crashes (there could be other cases too, that's the first and only file I checked this morning).
The solution is to promote the viewController to a field. That will make it alive even when the method returns, making it unavailable to collection.
UPDATE
I had a quick look at your code on github.
You are adding (sub)view but you never remove them (when the GC will Dispose them it won't remove them from the super view);
You are losing references to views, e.g. in PageDataSource.cs
newPageController = new BookPageController (nextPageIndex, parentController.currentPDFdocument, parentController);
return newPageController;
After the first page there will already be a reference stored in newPageController which will be overwritten and make the object collectable bug the GC. Since (sub)views are never removed there could still be native reference to them leading to crashes.
For debugging you can add your own finalizers, e.g.
~BookPageController ()
{
Console.WriteLine ("bu-bye");
}
and put breakpoints in them. If they get hit, while you think it's still in use, then you likely found a problem.
Since you are taking a dependency on iOS 5 new features, you should also adopt the new View Controller Containment APIs in iOS 5 that solve a few problems with view controllers.
I suggest you check the WWDC Video and slides for for Session 102 "Implement UIViewController Containment".

Resources