Open new tab from Chrome Extension Context Menu - javascript

UPDATE:
So because of the way my folder is structured, it looks like instead of chrome-extension://meajimhgfmioppbkoppphhkbcmapfngh/index.html it should be chrome-extension://meajimhgfmioppbkoppphhkbcmapfngh/html/index.html. When I type this in manually into the search bar it works but is still not working when I update my code to this:
chrome.contextMenus.onClicked.addListener(function (result) {
if (result['menuItemId'] === 'open-sesame') {
chrome.tabs.create({ 'url': chrome.extension.getURL("/html/index.html") }, function (tab) {
})
}
})
I have a chrome extension where users are presented my extension as a new tab. A new feature I am implementing is the ability to switch back to the default google search page and now users can access the extension from the browser action context menu. I referenced this answer when trying to come up with a solution.
I am now stuck at the contextMenu since when I click on it, I come up to the page where it says file could not be accessed.
background.js
chrome.contextMenus.create({
title: "Open",
contexts: ['browser_action'],
id: 'open-sesame',
})
chrome.contextMenus.onClicked.addListener(function (result) {
if (result['menuItemId'] === 'open-sesame') {
chrome.tabs.create({ 'url': chrome.extension.getURL("index.html") }, function (tab) {
})
}
})
The url that the new tab opens to is chrome-extension://meajimhgfmioppbkoppphhkbcmapfngh/index.html which seems like it would be correct to open my extension but it is still not working for whatever reason.
Folder Structure
html
index.html
js
background.js
css
style.css

Turns out I had to add the right file pathing to access my index.html and update the extension to get it to work.

Related

Firefox extension: Open window and write dynamic content

I have developed a Chrome Extension and it's mostly compatible to firefox web-extensions API. Just one problem:
In Chrome Extension i have popup.js and background.js. User click's a button, popup.js does chrome.sendMessage to background.js where data is received and afterwards (popup.html may be closed meanwhile) i just call in background.js:
newWin = window.open("about:blank", "Document Query", "width=800,height=500");
newWin.document.open();
newWin.document.write('<html><body><pre>' + documentJson + '</pre></body></html>');
// newWin.document.close();
so that works fine in Chrome extension but not in firefox. I read here (https://javascript.info/popup-windows) that for safety reasons firefox will only open with a "button click event". And if i move above code to popup.js, inside button-click-evenListener, it will open this way (but i dont have the data prepared yet, thats really not what i want)
So i tried everything i found but i dont get the chrome.tabs.executeScript running. Here is my code with comments:
popup.js
// working in firefox and chrome (popup.js)
const newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write("Hello, world!");
// not working firefox: id's match, he enters function (newWindow) but document.write doing nothing (but no error in log)
// not working chrome: doesnt even enter "function (newWindow)""
chrome.windows.create({
type: 'popup',
url: "output.html"
}, function (newWindow) {
console.log(newWindow);
console.log(newWindow.id);
chrome.tabs.executeScript(newWindow.tabs[0].id, {
code: 'document.write("hello world");'
});
});
background.js
(created local output.html and gave several permissions in Manifest.json - tabs, activeTab, output.html, , about:blank)
// opening but executeScript not working in firefox: Unchecked lastError value: Error: The operation is insecure.
// opening but executeScript not working in chrome: Unchecked runtime.lastError: Cannot access contents of url "chrome-extension://plhphckppghaijagdmghdnjpilpdidkh/output.html". Extension manifest must request permission to access this host
chrome.tabs.create({
// type: 'popup',
url: "output.html"
}, function (newWindow) {
console.log(newWindow);
console.log(newWindow.id);
chrome.tabs.executeScript(newWindow.id, {
code: 'document.write("hello world");'
});
});
How can I get the data into the new window/popup from background.js - i can open an empty page from there, so it's only about getting executeScript() running
Thanks to #wOxxOm for pointing me to a data URI to transport the json document into the browser from background.js.
While searching for a javascript method to build a data URI i found this thread, with the suggestion to create a Blob :
https://stackoverflow.com/a/57243399/13292573
So my solution is this:
background.js
var documentJson = JSON.stringify(documents, null, 2)
let a = URL.createObjectURL(new Blob([documentJson]))
chrome.windows.create({
type: 'popup',
url: a
});

Debugging source files using chrome extension

I am trying to control the debugger using Chrome Extension.
I am using devtools-protocol and chrome extension documentation, but I have no idea how to implement them as I have not seen any samples of the methods in use. I used the sample extension from here which shows how to pause and resume the debugger only, but that's absolutely no use to me. I tried to implement some methods in the sample, but nothing happens.
function onDebuggerEnabled(debuggeeId) {
chrome.debugger.sendCommand(debuggeeId, "Debugger.setBreakpointByUrl", {
lineNumber: 45825,
url: 'full https link to the js file from source tab'
});
}
The problem is that the js file I am trying to debug is loaded from the website inside the sources tab and it's huge, we talking 150k+ lines after its been formatted and it takes some time to load.
Now can anyone tell me how to simply add a break point inside the js file from the sources (USING CHROME EXTENSION) so it could be triggered on action which will then stops the debugger so I could change values etc?
Maybe you are placing wrong breakpoint location (formatted source), try working with original source and add columnNumber: integer
and here working version JavaScript pause/resume -> background.js:
install this extension
open https://ewwink.github.io/demo/Debugger.setBreakpointByUrl.html
click debugger pause button
click button "Debug Me!"
it will hit breakpoint on https://ewwink.github.io/demo/script.js at line 10
click debugger continue button, you will see message variable "hijacked..."
the code:
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// mod by ewwink
var attachedTabs = {};
var version = "1.1";
chrome.debugger.onEvent.addListener(onEvent);
chrome.debugger.onDetach.addListener(onDetach);
chrome.browserAction.onClicked.addListener(function(tab) {
var tabId = tab.id;
var debuggeeId = {
tabId: tabId
};
if (attachedTabs[tabId] == "pausing")
return;
if (!attachedTabs[tabId])
chrome.debugger.attach(debuggeeId, version, onAttach.bind(null, debuggeeId));
else if (attachedTabs[tabId])
chrome.debugger.detach(debuggeeId, onDetach.bind(null, debuggeeId));
});
function onAttach(debuggeeId) {
if (chrome.runtime.lastError) {
alert(chrome.runtime.lastError.message);
return;
}
var tabId = debuggeeId.tabId;
chrome.browserAction.setIcon({
tabId: tabId,
path: "debuggerPausing.png"
});
chrome.browserAction.setTitle({
tabId: tabId,
title: "Pausing JavaScript"
});
attachedTabs[tabId] = "pausing";
chrome.debugger.sendCommand(
debuggeeId, "Debugger.enable", {},
onDebuggerEnabled.bind(null, debuggeeId));
}
function onDebuggerEnabled(debuggeeId) {
chrome.debugger.sendCommand(debuggeeId, "Debugger.setBreakpointByUrl", {
lineNumber: 10,
url: 'https://ewwink.github.io/demo/script.js'
});
}
function onEvent(debuggeeId, method, params) {
var tabId = debuggeeId.tabId;
if (method == "Debugger.paused") {
attachedTabs[tabId] = "paused";
var frameId = params.callFrames[0].callFrameId;
chrome.browserAction.setIcon({
tabId: tabId,
path: "debuggerContinue.png"
});
chrome.browserAction.setTitle({
tabId: tabId,
title: "Resume JavaScript"
});
chrome.debugger.sendCommand(debuggeeId, "Debugger.setVariableValue", {
scopeNumber: 0,
variableName: "changeMe",
newValue: {
value: 'hijacked by Extension'
},
callFrameId: frameId
});
}
}
function onDetach(debuggeeId) {
var tabId = debuggeeId.tabId;
delete attachedTabs[tabId];
chrome.browserAction.setIcon({
tabId: tabId,
path: "debuggerPause.png"
});
chrome.browserAction.setTitle({
tabId: tabId,
title: "Pause JavaScript"
});
}
demo
EDIT: Just saw your comment about this being for a custom extension you're writing. My answer won't help you (sorry!), but it might help people that come here looking for a way of setting normal breakpoints in Chrome.
Maybe you already did, but... Have you tried just clicking the line number of the line you want to set the breakpoint in?
Like this:
You can even enable or disable breakpoints in several different calls in the same line.
When the page is loaded, open Dev Tools with F12, then navigate to the JS file in the Sources panel, and add the breakpoints you want. Then, refresh the page to load it again -- Chrome will remember where you set the breakpoints and stop at them.
If you can modify the source code of the file that you want to debug, I would look use the debugger statement.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger
function potentiallyBuggyCode() {
debugger; //application will break here as long as chrome developer tools are open
}
function breakhere() {
debugger;
}
ok, for start you have to sendCommand Debugger.enable .. something like this:
var tabId = parseInt(window.location.search.substring(1));
window.addEventListener("load", function() {
chrome.debugger.sendCommand({tabId:tabId}, "Debugger.enable");
chrome.debugger.attach( tabId, "0.1" );
chrome.debugger.onEvent.addListener(onEvent);
});
then inside you onEvent you can set breaking points
function onEvent(debuggeeId, message, params) {
if (tabId != debuggeeId.tabId) return;
var res = Debugger.setBreakpointByUrl( 2, 'url-of-the-script-file' );
}
I would strongly suggest to check the sniffing section on this page: https://chromedevtools.github.io/devtools-protocol/ because I was able to see the json that get returned via WS protocol and that will help you to do pretty much anything you want.. I can't build you full extension, you are on your own man,,
I guess that you need to add somekind of DOM elemnet with list of scripts that you'll parse from Network.getResponseBody and then somekind of UX tool to pick that scripts and let users to debugging,, that process could take you some time :(
hope I have steered you in the right direction, good luck!

CrossRider API, get opened tabs title

I am using the CrossRider api to get the opened tabs, using there API I can get the title of the links in my bookmarks, however with there api I cannot use how to get the title of the urls in my opened tabs, I can just get the URL.
Does anyone know if this is achievable, if not then if there is some other way. Current I have to call a php script to make calls to the URLs and extract the title, this is getting too slow with a lot of tabs open
It would be great if you included a code snippet to show how your code works. However, in the absence of a snippet, I'm guessing that you are working in the background scope using an API method such as appAPI.tabs.getAllTabs. As you correctly surmised, the method does no not provide the title of the URL.
There are several way to work around this, on of which you mentioned, however, I prefer getting the information from the tab itself through messaging. For example, assuming you still need the information in the background scope:
background.js:
appAPI.ready(function($) {
appAPI.message.listener(function(msg) {
if (msg.action==='tab-info') {
doSomething(msg.data);
}
});
appAPI.message.toAllTabs({action:'get-tab-info'});
});
extension.js:
appAPI.ready(function($) {
appAPI.message.listener(function(msg) {
if (msg.action==='get-tab-info') {
appAPI.message.toBackground({
action:'tab-info',
data: {
tabId: appAPI.getTabId(),
url: appAPI.dom.location.href,
title: document.title
}
});
}
});
});
[Disclosure: I am a Crossrider employee]

Can we download a webpage completely with chrome.downloads.download? (Google Chrome Extension)

I want to save a wabpage completely from my Google Chrome extension.
I added "downloads", "<all_urls>" permissions and confirmed that the following code save the Google page to google.html.
chrome.downloads.download(
{ url: "http://www.google.com",
filename: "google.html" },
function (x) { console.log(x); })
However, this code only saves the html file.
Stylesheets, scripts and images are not be saved.
I want to save the webpage completely, as if I save the page with the dialog, selecting Format: Webpage, Complete.
I looked into the document but I couldn't find a way.
So my question is: how can I download a webpage completely from an extension using the api(s) of Google Chrome?
The downloads API downloads a single resource only. If you want to save a complete web page, then you can first open the web page, then export it as MHTML using chrome.pageCapture.saveAsMHTML, create a blob:-URL for the exported Blob using URL.createObjectURL and finally save this URL using the chrome.downloads.download API.
The pageCapture API requires a valid tabId. For instance:
// Create new tab, wait until it is loaded and save the page
chrome.tabs.create({
url: 'http://example.com'
}, function(tab) {
chrome.tabs.onUpdated.addListener(function func(tabId, changeInfo) {
if (tabId == tab.id && changeInfo.status == 'complete') {
chrome.tabs.onUpdated.removeListener(func);
savePage(tabId);
}
});
});
function savePage(tabId) {
chrome.pageCapture.saveAsMHTML({
tabId: tabId
}, function(blob) {
var url = URL.createObjectURL(blob);
// Optional: chrome.tabs.remove(tabId); // to close the tab
chrome.downloads.download({
url: url,
filename: 'whatever.mhtml'
});
});
}
To try out, put the previous code in background.js,
add the permissions to manifest.json (as shown below) and reload the extension. Then example.com will be opened, and the web page will be saved as a self-contained MHTML file.
{
"name": "Save full web page",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"]
},
"permissions": [
"pageCapture",
"downloads"
]
}
No, it does not download for you all files: images, js, css etc.
You should use tools like HTTRACK.

Difficulties saving URL from Chrome tab (for Chrome extension)

I'm attempting to build a Chrome extension which will check (through a "link:URL" Google search) which sites link to the one that is currently open in the active tab. But my code fails to properly save the tab's URL into a variable. I have found similar questions (and their answers) here on stackoverflow and I understand it may have sth to do with the fact that js is asynchronous, but I wasn't able to make it work. Any hint(s) would be hugely appreciated. Thanks!
// this is the part that doesn't work
chrome.tabs.query({'active': true}, function (tabs) {
var query = tabs[0].url;
});
// this is the part that works just fine
chrome.browserAction.onClicked.addListener(function(activeTab)
{
var stemURL = "http://www.google.com/#q=link:";
chrome.tabs.create({ url: (stemURL + query) });
});
Here's how I set the permissions in the manifest, which should be right
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
This is because when you declare your "query" variable, it only has scope within your callback function in chrome.tabs.query. Now, you could declare your variable at the top of your script to give it scope within the entire script:
var query;
chrome.tabs.query({'active': true}, function (tabs) {
query = tabs[0].url;
});
chrome.browserAction.onClicked.addListener(function(activeTab)
{
var stemURL = "http://www.google.com/#q=link:";
chrome.tabs.create({ url: (stemURL + query) });
});
...or you could use your activeTab variable that chrome.browserAction.onClick passes to you and grab the active tab's URL from that to ensure that you open the search results for the tab that the user was viewing when they clicked your extension's button, which would also have the added advantage of cutting out the first half of your code:
chrome.browserAction.onClicked.addListener(function(activeTab)
{
var stemURL = "http://www.google.com/#q=link:";
chrome.tabs.create({ url: (stemURL + activeTab.url) });
});
I would recommend the latter approach; it's faster, cleaner, and more reliable. Good luck!

Categories

Resources