C# WebBrowser Body empty - webbrowser-control

.Net Version 4.5.2
When loading a page that returns 302, the browser control does load the redirected URL, presumably correctly. When you examine the call results in Fiddler, the entire correct page is returned from the server.
Now, the page never 'Completes' for a long time, but does go into an 'Interactive' state where you should be able to interact with it, no?
When I look at the WebBrowser's Document, which is not null, it has no content, so you can't access Body, or any element.
The results is encoded - gzip. You have to Decode it in Fiddler to see it.
How do I get the returned HTML to be available in the Document property?
using (browser = new WebBrowser()) {
browser.ClientSize = new Size(800, 600);
browser.ScrollBarsEnabled = false;
browser.ScriptErrorsSuppressed = true;
System.Windows.Forms.HtmlDocument doc = null;
browser.Navigate(_url);
// Wait for control to load page
while (browser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
if (browser.ReadyState == WebBrowserReadyState.Interactive && browser.Document != null)
{
// give some redering time..
Thread.CurrentThread.Join(500);
Application.DoEvents();
doc = browser.Document;
break;
}
}
var elements = browser.Document.GetElementsByTagName("INPUT");
foreach (HtmlElement element in elements)
{
if (element.Name.ToLower().Contains("theInputFieldName"))
{
element.InnerText = NewFieldContentsVariable;
}
//to get the text use : string value = element.GetAttribute("value");
//to set the text use : elemet.InnerText = "something";
}
...

Related

Storing an iframe's elements (the ones in the page that it is has loaded -- like <table>) in a variable

How can I store the elements of an iframe into a variable?
This is something I want to happen within the parent.
I know the elements should have an id to implement this repeatedly proposed solution that does not work:
var foo = document.getElementbyId([IFRAME ID]).contentWindow.document.getElementbyID([ELEMENT ID]);
nor does this code work:
var foo = document.getElementbyId([IFRAME ID]).contentDocument.getElementbyID([ELEMENT ID]);
Saving each section into individual variables makes no difference.
i.e.
var x = document.getElementbyId([IFRAME ID]);
var y = (x.contentDocument || x.contentWindow.document);
var foo = y.getElementbyID([ELEMENT ID]);
What works? Please demonstrate a solution in jfiddle.
Thanks.
UPDATE:
I tried running this function with the iframe id passed into it (on my site there is a jukebox page which is loaded into the main iFrame and it has an iFrame itself -- which has an id called 'albumcover'):
function showIframeContent(id) {
var iframe = document.getElementById(id);
try {
var doc = (iframe.contentDocument)? iframe.contentDocument: iframe.contentWindow.document;
alert("The jukebox page's iframe URL is" +
doc.getElementById('albumcover').contentWindow.location.href);
}
catch(e) {
alert(e.message);
}
return false;
}
I then received this message:
[ Permission denied to access property "href" ]
-- 100% of my site, all referenced data...everything, is within a public_html folder...same domain, same hosting service area...the works.
What in the world is going on?
Thanks again.

Firefox setResponseHeader isn't working

I'm working on a web application where I need to access elements of an iFrame using JavaScript. To do that, the iFrame has to send an "Allow-Control-Allow-Origin: *" header to the browser.
Unfortunately this doesn't happen, that's why I'm using an extension to modify the response headers, but for some reason, setResponseHeader doesn't work.
It gets even more confusing since I'm using setResponseHeader to strip X-Frame-Options, but when I'm setting a custom header, it just won't work.
I'm using Firefox's "Inspect Element"'s Network tab to observe the requests, and while it shows the request header being set correctly, it doesn't show the response header.
That's how I'm setting the request and response headers.
var chrome = require("chrome");
chrome.Cc["#mozilla.org/observer-service;1"].getService( chrome.Ci.nsIObserverService ).addObserver({
observe : function(subject, topic, data) {
var channel = subject.QueryInterface( chrome.Ci.nsIHttpChannel );
channel.setRequestHeader("x-mysite-extended", "somedata", false);
}
},"http-on-modify-request",false);
chrome.Cc["#mozilla.org/observer-service;1"].getService( chrome.Ci.nsIObserverService ).addObserver({
observe : function(subject, topic, data) {
var channel = subject.QueryInterface( chrome.Ci.nsIHttpChannel );
channel.setResponseHeader("x-mysite-extended", "somedata", false);
}
},"http-on-examine-response",false);
Again, the request header works according to the Network tab. I tried http-on-modify-request to set the response header but that didn't work as well.
That's how I'm stripping of the X-Frame-Options header, which works.
let myListener =
{
observe : function (aSubject, aTopic, aData)
{
console.log(aTopic);
if (aTopic == "http-on-examine-response")
{
let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
try
{ // getResponseHeader will throw if the header isn't set
let hasXFO = channel.getResponseHeader('X-Frame-Options');
if (hasXFO)
{
// Header found, disable it
channel.setResponseHeader('X-Frame-Options', '', false);
}
}
catch (e) {}
}
}
}
var observerService = Cc["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(myListener, "http-on-examine-response", false);
I've been trying to solve this for two hours now so any help is appreciated. Thanks.
You're adding obserer for http-on-examine-response, with this you can only getResponseHeader
change it to http-on-modify-request. then you can setRequestHeader, you cant getResponseHeader in on modify request though.
This is scrap code but it worked for me:
observe : function(aSubject, aTopic, aData) {
// Make sure it is our connection first.
if (aSubject == channel) {
//this is our channel
//alert('is my mine');
cdxFire.myChannel = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
if (cdxFire.myChannel.requestMethod == 'GET') {
//alert('its a get so need to removeObserver now');
//cdxFire.observerService.removeObserver(modHeaderListener, "http-on-modify-request");
}
if (aTopic == 'http-on-modify-request' && cdxFire.myChannel.requestMethod == 'POST') {
//can set headers here including cookie
try {
var xContentLength = httpChannel.getRequestHeader('Content-Length');
var xContentType = httpChannel.getRequestHeader('Content-Type');
//alert('content length is there so change it up');
cdxFire.myChannel.setRequestHeader('Content-Type','',false);
cdxFire.myChannel.setRequestHeader('Content-Type',xContentType,false);
cdxFire.myChannel.setRequestHeader('Content-Length','',false);
cdxFire.myChannel.setRequestHeader('Content-Length',xContentLength,false);

How do I force razor to switch back to client side code?

I've got the following code in one of my views
#if (ViewBag.LoginInfo != null)
{
var loginToken = "#ViewBag.LoginInfo.Token";
var loginUser = "#ViewBag.LoginInfo.UserNameJs";
var notifyUrl = "#ViewBag.LoginInfo.NotificationUrl";
}
The code between { } should be rendered to the page as javascript, however it seems to be getting run as serverside code. I'm aware razor switches back to client code when it sees html in this case the code is valid as C# and javascript. How to I force everthing between { } to be written to the page as javasript?
Thanks
Alternatively use #:
#if (ViewBag.LoginInfo != null)
{
#:var loginToken = #Html.Raw(Json.Encode(ViewBag.LoginInfo.Token);
#:var loginUser = #Html.Raw(Json.Encode(ViewBag.LoginInfo.UserNameJs);
#:var notifyUrl = #Html.Raw(Json.Encode(ViewBag.LoginInfo.NotificationUrl);
}
You could wrap them in <text> tags:
#if (ViewBag.LoginInfo != null)
{
<text>
var loginToken = #Html.Raw(Json.Encode(ViewBag.LoginInfo.Token);
var loginUser = #Html.Raw(Json.Encode(ViewBag.LoginInfo.UserNameJs);
var notifyUrl = #Html.Raw(Json.Encode(ViewBag.LoginInfo.NotificationUrl);
</text>
}
Also notice how I have safely encoded the values. Your example will produce invalid javascript if for example your token contains the " character. You should never be mixing javascript and server side values without using a safe serializer as shown in my example.

actionscript 2.0 input text box

So, here's what I'm trying to do, and I, frankly, believe it should be obvious, but I can't figure it out. I am creating a very simple Artificial Intelligence simulation. And in this simulation there's an input box at the bottom of the screen (called "input" exactly). "input" has a variable in its properties that is called "inbox" (exactly). Using a key listener the script calls up a function when the enter button is pressed. This function has 2 if statements and an else statement which dictate the responses of the AI (named "nistra"). The problem is this, When I type in what I want to say, and hit enter, it always uses the second response ("lockpick" in the code below). I have tried variations on the code but I still don't see the solution. I believe the problem is that the "typein" variable holds all the format information from the text box as well as the variable, but I could be wrong, that information is in here as well, underneath the code itself. Any help I can get would be greatly appreciated.
var typein = ""; //copies the text from inbox into here, this is what nistra responds to
var inbox = ""; //this is where the text from the input text box goes
var respond = ""; //nistra's responses go here
my_listener = new Object(); // key listener
my_listener.onKeyDown = function()
{
if(Key.isDown(13)) //enter button pressed
{
typein = inbox; // moves inbox into typein
nistraresponse(); // calles nistra's responses
}
//code = Key.getCode();
//trace ("Key pressed = " + code);
}
Key.addListener(my_listener); // key listener ends here
nistraresponse = function() // nistra's responses
{
trace(typein); // trace out what "typein" holds
if(typein = "Hello") // if you type in "Hello"
{
respond = "Hello, How are you?";
}
if(typein = "lockpick") // if you type in "lockpick"
{
respond = "Affirmative";
}
else // anything else
{
respond = "I do not understand the command, please rephrase";
}
cntxtID = setInterval(clearnistra, 5000); // calls the function that clears out nistra's response box so that her responses don't just sit there
}
clearnistra = function() // clears her respond box
{
respond = "";
clearInterval(cntxtID);
}
// "typein" traces out the following
<TEXTFORMAT LEADING="2"><P ALIGN="CENTER"><FONT FACE="Times New Roman" SIZE="20" COLOR="#FF0000" LETTERSPACING="0" KERNING="0">test</FONT></P></TEXTFORMAT>
Since ActionScript is based on ECMAScript I'm pretty sure that you need to use == instead of = for equality comparison.
Right now your code works like this:
if(typein = "Hello") { // assign "Hello" to typein. always true.
respond = "Hello, How are you?";
}
if(typein = "lockpick") { // assign "lockpick" tot ypein. always true.
respond = "Affirmative";
}
// the else block is always false for obvious reasons
So you simply need to change the code like this:
if(typein == "Hello") {
respond = "Hello, How are you?";
}
else if(typein == "lockpick") {
respond = "Affirmative";
}
else {
respond = "I do not understand the command, please rephrase";
}

Safari analog of chrome.tabs.update or loadURI

I need analog of Chrome chrome.tabs.update or Firefox loadURI in Safari.
I've tried safari.application.activeBrowserWindow.activeTab.url = newURL but it doesn't work with bookmarklets urls like javascript:...
That's right, it doesn't work. You're going to have to pass a message to an injected script in a web page to open the bookmarklet. For example:
in the global page's script:
var activeTab = safari.application.activeBrowerWindow.activeTab;
var url = "javascript:alert('hello sucker')";
activeTab.page.dispatchMessage("pleaseLoadThisUrl", url);
in the injected script:
safari.self.addEventListener("message", handleMessage, false);
function handleMessage(e) {
if (e.name == "pleaseLoadThisUrl") {
window.location = e.message;
}
}
That will work.