How to get the document CDHtmlDialog after Asp.Net AJAX UpdatePanel - c++

When the page displayed in our CDHtmlDialog does an Asp.Net AJAX UpdatePanel we get a navigate event, but everything after that seems to be lost. We don't have a document anymore or get any mouse events on the page.

Looks like I made the original post as an unregistered user, so I don't think I can edit it. We were able to work around the original issue, but it came up again in a different context (really starting to hate CDHTMLDialog).
Here is the cause of the problem:
Javascript calls are causing a Navigate event, and CDHtmlDialog::OnBeforeNavigate gets called and disconnects and deletes the IHTMLDocument2. Unfortunately it's not a true Navigate since the page never changed. This means CDHtmlDialog::OnNavigateComplete is never called to get the document back.
To make matters worse, when I override CDHtmlDialog::OnBeforeNavigate I find the URL string is unreadable (bug)?
The simplest (best?) solution:
We need to intercept the Before Navigate event, and only call the CDHtmlDialog's _OnBeforeNavigate2 if the URL isn't a javascript action:
BEGIN_EVENTSINK_MAP(CMyHTMLDlg, CDHtmlDialog)
ON_EVENT(CMyHTMLDlg, AFX_IDC_BROWSER, DISPID_BEFORENAVIGATE2, OnBeforeNavigate2, VTS_DISPATCH VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_PBOOL)
END_EVENTSINK_MAP()
void CMyHTMLDlg::OnBeforeNavigate2(LPDISPATCH pDisp, VARIANT* URL,VARIANT* Flags, VARIANT* TargetFrameName, VARIANT* PostData,VARIANT* Headers, BOOL* Cancel)
{
...
if (URL != NULL)
{
// Check if navigation is to a folder..
CString url = CString(*URL);
if(url.Left(11) != _T("javascript:"))
{
_OnBeforeNavigate2(pDisp, URL, Flags, TargetFrameName, PostData, Headers, (BOOL*)Cancel);
// If dynamic linking MFC then the above handler doesn't exist. Need to call OnBeforeNavigate direct.
// This is from a code site, and it compiles, but I've never tested it to see if it works.
//CDHtmlDialog::OnBeforeNavigate(pDisp,(LPCSTR)URL);
}
}
}
Most of this is pretty standard for setting up a CDHtmlDialog subclass, and it's pretty simple actually, but it took me a bit to figure out how to handle JavaScript. Unfortunately, I'm not sure how this will work if the JavaScript is making dynamic changes to the page itself.
A couple notes:
If the navigation needs to be completely canceled here, then set *Cancel = TRUE and don't call _OnBeforeNavigate2. Be careful here because this also cancels any JavaScript actions.
It wasn't clear until I saw the source, but CDHtmlDialog::_OnBeforeNavigate2 just calls CDHtmlDialog::OnBeforeNavigate.

Related

How to detect URL schemes with .handlesExternalEvents and NSAppleEventManager simultaneously

I have a SwiftUI-based Mac app with multiple WindowGroups.
1. Opening different SwiftUI WindowGroups using URL schemes
To open those windows I am using URL schemes (like described here):
WindowGroup {
// ...
}
.handlesExternalEvents(matching: Set(arrayLiteral: "primaryWindow"))
... and then calling:
NSWorkspace.shared.open(URL(string: "myapp://primaryWindow")!)
☑️ This works just fine!
2. Detecting URLs called from outside the app
I also need to be able to recognise and handle URL schemes called from outside the app, like myapp://somePath?someParameter=1. I found this solution and set an event handler within my AppDelegate:
func applicationWillFinishLaunching(_ notification: Notification) {
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleGetURL(event:reply:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) )
}
☑️ This works just fine, too, and my #selector method is called like you would expect.
3. Problem: How to use .handlesExternalEvents and .setEventHandler simultaneously?
🛑 Here’s where the problem starts: After calling .setEventHandler my WindowGroups no longer react on called URLs and I remain unable to open new windows.
That somehow makes sense since I’ve registered an event handler in AppDelegate specifically for kAEGetURL but I have no idea how to implement both features simultaneously. Looking forward for your advice!

How to know if current page comes from Forward or from Back, Ionic2

I am currently working on an Ionic2 project. On one page (e.g. PageB) I am showing a Loader (inside ionViewWillEnter() event) till Ajax request success, after that loader.dismiss() called. It is working perfectly. After ajax request User click on something to goto next page(e.g : PageC). But when user comes back from PageC to PageB, loader is again visible.
I want to know if there is any function, so that On PageB load I can know if the page is transitioned from PageC(from history), and prevent loader loading.
Smaple code for PageB is
ionViewWillEnter()() {
this.presentLoading();
}
presentLoading() {
this.loader = this._loadingCtrl.create({
content: "Please wait..."
});
this.loader.present();
}
Instead of putting the ajax request in ionviewWillEnter you could set the same call and present loading call inside either ngOnInit or ionViewDidLoad.
ngOnInit(){
this.presentLoading();
}
These lifecycle hooks are called only once during initial page load.If it makes sense to put the ajax call in this hook, it will provide the same effect and loader will not be shown when user returns from PageC to PageB.

How can you check if the user's browser supports Google Caja?

I'm using Google Caja to sanitize user input on my site. I'm currently processing the user's input inside the callback I pass to caja.whenReady(). However, on Microsoft Edge, the callback is never called because Edge can't be made safe by Caja. In the event that Caja doesn't work, I want to fall back to processing the user's content server side where I'll simply strip out all JavaScript.
How can I check if Caja works with the user's browser?
The code below will give you a function, browserSupportsCaja() that will return true at any time after Caja calls its whenReady() callbacks. This way you can determine if Caja is supported after it initializes.
If you check for Caja support before it finishes initializing, then you will get a false negative. To catch that, just put the code that you want to execute after Caja is ready in a whenReady() callback and assume that Caja is not available anywhere else.
caja.initialize({
cajaServer: 'https://caja.appspot.com/'
});
function browserSupportsCaja() {
return browserSupportsCaja.return_value;
}
browserSupportsCaja.return_value = false;
caja.whenReady( function() {
browserSupportsCaja.return_value = true;
});

Accessing Firefox tab element in nsIWebProgressListener::OnStateChange using C++

I am developing extension for Firefox 3.0-3.5 versions using VS2008.
I want to set attribute to a tab once the document load request completes within that tab window.
So in OnStateChange method, I am checking for document load.
I have used STATE_STOP & STATE_IS_DOCUMENT for it.
I want to determine which tab window has been associated with particular document request.
I have valid DOM Document pointer got from nsIWebProgress *aWebProgress which is 1st input
parameter of OnStateChange.
if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_DOCUMENT))
{
nsCOMPtr<nsIDOMWindow> domwin;
nsCOMPtr<nsIDOMDocument> domDoc;
aWebProgress->GetDOMWindow(getter_AddRefs(domwin));
domwin->GetDocument(getter_AddRefs(domDoc));
}
I have tried to get nsIDOMDocumentXBL pointer by QIing nsIDOMDocument pointer(domDoc in my example) but it fails with Error code 0x80004002 (2147500034) i.e.NS_ERROR_NO_INTERFACE.
How do I get the tab element corresponding to document load request.
Could any one please help me?
Thanks in Advance,
Vaibhav D. Gade.
IF I understood the question correctly and you want a for a content window, you probably need https://developer.mozilla.org/en/Working_with_windows_in_chrome_code#Accessing_the_elements_of_the_top-level_document_from_a_child_window to get the chrome window, then run the implementation of gBrowser.getBrowserForDocument in the chrome window.
You'd save yourself a lot of time if you stopped writing C++ and switched to JS for such things.

How to return HTTPResponse from ASMX web service to consumer web page

I am working on an ASMX web service; trying to create a method that will download a document from a server and show the document in the browser (the calling .aspx web page). My service builds without error but I get the following error when I try to "Add Web Reference" in my Proxy class project:
System.Web.HttpResponse cannot be serialized because it does not have a parameterless constructor.
Here is a snippet of the code in .ASMX file:
public class FileService : System.Web.Services.WebService
{
[WebMethod]
public void DownloadDocument(string URI, HttpResponse httpResponse)
{
int DownloadChunkSize = (int)Properties.Settings.Default.DownloadChunkSize;
// some more code here....
using (httpResponse.OutputStream)
{
// more code here...
}
}
}
I see I am confused about how to send back an HttpResponse from a web service to a requesting web page. Could someone please give me a tip on how to do this? Thanks.
You should look into web handlers (.ashx). They are perfect for what you are trying to achieve.
For example:
public class Download : IHttpHandler, IRequiresSessionState {
public void ProcessRequest(HttpContext context) {
var pdfBytes = /* load the file here */
context.Response.ContentType = #"Application/pdf";
context.Response.BinaryWrite(pdfBytes);
context.Response.End();
}
}
UPDATE:
An ashx handler is actually a replacement to aspx. Basically, it has no UI but still processes get / post requests just like an aspx page does. The point is to reduce the overhead generated by running a regular aspx page when all you need to do is return some simple content (like a file...) or perform a quick action.
The IRequiresSessionState interface allows you to use the SESSION object like any other page in your site can. If you don't need that, then leave it off.
This site has an interesting walk through on how to create one. Ignore Step 4 as you probably don't care about that.
Assuming that you have a regular page (aspx) that has a link to your document: The link in the aspx file would actually point directly to your ashx handler. for example:
Click Here
Then the code in the ProcessRequest method of the ashx handler would do whatever calls it needed (like talk to your DLL) to locate the document then stream it back to the browser through the context.Response.BinaryWrite method call.
That is not how standard ASMX web services work. If you want to make your own handler, or even use an ASPX page to deliver the doc, you are fine, but the standard ASMX web service method of doing this is to actually return the bits of the document as an encoded blob.
If you want to roll your own, consider this article:
http://msdn.microsoft.com/en-us/magazine/cc163879.aspx
The web smethod (from asmx) returns an object, which can be serialized.
You need to create your method like:
[WbeMethod]
public byte[] DownloadDocument(string URI)
Or if the content is some text - return string.