I have a contentscript that essentially does a console.log to indicate that it has been injected into a page, and my manifest.json has all_frames set to true.
As a result, if I go to http://www.reddit.com/r/videos I see a message per frame and if I click on a video, I will also see a message coming from a script injected into the video's iframe. This indicates to me that if the page is dynamically modified to include an iframe, the contentscript will be injected into it.
When I go to http://www.html5video.org, I only get a message from one frame, but if I look at the DOM I see that there is an iframe for the video so I would expect my contentscript to be injected into it, but it is not.
My ultimate goal is to get a selector for the video on the page and I would expect to be able to do so by injecting code that looks for it into the iframe.
Help is appreciated.
I suspect that Chrome will inject your content scripts into an IFRAME that is part of the original page source which is the case with the reddit.com example - the IFRAMEs are part of the original page so Chrome can and will inject into those. For the html5video link the IFRAME is not part of the original source. However, if you inspect the elements you can see the IFRAME which suggests to me that the IFRAME has been dynamically loaded to the DOM. I see the same behaviour with an extension I have written so it seems consistent.
If you need to inject into the IFRAME then perhaps you can hook the DOM creation event and take the action you require:
document.addEventListener('DOMNodeInserted', onNodeInserted, false);
UPDATE:
What about this for http://html5video.org/ - using the following content_script code I can get the IFRAME and then VIDEO tag. Note: This approach/concept should also work pretty well too for Reddit.
content_script.js
console.log("content script for: " + document.title);
var timer;
document.addEventListener('DOMNodeInserted', onNodeInserted, false);
function onNodeInserted(e)
{
if(timer) clearTimeout(timer);
timer = setTimeout("doSomething()", 250);
}
function doSomething()
{
$media = $(".mwEmbedKalturaIframe");
console.log($media);
$video = $media.contents().find("video");
console.log($video);
}
manifest.json
{
// Required
"name": "Foo Extension",
"version": "0.0.1",
// Recommended
"description": "A plain text description",
"icons": { "48": "foo.png" },
//"default_locale": "en",
// Pick one (or none)
"browser_action": {
"default_icon": "Foo.png", // optional
"default_title": "Foo Extension" // optional; shown in tooltip
},
"permissions": [ "http://*/", "https://*/", "tabs" ],
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["jquery-1.7.1.min.js", "content_script.js" ],
"run_at": "document_idle",
"all_frames": true
}
]
}
See also: jQuery/JavaScript: accessing contents of an iframe
Related
Thumbnails from external urls are not loading. However, the post inspector tool loads it just fine.
Page I used to perform some tests: https://www.cnbc.com/2022/10/28/more-than-40percent-of-us-households-will-owe-no-federal-income-tax-for-2022.html
Things I've tried so far:
Add an extra parameter at the end of the url in order to clear linkedin cache.
Post Inspector Tool
I did some research but I wasn't successful on finding a solution.
I created a post using different links like youtube and stackoverflow. Thumbnails didn't show up either.
I made sure each page has those required meta(open graph) tags that allows the crawler to retrieve information.
Here's an example of one of those API requests I've been calling to(I got this from the docs):
`
{
"author": "urn:li:person:{ID}",
"lifecycleState": "PUBLISHED",
"specificContent": {
"com.linkedin.ugc.ShareContent": {
"shareCommentary": {
"text": "Learning more about LinkedIn by reading the LinkedIn Blog!"
},
"shareMediaCategory": "ARTICLE",
"media": [
{
"status": "READY",
"description": {
"text": "Official LinkedIn Blog - Your source for insights and information about LinkedIn."
},
"originalUrl": "https://www.cnbc.com/2022/10/28/more-than-40percent-of-us-households-will-owe-no-federal-income-tax-for-2022.html",
"title": {
"text": "Official LinkedIn Blog"
}
}
]
}
},
"visibility": {
"com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"
}
}
`
In the Share Media object, you're missing the media attribute. It accepts LinkedIn URN so you'll need to upload the image. Personally, I'm not using that attribute but thumbnails that accepts image url. I don't see it in the docs anymore so something might have been changed. At least it's still working for me and I haven't seen it deprecated in the changelog yet. Be careful with the image requirements as well. It accepts an image url with this signature
{
...,
"thumbnails": [{
"url": "https://image-url.com"
}]
}
I want to dynamicaly inject and load an iframe inside the background page. But every time, the request is canceled.
http://i.imgur.com/Puto33c.png
That used to work a week ago. I don't know where I'm wrong.
To reproduce this issue, I created a small extension :
manifest.js :
{
"name": "iframe background",
"version": "1.0.0",
"manifest_version": 2,
"browser_action": {
"default_title": "iframe"
},
"background": {
"persistent": false,
"scripts": ["background.js"]
}
}
background.js :
chrome.browserAction.onClicked.addListener(function() {
var iframe = document.createElement('iframe');
iframe.src = 'http://localhost:3000/';
iframe.onload = function() {
console.log(iframe.contentDocument); // return null
};
document.body.appendChild(iframe);
});
The page to load is not blocked by X-Frame-Options SAMEORIGIN.
I tried to put the iframe directly within a HTML background page with no luck.
I also tried to add an content_security_policy :
"content_security_policy": "script-src 'self'; object-src 'self'; frame-src 'self' http://localhost:3000/"
But the iframe still doesn't load.
Does someone has a workaround or a solution to this problem?
Thanks !
Chrome 58.0.3014.0 enables Site Isolation for extensions by default that makes the iframe load in a different renderer process handled by a separate chrome.exe OS process.
The 'canceled' message means that the extension's chrome.exe process canceled the request and it was handled by a different hidden chrome.exe process.
The correct approach is to declare a content script that will automatically run on the iframe URL and communicate to the background page. Note: only JSON-fiable data may be passed, in other words, you can pass innerHTML but not DOM elements. This is easy to handle though via DOMParser.
manifest.json additions:
"content_scripts": [{
"matches": ["http://localhost:3000/*"],
"js": ["iframe.js"],
"run_at": "document_end",
"all_frames": true
}],
iframe.js:
var port = chrome.runtime.connect();
// send something immediately
port.postMessage({html: document.documentElement.innerHTML});
// process any further messages from the background page
port.onMessage.addListener(msg => {
..............
// reply
port.postMessage(anyJSONfiableObject); // not DOM elements!
});
background.js:
var iframePort;
chrome.browserAction.onClicked.addListener(() => {
document.body.insertAdjacentHTML('beforeend',
'<iframe src="http://localhost:3000/"></iframe>');
});
chrome.runtime.onConnect.addListener(port => {
// save in a global variable to access it later from other functions
iframePort = port;
port.onMessage.addListener(msg => {
if (msg.html) {
const doc = new DOMParser().parseFromString(msg.html, 'text/html');
console.log(doc);
alert('Received HTML from the iframe, see the console');
}
});
});
See also a similar QA: content.js in iframe from chrome-extension popup
I'm looking at the MDN Javascript API example for bookmarks.create(). I'm trying to implement the example they have to learn how to make a folder:
function onBookmarkAdded(bookmarkItem) {
console.log("Bookmark added with ID: " + bookmarkItem.id);
}
chrome.bookmarks.create({
title: "bookmarks.create() on MDN",
url: "https://developer.mozilla.org/Add-ons/WebExtensions/API/bookmarks/create"
}, onBookmarkAdded);
This does nothing as far as I can tell. Any help or other examples of how to make a folder for bookmarks would be greatly appreciated.
Assuming you have added "bookmaks" to the permissions in your manifest.json file, then your code works as written to create a bookmark. Because your manifest.json file is not included in the question, we can not determine if that is the problem.
To create a bookmark folder, you either omit the url property or provide url:null in the object that you pass to bookmark.create()
Below is the complete, tested (on FF48.0.2 and Developer Edition, FF50.0a2), extension. It is wrapped in code that allows creating the bookmark when a browser_action button is clicked. I find it easier for testing to have things execute when a browser_action button is clicked rather than just on install/Firefox run. It will:
Create a bookmark titled and linked: bookmarks.create() on MDN
Create a bookmark folder My Bookmark Folder A
Create a bookmark folder My Bookmark Folder B
Create a bookmark folder My Bookmark Folder B.1 within My Bookmark Folder B
All of these are created under "Other Bookmarks" because no parentId is provided when calling bookmark.create() for any of them which are not children of a bookmark folder this extension creates.
background.js:
//* For testing, open the Browser Console
try{
//alert() is not supported in Firefox. This forces the Browser Console open.
// This abuse of a misfeature works in FF49.0b+, not in FF48
alert('Open the Browser Console.');
}catch(e){
//alert() throws an error in Firefox versions below 49
console.log('Alert() threw an error. Probably Firefox version below 49.');
}
//*
chrome.browserAction.onClicked.addListener(function(tab) {
doBrowserAction();
});
function doBrowserAction(){
console.log('Background: Doing action');
createABookmark();
createABookmarkFolder();
createABookmarkFolderWithinABookmarkFolder();
}
function onBookmarkAdded(bookmarkItem) {
console.log("Bookmark added with ID: " + bookmarkItem.id, bookmarkItem);
}
function createABookmark(){
chrome.bookmarks.create({
title: "bookmarks.create() on MDN",
url: "https://developer.mozilla.org/Add-ons/WebExtensions/API/bookmarks/create"
}, onBookmarkAdded);
}
function createABookmarkFolder(){
chrome.bookmarks.create({
title: "My Bookmark Folder A",
url: null
}, onBookmarkAdded);
}
function createABookmarkFolderWithinABookmarkFolder(){
chrome.bookmarks.create({
title: "My Bookmark Folder B",
url: null
}, bookmarkItem => {
onBookmarkAdded(bookmarkItem);
chrome.bookmarks.create({
title: "My Bookmark Folder B.1",
url: null,
parentId: bookmarkItem.id
},onBookmarkAdded
);
});
}
manifest.json:
{
"description": "Create a bookmark on browser_action button click",
"manifest_version": 2,
"name": "Demo: Create Bookmark",
"version": "0.1",
"applications": {
"gecko": {
//Firefox: must define id to use some features (e.g. option_ui)
"id": "demo-create-bookmark#example.com",
"strict_min_version": "48.0"
}
},
"permissions": [
"bookmarks"
],
"background": {
"scripts": [
"background.js"
]
},
"browser_action": {
"default_icon": {
"32": "myIcon.png"
},
"default_title": "Do Action",
"browser_style": true
}
}
Obviously, if you are going to use the various functions for more than a demo, you will want to make them more general purpose (i.e. passing callbacks, bookmark properties, etc.).
Note: Please see the section titled "General notes on testing and development of WebExtensions in Firefox" of this answer. Your statement, "This does nothing as far as I can tell", implies that you are not looking at the Browser Console for error messages or console logs.
I have a Ext JS Window with a spring form of user details. Additionally, I have an user validator in my controller, so that, if the form has errors i can see what errors are:
UserValidator userValidator = new UserValidator();
userValidator.validate(user, result);
if(result.hasErrors()){
return "RegisterUserForm";
My problem is relative to have this form inside a ExtJS window. If i return "RegisterUserForm" the browser goes to this form and show the errors but not in the window. It shows the form and errors in a new page and the url changes to /RegisterUserForm. (This is obvious) How can i show the same form with errors without having this problem?
Thank you
There are 2 options:
Change your server code to make that an AJAX call that returns only the data to be handled by your ExtJS code, rather than a form page
Make your Ext.window.Window use an iFrame with the /RegisterUserForm url:
ex:
Ext.create('Ext.window.Window', {
layout: 'fit',
//other config here
items: [{
xtype: 'component',
autoEl: {
itemId: 'iframe',
tag: 'iframe',
src: '/RegisterUserForm',
frameBorder: 0
}
}]
}).show()
I'm trying to add a button into the Gmail compose toolbar at the Insert section specifically. I've seen an extension that does just that, so I know its possible but I'm confused on how to do it.
I'm using the content_Script to javascript inject into the webpage but the compose window is in an iframe window which apparently you aren't allowed to inject into because the iframe loads after the content_script even with the "run_at": "document_end".
Also another thing I'm confused on is that Gmail has all their id tags randomizing so how could I know what tag to inject into if they are always different every time I compose an email.
So could anyone help me out with this an let me know how to go about using a content_script to inject into an iframe and how to get around GMail id tags always randomizing/being different.
{
"name": "Test Gmail",
"version": "0",
"description": "Test Gmail",
"permissions": ["tabs", "http://*/*", "https://*/*"],
"content_scripts": [
{
"matches": [ "http://*/*", "https://*/*"],
"css": ["mystyles.css"],
"js": ["myScript.js"],
"run_at": "document_end",
"all_frames": true
}
]
}
Use JQuery and listen for the even "DOMNodeInserted". After that you want to use JQuery to locate where you want to insert the button or whatever using the function $(selector, context); to search for the parent. GMail id name is all done dynamically so you have to try search for something that doesn't change such as the html tag or class name's.