Chrome Extension: Get current webpage url from background.html not stable - javascript

Try to get url in background.html through background.js in Chrome extension.
var myURL = "about:blank"; // A default url just in case below code doesn't work
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { // onUpdated should fire when the selected tab is changed or a link is clicked
chrome.tabs.getSelected(null, function(tab) {
myURL = tab.url;
});
});
chrome.contextMenus.onClicked.addListener(function(info, tab) {
logUrl();
})
function logUrl() {
...
eventProperties.setProperty('URI', myURL);
...
}
myURL sometimes shows as "about:blank", it shows actual url after reloading the page.
How shall I fix this?

Related

Copy window.location.href to clipboard from extension

I am trying to copy 'window.location.href' e.g. the URL of the current page to clipboard from my extension.
My issue is that when I copy the URL to clipboard, it is the extensions URL that is copied and not the page I am visiting.
Extensionbar:
<!DOCTYPE HTML>
<html>
<head>
<button onclick="copyFunction();">Copy</button>
<script type="text/javascript">
function copyFunction() {
var inputDump = document.createElement('input'),
hrefText = window.location.href;
document.body.appendChild(inputDump);
inputDump.value = hrefText;
inputDump.select();
document.execCommand('copy');
document.body.removeChild(inputDump);
}
</script>
</head>
</html>
From my understanding the solution should be this, but I fear I am too clueless how to proceed: https://developer.apple.com/documentation/safariservices/safari_app_extensions/passing_messages_between_safari_app_extensions_and_injected_scripts
This is how I (tried to) proceed, by creating a global.html page and an injected script.
Global page:
<!DOCTYPE HTML>
<script>
safari.application.addEventListener("command", copyFunction, false);
function copyFunctionEvent(event) {
if (event.command == "CopyToClipboard") {
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("CopyToClipboard", "all");
}
}
</script>
Injected script:
function myextension_openAll(event){
if (event.name == 'CopyToClipboard'){
function copyFunction() {
var inputDump = document.createElement('input'),
hrefText = window.location.href;
document.body.appendChild(inputDump);
inputDump.value = hrefText;
inputDump.select();
document.execCommand('copy');
document.body.removeChild(inputDump);
}
}
safari.self.addEventListener("message", myextension_openAll, true);
Actual:
safari-extension://com.myextension-0000000000/abc123/extensionbar.html
Expected:
http://www.google.com (e.g. if current tab)
From your code above (Extensionbar html), you seem to write legacy Safari extension (.safariextz), and it has been deprecated. See What’s New in Safari and WebKit" session on WWDC18
I recommend you rewrite your code into Safari App Extension by following process, which can be written in Swift. I'm not sure why wrong URL is copied to clipboard in your code, but rewriting your code would solve the problem as a result.
Creating App Extension project
Create App Extension by following [File] -> [New] -> [Project...] then choose [Safari Extension App] on Xcode. Project template contains example of menubar implementation.
Copying location.href by clicking menu bar button
Following code would add functionality to copy location.href when you click menu bar button.
Just paste this into SafariExtensionHandler.swift.
class SafariExtensionHandler: SFSafariExtensionHandler {
override func messageReceived(withName messageName: String, from page: SFSafariPage, userInfo: [String : Any]?) {
// WHen injected script calls safari.extension.dispatchMessage, the message will come here
guard let href = userInfo?["href"] as? String else { return }
// Save href to clipboard
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(href, forType: .string)
}
override func toolbarItemClicked(in window: SFSafariWindow) {
// Request injected script a message to send location.href
window.getActiveTab { currentTab in
currentTab!.getActivePage { currentPage in
currentPage!.dispatchMessageToScript(withName: "getHref", userInfo: nil)
}
}
}
}
And injected script (script.js) as follows.
safari.self.addEventListener("message", function(event) {
console.log("event received");
safari.extension.dispatchMessage("sendHref", { "href": location.href });
});
Working Example
Complete working code here, This may help your work. Good luck :)
https://github.com/horimislime/safari-extension-menubar-example

Chrome extension: Display a popup window once PDF Viewer (pdf.js) processes a PDF

I am new to pdf.js and google chrome extensions. I am using pdf.js to view PDF files in Chrome (https://github.com/mozilla/pdf.js/tree/master/extensions/chromium).
WHAT I WANT TO IMPLEMENT: Once my PDF is loaded and processed by PDF viewer (pdf.js), I want to check if a user is logged into my website via XmlHttpRequest. Then I want to create a popup window showing the user's name or ask him/her to login.
I've added checkLogin(); function to the following script (https://github.com/Rob--W/chrome-api/tree/master/chrome.tabs.executeScriptInFrame).
checkLogin(); opens a new popup window (dialog.html)
chrome.tabs.executeScriptInFrame.js :
function checkLogin() {
chrome.tabs.create({
url: chrome.extension.getURL('dialog.html'),
active: false
}, function(tab) {
// After the tab has been created, open a window to inject the tab
chrome.windows.create({
tabId: tab.id,
type: 'popup',
focused: true,
height: 200, width:500
});
});
}
dialog.html displays the message returned from dialog.js (containing username or asking user to login)
dialog.html :
<html>
<head><title>Dialog test</title></head>
<body>
<div id="output"></div>
<script src="dialog.js"></script>
</body>
</html>
dialog.js :
connect();
function connect() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "sendingcookies.php", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status ==200 ) {
var response = xhr.responseText;
document.getElementById('output').innerHTML = response;
}
}
xhr.send(null);
}
THE PROBLEM: If I insert checkLogin(); function in background.js, the script runs when the extension is loaded. However, I want to run this function each time a PDF is loaded and processed by pdf.js. I am not sure how to proceed as I'm still familiarizing with pdf.js code.
Any tips on how to implement this correctly will be awesome. Thanks in advance for your help!
So I figured out how to implement this. I'm posting this answer for those that may be interested.
As suggested by user #Luc on the thread How to know if PDF.JS has finished rendering? , I added my checkLogin(); function to this existing function in viewer.js.
document.addEventListener('textlayerrendered', function (e) {
var pageIndex = e.detail.pageNumber - 1;
var pageView = PDFViewerApplication.pdfViewer.getPageView(pageIndex);
//Added this code - creates popup window once PDF has finished rendering
if (event.detail.pageNumber === PDFViewerApplication.page) {
checkLogin();
function checkLogin() {
chrome.tabs.create({
url: chrome.extension.getURL('dialog.html'),
active: false
}, function(tab) {
// After the tab has been created, open a window to inject the tab
chrome.windows.create({
tabId: tab.id,
type: 'popup',
focused: true,
// incognito, top, left, ...
height: 300, width:500
});
});
}
}
}, true);
As a result, my popup window loads while/once the PDF has finished rendering. It's pretty neat!

Chrome Extension - Injected Iframe not accessing Chrome browserAction or chrome.tabs or AngularJS

I have a chrome extension that toggles a sidebar with the browser action click. The sidebar contains an iframe with a local (chrome extension) source. I thought the page within the iframe would be considered a local chrome extension file with open access to the chrome APIs and etc. However, I keep getting the following errors in the web console:
Uncaught TypeError: Cannot read property 'onClicked' of undefined <-- background.js
TypeError: Cannot read property 'query' of undefined <-- sidebar.js
How do I get it so that the iframe injected with a context script has access to the local chrome environment?
Code below:
sidebar.js:
var myApp = angular.module('PlaceMates', []);
myApp.service('pageInfoService', function() {
this.getInfo = function(callback) {
var model = {};
chrome.tabs.query({
'active': true, // Select active tabs
lastFocusedWindow: true // In the current window
},
function (tabs) {
if (tabs.length > 0)
{
model.title = tabs[0].title;
model.url = tabs[0].url;
chrome.tabs.sendMessage(tabs[0].id, { 'action': 'PageInfo' }, function (response) {
model.pageInfos = response;
console.log("popup js: " + model.pageInfos);
callback(model);
});
}
});
};
});
myApp.controller("PageController", function ($scope, pageInfoService) {
$scope.message = "This extension identifies the photos on this page!";
pageInfoService.getInfo(function (info) {
$scope.title = info.title;
$scope.url = info.url;
$scope.pageInfos = info.pageInfos;
$scope.place_name = info.place_name;
$scope.$apply();
});
});
background.js
console.log( 'Background.html starting!' );
// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
// No tabs or host permissions needed!
console.log('Toggling sidebar on ' + tab.url);
// send message to current tab when clicked
var tabId = tab.id;
console.log("tab.id: " + tabId);
chrome.tabs.query({active: true, currentWindow: true}, function(tab) {
chrome.tabs.sendMessage(
//Selected tab id
tabId,
//Params inside a object data
{callFunction: "toggleSidebar"},
//Optional callback function
function(response) {
console.log(response);
}
);
});
console.log('Done toggling sidebar!');
});
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if(request.cmd == "read_file") {
$.ajax({
url: chrome.extension.getURL("sidebar.html"),
dataType: "html",
success: sendResponse
});
}
})
chrome.runtime.onMessage.addListener(
function(msg, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (msg.command == "read_info"){
console.log(JSON.parse(JSON.stringify(msg.myInfo)));
sendResponse({command: "done"});
}
}
);
console.log( 'Background.html done.' );
The only pages that have access to all chrome.* extension API are pages that are run at the extension's origin and within the Chrome extension process.
When an extension page is embedded in an iframe, its extension runtime is equivalent to a content script: The page can only use cross-origin XMLHttpRequest and some of the extension APIs (messaging and some other methods in the chrome.runtime / chrome.extension namespace).
If you wish to make the functionality of the other Chrome APIs available to your iframe, then you have to call these APIs from the background page, and use the messaging API to proxy requests from the iframe to the background page and back. Luckily, most of the Chrome extension API is asynchronous by design, so it will not be difficult to change your code to use these proxies.

Oauth login popup not closing in ie

I have written javascript code for oauth login popup for google OAuth
code is as follows
function authorize(authorize_url,get_token,get_token_secret)
{
console.log("acToken is "+get_token);
var win = window.open(authorize_url, "windowname2", "width=800, height=600");
var pollTimer = window.setInterval(function() {
try
{
if (win.document.URL.indexOf(oauth_callback) != -1) {
console.log("url inside callback"+win.document.URL)
window.clearInterval(pollTimer);
win.close();
getting_access_token(get_token,get_token_secret);
}
}catch(e)
{
}
},100);
}
in that window is opening oauth but after click allow it is not going inside if of window.setinterval function that's why popup window is not closing in ie in firefox and chrome window is closing properly how to resolve this in ie.
You should open login page in a new window, then redirect to a success page, which then closes the popup:
page.html
function login() {
var win = window.open('', 'login.html', 'width=800,height=400');
win.focus();
}
login.html
window.location.href = 'success.html'; // or use server-side redirect
success.html
window.opener.close();

Obtain URL's of chrome popups

I have written a piece of code which alerts the tab URL after every 2 seconds. However, I am unable to do this for pop-ups. Whenever I open a pop-up; the tab url is of the background page and not the pop-up.
How can i get the url of the pop-up in crome?
<script>
var seconds = 2*1000;
setInterval(function(){
chrome.tabs.getSelected(null, function(tab) {
tabId = tab.id;
tabUrl = tab.url;
alert(tabUrl);
});
},seconds);
</script>
</head>
When you pass null instead of windowId to chrome.tabs.getSelected(), it defaults to "current" window, which is not necessary the selected one, as explained here:
The current window is the window that contains the code that is currently executing. It's important to realize that this can be different from the topmost or focused window.
So you need to find the focused window first, and then get its selected tab:
var seconds = 2*1000;
setInterval(function(){
chrome.windows.getLastFocused(function(window) {
chrome.tabs.getSelected(window.id, function(tab) {
tabId = tab.id;
tabUrl = tab.url;
alert(tabUrl);
});
});
},seconds);
In content_script.js or popup.html:
function get_urlInfo() {
var d = {
'action' : 'getUrl'
};
chrome.extension.sendRequest(d, function(response) {
alert(response.url);
});
};
In background.html:
function onRequest(request, sender, sendResponse) {
if (request.action == 'getUrl') {
sendResponse({'url' : sender.tab.url});
}
};
chrome.extension.onRequest.addListener(onRequest);
It should work!

Categories

Resources