Ionic 2/3 in-app-browser javascript injection - html

What I would like to do is open up a web page without it showing, inject javascript into it, and then proceed into my app.
The secondary page is a login page that I need to use but I don't want to show it in my app.
Therefore, I would like to open that page, use it, and most importantly, get the login information back, all without seeing the external login page.
I have my own login page to gather the information and a "login" button to kick it all off.
Here is what I have so far:
login(){
const browser = this.iab.create('https://authn.exampleLoginPage.com/login.aspx', "_blank","hidden=yes,location=no");
browser.executeScript({code:'document.getElementById("uxUserName").value="myUserName"'});
browser.executeScript({code:'document.getElementById("uxPassword").value="myPassword"'})
browser.executeScript({code:'document.getElementById("SubmitCreds").click();'})
.then( (value) => {
console.log("ob2 is ", value);
})
this.nav.setRoot(TabsPage);
}
login() gets called by clicking my login button.
I am testing this in chrome by running ionic serve and I'm encountering a couple problems. First, the code pulls up a new tab with the external website. Second, the javascript doesn't seem to be firing. I never get to the console log in the promise. I don't know what I'm missing here.

Related

Puppeteer - Is there a way to handle new windows in headless mode?

I'm working in an application that requires these types of login where a new window (no tab) pops up and ask you to login, in the same way that twitter or facebook do (or used to do), where it shows where to put your email and password, click "login" and then the window would close and the main window would receive the authentication and keep going.
I can do it in "headed" mode, when I click the authentication button, the window pops up and I get a grip of it with
const newWindow = (await browser.pages())[1]
and then I'd navigate like normal where in my case I only have to click a single button because I'm already logged in the page I'm trying to use for authentication
await newWindow.waitFor("//SomeXpath")
const buttonToClick= (await newWindow.$x("//SomeXpath"))[0]
await buttonToClick.click()
Again, in headed mode it works fine. but in headless mode is like this 2nd page would not open.
If I try:
console.log(await browser.pages())
I only see the main page where I open puppeteer
I've seen people talking about the "target" class, but it seems is for new tabs, and the examples I've found didn't work for me (or probably I wasn't able to understand and properly use them)
I'm afraid that what I'm trying to do is not possible and I'm chasing a ghost.
Thanks
Edited:
A snapshot of the window with the button I have to click
Snapshot of the new window
Also I've tried this, but it didn't work either:
const newPagePromise = new Promise(x => browser.once('targetcreated', target => x(target.page())));
const popup = await newPagePromise;
where popUp would be the new "page". But if I do a console.log(popup) it returns "null"

Paypal hybrid app

I have managed to integrate a donate paypal button in a Cordova app:
<form action='https://www.paypal.com/cgi-bin/webscr' method='post' target='_top'>
...
</form>
All works fine except that when the button is pressed, a new window appears and completly covers the app webview making it impossible for the user to go back to the app (the only way is killing the app process), which I think is a very bad user experience.
Things that I've tried:
target='_blank': same result
target='myIFrameName': Cross-domain problem
Post the form via ajax and put result in a div: Form must be calculated on the fly error (with $http.put in ionic, haven't tried with jQuery)
Please, any solution?
The best one would be to have the paypal window inside the current webview not covering header, as I could place a back button there (something like iframe solution that could work with cross domain) but also could be with placing a link to go back in the paypal donate page. I haven't investigated deeper enought the paypal plugin at this location: https://github.com/paypal/PayPal-Cordova-Plugin. anyone knows if it could do the work? (I've already opened an issue there asking for this feature)
Why not use a inApp browser ? Cordova InAppBrowser
And call cordova.InAppBrowser.open( url, '_blank', 'location=yes'); on a button click function, or whatever suits you.
_blank = inside the app
_system = system's browser( will redirect you from app )

How to prevent reload of pages in Chrome Extension?

I have written a Chrome Extension to Clear TYPO3 CMS Caches right out of the browser's address bar.
Now I would like to add an optional feature, to clear the caches automatically on page refresh . That means, when the user presses F5, CTRL+R, clicks the reload icon in toolbar or clicks in context menu to "Reload", first my ajax script should be executed (to clear the CMS cache) and after it, the page may get reloaded.
Is there a possibility to do it with the Chrome API?
I tried first the window.onbeforeupdate event in content script - and this is triggered always when the page is reloading, but also if I close the window or switch to another website. And furthermore I can't tell the browser to wait for my ajax request here.
What works is to check in document.onkeydown event the keys 116 (F5) and 82 (R) with control key and use event.preventDefault(). But this will not cover the two other possible cases to refresh the cache.
Thanks!
I've found a solution. It does not really match my requirements, but it works (even better).
Chrome provides a webRequest API which allows you to modify or block all http requests.
chrome.webRequest.onBeforeRequest.addListener(
function (details) {
if (!severalConditionsToCheckIfIWantToDoTheMagic) {
return;
}
$.ajax(url, {
async:false,
complete:function () {
return {redirectUrl:details.url};
}
});
},
{urls:["<all_urls>"]},
["blocking"]
);
In this example first I check if I want to do the ajax request. If yes, the next step is no do the ajax request. It is important, that the request is not asynchronous. On complete I return the original url of the request, which is basically just a reload.
The reason why it does not really match my requirements, is that it will be triggered always, on any request, not just on reload. That means in my conditions I have to check against:
Other websites
Other request types (loading css, js or images are also request), I just need the type 'main_frame'
Some variables belonging to my extension
Now, the script will be also triggered when I click on a link which is on the website - but for my case this is fine.

How can I open my extension's pop-up with JavaScript?

I am trying to write a JavaScript function that will open my extension like when the extension icon is clicked. I know how to open my extension in a new tab:
var url = "chrome-extension://kelodmiboakdjlbcdfoceeiafckgojel/login.html";
window.open(url);
But I want to open a pop-up in the upper right corner of the browser, like when the extension icon is clicked.
The Chromium dev team has explicitly said they will not enable this functionality. See Feature request: open extension popup bubble programmatically :
The philosophy for browser and page action popups is that they must be triggered by user action. Our suggestion is to use the new html notifications feature...
Desktop notifications can be used progammatically to present the user with a small HTML page much like your popup. It's not a perfect substitution, but it might provide the type of functionality you need.
Chrome team did create a method to open the popup programmatically, but it's only enabled as a private API, and plans to make it generally available have stalled due to security concerns.
So, as of March 2018 as of now, you still can't do it.
Short answer is that you cannot open browserAction programmatically. But you can create a dialog with your content script which emulates your browserAction and display that isntead (programmatically). However you won't be able to access your extension's background page from this popup directly as you can from your popup.html. You will have to pass message instead to your extension.
As mentioned there is no public API for this.
One workaround I have come up with is launching the extension as an iframe inside a content script with a button click. Whereby the background script emits the extension URL to the content script to be set as the iframe's src, something like below.
background.js
browser.runtime.onMessage.addListener((request) => {
if (request.open) {
return new Promise(resolve => {
chrome.browserAction.getPopup({}, (popup) => {
return resolve(popup)
})
})
}
})
content-scipt.js
const i = document.createElement('iframe')
const b = document.createElement('button')
const p = document.getElementById('some-id')
b.innerHTML = 'Open'
b.addEventListener('click', (evt) => {
evt.preventDefault()
chrome.runtime.sendMessage({ open: true }, (response) => {
i.src = response
p.appendChild(i)
})
})
p.appendChild(b)
This opens the extension in the DOM of the page the script is running on. You will also need to add the below to the manifest.
manifest.json
....
"web_accessible_resources": [
"popup.html"
]
....
You could emulate the popup by displaying a fixed html element on the page in the same location the popup would be and style it to look like the popup.
I had the same requirement: When the user clicks on the extension icon a small popup should open. In my case, I was writing an extension which will give updates on selective stocks whenever the icon is clicked. This is how my popup looked.
If you were having the same requirement then please read the answer below.
This is how my manifest.json file looked.
All the heavy lifting was handled by manifest.json file only. There is a section browser_action inside which there is a key called default_popup, just put the name of the HTML file that you want the popup to display.
I wanted my extension to work on all the pages that's why I added the attribute matches under content_scripts. I really didn't need to put the jquery file jquery-3.2.1.js inside the js array but the extension manager was not allowing me to keep that array empty.
Hope this helps, do comment if you have any doubt regarding the answer.

Execute a CGI each time a button was clicked without changing the current html page

I am starting my internship on a Home Server able to control mutliple domotics equipments from a web page. The global idea is that based on a click on a button, a certain script is spawned on the server and controls a microcontroller.
My tutor built a simple website he gave me, using AJAX to always stay on 1 page, and brings the menus according to user actions (they are hidden if not used, brought back to front if used).
I have set up an apache server which I configured to execute CGI scripts, and it works.
To always stay on one page, I used the '204 No Content' return trick, so that the server's answer to the page is 'I don't have anything to say, just stay on this page'.
But the one problem I have is that the CGI is launched only once. If I click the button for the first time it works, afterwards nothing happens.
I tried using the SSI (shtml) to use the in a button code instead of using a FORM with GET method but the script still won't execute twice.
I might be using the wrong tools. Should I keep going with CGIs ? Or is there something else (like AJAX, jquery) that actually is designed to do what I want ?
Thanks for having read.
EDIT : I have found a way around it (it's always when I'm desperate after looking for days for an answer that I go to forums and then find myself a nice solution in the next hour .... )
I used a basic link, and for some reason it has a different behaviour than using a button. Whatever. My interrogations on the technologies used still stand though :)
EDIT2 : My solution is crappy, for some reason the script is also called at page refresh (or when the page loads for the first time). It's strange, because since it's in the it should only be spawned when I click on it ...
Familiarize yourself with jQuery and its AJAX API. You can't make it not load a new page unless you use AJAX. Here is an example of what an AJAX call looks like:
$.ajax({
url: 'http://server.domain.com/cgi-bin/myfile.cgi',
data: {
x: 1,
today: '20110504',
user: 'Joe'
}
}).success(function(data, status, xhr) {
if (data)
alert(data);
});
That is for jQuery 1.5 or higher. You can run that whenever a certain button is clicked like this:
HTML for the button:
<input type="button" id="doThis"/>
JavaScript:
$(function() {
$('#doThis').click(function() {
//put AJAX sample shown above, here
});
});