Injection scripts in Safari extensions don't fire in Youtube - javascript

While creating a Safari extension, I tried adding an End Script on Youtube pages. The script runs when the first Youtube page loads. The problem is that if I click any of the Youtube links in the page, nothing happens. However, if I open the link in a new tab, it works like a charm. Any idea why this happens?
The code is just a simple alert:
if (window.top === window) {
alert("Hello World");
}
and the pattern I used for the Allowed Domains is:
*.youtube.com

Youtube is a single page application. It loads required parts via XHR without reloading the page.
You can use dom mutation events to detect changes.

Related

$(document).ready not firing

I have a content script from a chrome extension injected in a youtube page.
Something like:
$(document).ready(function () {
console.log("[INFO] Changes detected");
myFunc();
}
When I refresh the script executes as expected. When I navigate in between pages,
ready() does not fire. Does this mean that the document does not change? Inspecting the
elements it obviously does.
Why isn't .ready() firing while navigating on a page?
When navigating between /watch?v=VideoID videos on YouTube, you are essentially staying on the same page. Elements of the page get replaced with the help of XHR requests, but the document itself does not change.
You can see this if you open the Network tab and watch what happens when you navigate to a new video:
Notice how document is not any one of the request types there.
New documents are only loaded when you see document get requested, like in the following, where I press Enter from the address bar:
$(document).ready( only fires when a new page is loaded, not when parts of the current page get replaced with .innerHTML etc.
If you want to detect when parts of the page get replaced, use a MutationObserver.

Open a tab and run script

Below doesn’t work:
window.open(‘javascript:{do something here}’)
Some security error and asking for unsafe-inline keywordenter code here
I need to open a new window and navigate to a url and find a button and click it.
All i have are urls(hundreds of em) I’m looping and using promises for each url. The problem is the script doesn’t work because the page is reloaded as the link is clicked. Therefore it needs to be opened in new tab then I can run the script (of clicking button to download) as the link is opened.
var lk=[
{
"key": "www.someurl.com",
"value": "somefile"
},
{
"key": "someurl",
"value": "somefilename"
}];
p=Promise.resolve();
for(i=0;i<lk.length;i++){
p=p.then(new Promise(_=>{
var link = document.createElement("a");
link.download = lk[i].value;
link.href = lk[i].key;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
setTimeout(()=>{
_();
},30000);
}));
console.log('Completed '+i);
}
Above script stops working as page is reloaded on link.click() in chrome console
I tried puppeteer, it has download issues. Any suggestions are appreciated.
Thanks
For security reasons, browsers isolate JavaScript code running on different origins (an origin is the combination of protocol, domain and port). While you can open a page on a different origin (by redirecting, opening a new window or adding a frame on the current page), you can't directly interact with it. So it's impossible for code on one page to open a different page and click on the button on that page.
The only way to work around this in a browser is to write a browser extension or user script. Browser extensions and user scripts are both higher privileged and able to interact with pages that are not under their control, but they need to be installed in the browser, and access to sites needs to be approved by the user (usually during installation).
I am creating another answer because you changed the question.
Don't create a link and then click on it, it will surely break the script due to reloading. instead, use ajax or https://www.npmjs.com/package/fetch. these will call the given URL in the background. but then you will not be able to click the button.
So I would suggest, you create an iframe with the URL, and then maybe try clicking the button.
If this would be possible, it would be a huge security issue. You could use it to lure somebody to your page, then open their online bank in new tab and make a transaction for example.
If you have control over the page you are opening in the new tab then you could pass some query parameter and listen to that parameter in the new page and invoke some javascript if this parameter is set.
If you want to run a script that will trigger a button on a new tab, and that tab is under your control, then you can achieve this by supplying your tab with the following script:
window.onload = function() {
document.getElementById('my-button').click();
}
I would suggest using Jquery Ready Function because it will be triggered once everything on the page is loaded.
Maybe open the URL into an Iframe and then you can control its content. Something like this: Control iframe content with javascript/html
Then you can not only click the button, but you have complete access to its DOM. but make sure X-Frame-Options is not set for that website. otherwise, this option will not work.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
and if that doesn't work:
Then you may want to try:
https://github.com/puppeteer/puppeteer
https://devexpress.github.io/testcafe/
https://www.cypress.io/
These tools are used for automated testing, but you can use these for your purpose.
These tools work like a human click on any button. They themselves open a browser, click on the button and let you know, or download the item or anything.

Cordova inappbrowser redirect url to system browser Android only

In summery the question is: using the inappbrowser how do I load external urls using the system browser and stop them from being displayed in the inappbrowser?
More detail
I am using the inappbrowser to display a customer portal website, however there are external links on the portal that I want to display in the system browser.
What I want to be able to do is detect the external URL, open external link in system browser and then make sure the inappbrowser is still showing the same page before the external link is pressed.
I am using the loadstart event to detect the URL and then using window.open(url, '_system'); to open the system browser. The problem is that when the system browser closes the external page is also shown in the inappbrowser.
So initially after loading the system browser I initialised the inappbrowser again with the url I wanted to display. This is fine, but I loose all the session history and the next time the back button is pressed the inappbrowser closes down.
The next thing I tried was to use the execute script functionality:
app.inAppBrowserRef.executeScript({
code: "window.open('" + overrideUrl + "', '_blank');"
}, function () {
//alert("Redirected!");
});
This loads the link in the system browser and the page displayed when the system browser is closed is correct. The problem is that the view being displayed is not running my loadstart code, so if I click on the same external link it now loads in the same view and not the system browser. Also if I put some debug in I don't see any evidence that what I am seeing is in the inappbrowser or it does not have my code. I also tried executing window.location = overrideUrl, this didn't work either.
The odd thing is that when I open the url using the chromecustomtab plugin and not the systembrowser the executeScript works as required. So this is to do with running the execute script while the system browser is open. I need to support the system browser in case chrome is not installed on the device.
This must be a common problem so really hoping there is a solution out there.
Thanks in advance!
The problem is when the system browser opens the inappbrowser looses its events.I am opening a new question where the question is more relevant.

iframe with src starting with `http` automatically opens in safari rather than in Webapp

I've a WebApp(for ios) which have a lot of pages in it. Almost in all pages I've iframes with sources that start with http. When I click on this link of one of those pages, safari browser open up before I can see that web page. The problem I figured out is that every link starting with http will automatically open in new window of safari and without http it stays inside my webapp. How can I solve this problem? can I remove http:// from each page before the page load? or is there anyother solution for it?
<iframe src="http://www.google.com"/> Opens in safari, out of the webapp whereas <iframe src="www.google.com"/> opens in the same webapp page.

Developing website for iPad only - force all links to be opened in app mode

I'm building a small website that will be always be viewed on an iPad, I am using the meta tag:
<meta name="apple-mobile-web-app-capable" content="yes">
And adding the site to the homepage to force the iPad to treat it as an app. This eliminates the address bar and back buttons etc...
I have the site inside a frame set, initially the site will load up an index.htm landing page which has links to other pages containing <frameset>'s and <frame>'s. Each page has a navigation frame and a frame for displaying content. The content of the second frame will be an external webpage.
I had a problem where launching the site in app mode and clicking on the links in the landing page would result in a new window being opened in safari - essentially it would break out of the app context and load up safari, i resolved this with:
<script type="text/javascript">
$(document).ready(function () {
$('a').click(function (e) {
window.location = $(this).attr('href');
e.preventDefault();
});
});
</script>
Which keeps all links under my site loaded within the 'app'.
Now, here is the problem.
The frames that load the external webpages will obviously contain links, when clicking on these links in the frame this fires up safari and breaks out of the app context and the app goes back to behaving as it did before.
Is there a way of making sure that all links on the site open within the 'app', even those contained within the <frame> elements?
The overall goal here is to prevent the user from breaking out of the app and going off to do whatever they like on the net
I know you state that it's a website, but it seems like you're making something which resembles an app and I'm tempted to suggest using phonegap. http://phonegap.com/
The reason is, you're not going to be able to prevent the links opening in safari. Although Brainfeeder makes a good suggestion with loading external html into a div, but I think you're still going to have the same issue when users click links from external sites inside that div.
With phonegap all you'll have to do is create a new project, dump your code as it is into the www folder and straight away you'll have an app you can deploy to your iPad.
But the main thing which made me suggest this is a feature called inAppBrowser which will let you specify links to open in a foreground webview, so that when a user is finished viewing, they just click done and are returned to your app.
http://docs.phonegap.com/en/3.0.0/cordova_inappbrowser_inappbrowser.md.html#InAppBrowser
Appreciate it seems like a bit of overhead just to fix the safari issue, but might be worth considering.

Categories

Resources