Urls in creating chrome extension tabs do not work - javascript

I am creating a chrome extension which access a api and parses the json feed to get data. One of the data is a link and I want the link to be opened in a new tab. I use chrome.create.tabs to do it. But instead of opening a tab with specified url it opens like this
chrome-extension://app_id/%22http://www.twitch.tv/imaqtpie%22
Here is my popup.js
document.addEventListener('DOMContentLoaded', init);
function init(){
var elem = document.getElementById('Add');
elem.addEventListener('click',func);
}
function func(){
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.twitch.tv/kraken/search/streams?q=league%20of%20legends", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// innerText does not let the attacker inject HTML elements.
var qtpie=JSON.parse(xhr.responseText);
var display_name = JSON.stringify(qtpie.streams[0].channel.display_name);
var stream_status = JSON.stringify(qtpie.streams[0].channel.status);
var stream_url=JSON.stringify(qtpie.streams[0].channel.url);
var res = display_name+" : "+stream_status+"\n"+stream_url;
console.log(stream_url);
var a = document.createElement('a');
var linkText = document.createTextNode(res);
a.appendChild(linkText);
a.setAttribute('href', stream_url);
a.addEventListener('click', link_handler(stream_url));
document.getElementById("status").appendChild(a);
var magic=activateLinks();
// document.getElementById("status").innerText = res;
}
}
xhr.send();
}
function activateLinks()
{
var links = document.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
(function () {
var ln = links[i];
var location = ln.href;
ln.onclick = function () {
chrome.tabs.create({active: true, url: location});
};
})();
}
}
function link_handler(url)
{
// Only allow http and https URLs.
if (url.indexOf('http:') != 0 && url.indexOf('https:') != 0) {
return;
}
chrome.tabs.create({url: url});
}
Here stream_url is the variable that stores the parsed url from json.
here is the json from which it is parsed from
"video_banner":null,
"background":null,
"profile_banner":null,
"profile_banner_background_color":null,
"partner":true,
"url":"http://www.twitch.tv/imaqtpie",
"views":91792487
i want the new tab to open http://www.twitch.tv/imaqtpie instead of chrome-extension://app_id/%22http://www.twitch.tv/imaqtpie
. Thanks in advance. Btw using <base href="http://" target="_blank"> does not work.

So the problem is for the url. Your url is improper when using chrome.tabs.create, because %22 indicates the character " in ASCII Encoding Reference. You should strip it off in the url when you get the element in html. Glad it helps!

Related

Why doesn't this chrome extension work?

I want to collect the url (var name is 'url') of a webpage into a variable in a chrome extension, together with several user inputs in text inputs, and to send it to a remote php script for processing into an sql database. I am using AJAX to make the connection to the remote server. The popup.html contains a simple form for UI, and the popup.js collects the variables and makes the AJAX connection. If I use url = document.location.href I get the url of the popup.html, not the page url I want to process. I tried using chrome.tabs.query() to get the lastFocusedWindow url - the script is below. Nothing happens! It looks as though it should be straightforward to get lastFocusedWindow url, but it causes the script to fail. The manifest.json sets 'tabs', https://ajax.googleapis.com/, and the remote server ip (presently within the LAN) in permissions. The popup.html has UI for description, and some tags. (btw the response also doesn't work, but for the moment I don't mind!)
//declare variables to be used globally
var url;
// Get the HTTP Object
function getHTTPObject(){
if (window.ActiveXObject) return new ActiveXObject("Microsoft.XMLHTTP");
else if (window.XMLHttpRequest) return new XMLHttpRequest();
else {
alert("Your browser does not support AJAX.");
return null;
}
// Change the value of the outputText field THIS PART IS NOT WORKING YET
function setOutput(){
if(httpObject.readyState == 4){
//document.getElementById('outputText').value = httpObject.responseText;
"Bookmark added to db" = httpObject.responseText; // does this work?
}
}
//put URL tab function here
chrome.tabs.query(
{"active": true, "lastFocusedWindow": true},
function (tabs)
{
var url = tabs[0].url; //may need to put 'var' in front of 'url'
}
);
// Implement business logic
function doWork(){
httpObject = getHTTPObject();
if (httpObject != null) {
//get url? THIS IS OUTSTANDING - url defined from chrome.tabs.query?
description = document.getElementById('description').value;
tag1 = document.getElementById('tag1').value;
tag2 = document.getElementById('tag2').value;
tag3 = document.getElementById('tag3').value;
tag4 = document.getElementById('tag4').value;
httpObject.open("GET", "http://192.168.1.90/working/ajax.php?url="+url+"&description="+description+"&tag1="+tag1+"&tag2="+tag2+"&tag3="+tag3+"&tag4="+tag4, true);
httpObject.send(null);
httpObject.onreadystatechange = setOutput(); //THIS PART IS NOT WORKING
finalString = httpObject.responseText; //NOT WORKING
return finalString; //not working
} //close if
} //close doWork function
var httpObject = null;
var url = null;
var description = null;
var tag1 = null;
var tag2 = null;
var tag3 = null;
var tag4 = null;
// listens for button click on popup.html
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click', doWork);
});
Having no responses I first used a bookmarklet instead. The bookmarklet passes the url and title to a php script, which enters them into a db before redirecting the user back to the page they were on.
javascript:(function(){location.href='http://[ipaddress]/bookmarklet.php?url='+encodeURIComponent(location.href)+'&description='+encodeURIComponent(document.title)})()
Then I found this code which works a treat.
var urlOutput = document.getElementById('bookmarkUrl');
var titleOutput = document.getElementById('bookmarkTitle');
if(chrome) {
chrome.tabs.query(
{active: true, currentWindow: true},
(arrayOfTabs) => { logCurrentTabData(arrayOfTabs) }
);
} else {
browser.tabs.query({active: true, currentWindow: true})
.then(logCurrentTabData)
}
const logCurrentTabData = (tabs) => {
currentTab = tabs[0];
urlOutput.value = currentTab.url;
titleOutput.value = currentTab.title;
}

Page load happens before data returned via xhr in angular

We are facing a challenge in loading document urls fetched from S3 and displaying thumb images on the dashboard tab page.
/***fetch docs **push success confirm***/
$scope.getdocuments = function(){
DDListDataService.getDocumentTypes().then(function(docs){
$scope.docTypes = docs.data;
});
userService.fetchUserDocs($scope.user.customerId,$scope.user.entityType).then(function(userDocs){
//console.log("result--"+userDocs);
angular.forEach(userDocs, function(object , key){
console.log(object);
var xhr = new XMLHttpRequest();
var blob;
xhr.open('GET', object.documents[0].documentUrl);
//var file = common.base64ToBlob(object.d, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
//var file = remoteToBlob(object.documents[0].documentUrl);
//var file = common.base64ToBlob(object.documents[0].document, 'image/jpg');
/*file.lastModifiedDate = new Date();
file.name = "";*/
var file = new Blob([this.response], {type: 'image/jpg'});
//rest of the code that uses the blob goes here
file.lastModifiedDate = new Date();
file.name = "";
//setTimeout(function(){console.log(file)},1000);
var options = {
customerId : $scope.user.customerId,
customerType : $scope.user.entityType,
docTypeName : object.key.documentName,
documentName : object.key.documentNameId,
documentVersion : object.key.documentVersion,
documentUID : object.doccumentUID,
//requestedBy : $scope.user.customerType,
requestedBy : LocalService.get('userType'),
requestedById : $scope.user.customerId
}
var fileItem = new FileUploader.FileItem($scope.uploader,file,options);
fileItem.progress = 100;
fileItem.isUploaded = true;
fileItem.isSuccess = true;
/*file.customerId = $scope.user.customerId;
file.customerType =$scope.user.entityType;
file.documentName = object.key.documentNameId;
file.documentVersion =object.key.documentVersion;
file.documentUID = object.doccumentUID;
file.requestedBy = $scope.user.customerId;
file.requestedById = $scope.user.customerId;*/
$scope.uploader.queue.push(fileItem);
console.log(fileItem);
};
xhr.send();
});
});
//$scope.uploader.formData=[{"user":angular.json($scope.user)}];
$scope.uploader.queue.length = 0;
}
After the xhr.send() is executed the page load happens but the data is still not ready and it gives undefined file object as the data is not returned in the mean time. How can we hault the load till the data is returned? The onload I believe has a callback which should carry out the function.Correct me if wrong.
How can this be handled?
The html to display the image is
<div ng-show="uploader.isHTML5" ng-thumb="{ file: item._file, height: 100 ,stream:item._file}"></div>
The time it takes for the page to load is independent of the time it takes for your xhr request to complete.
So, create a window.load function that calls another function, and put what you need after the xhr request inside that other function like this:
$(window.load(function (){
afterXHRLoad(); //This calls the afterXHRLoad function after the page loads
});
function afterXHRLoad(){
if($.active == 0)
{
//code needed here;
}
else
{
setTimeout(afterXHRLoad, 1000); //recursively call the function after 1 second
}
}

How to download a file that I have chosen from Google Picker API?

I am implementing the Google Picker in a PHP site. I am able to get the file id from the Google Picker API and also I can download the file using JavaScript. Following is my callback function called in setCallback(pickerCallback) function.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
document.getElementById('googleFileId').value = fileId;
var name = data.docs[0].name;
var url = data.docs[0].url;
var accessToken = gapi.auth.getToken().access_token;
var request = new XMLHttpRequest();
request.open('GET', 'https://www.googleapis.com/drive/v2/files/' + fileId);
request.setRequestHeader('Authorization', 'Bearer ' + accessToken);
request.addEventListener('load', function() {
var item = JSON.parse(request.responseText);
window.open(item.webContentLink,"_self"); //Download file in Client Side
});
request.send();
}
var message = 'File ID of choosen file : ' + fileId;
document.getElementById('result').innerHTML = message;
}
I can pass the file id to PHP, but to download the file I have to authenticate again. Can any one help in how to proceed with file download in PHP ?
There is a Manage Downloads help in Google Developers page but it is not working for me https://developers.google.com/drive/web/manage-downloads.
Found a question similar to this one but no answers to how to download the file in backend Download file right after picked file from google picker.
You have to implement a callback for the pick action. Take a look at my implementation:
var buildPicker = function(parentId) {
var pickerCallback = function(data) {
if (data[google.picker.Response.ACTION] === google.picker.Action.PICKED && data.viewToken[0] !== 'upload') {
var docs = data[google.picker.Response.DOCUMENTS];
for (var d = 0; d < docs.length; d++) {
downloadFile(docs[d].id);
}
}
};
GAuth.getToken().then(function(token) {
var picker = new $window.google.picker.PickerBuilder()
.addView(new google.picker.DocsUploadView().setParent(parentId))
.addView(new google.picker.DocsView().setParent(parentId).setIncludeFolders(true))
.setDeveloperKey(apiKey)
.setOAuthToken(token.access_token)
.setCallback(pickerCallback);
picker.enableFeature(google.picker.Feature.MULTISELECT_ENABLED);
picker.build().setVisible(true);
});
};
var downloadFile = function(fileId) {
getFile(fileId).then(function(file) {
var downloadUrl;
if (angular.isDefined(file.exportLinks)) {
downloadUrl = file.exportLinks['application/pdf'];
} else {
downloadUrl = file.webContentLink;
}
var $idown;
var makeiFrame = function(url) {
if ($idown) {
$idown.attr('src', url);
} else {
$idown = $('<iframe>', {
id: 'idown',
src: url
}).hide().appendTo('body');
}
};
makeiFrame(downloadUrl);
});
};
// Implemented with https://github.com/maximepvrt/angular-google-gapi. But any other implementation will be fine as well
var getFile = function(fileId) {
var parameters = {
'fileId': fileId
};
return GApi.executeAuth('drive', 'files.get', parameters);
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

replace XMLHttpRequest in javascript

I used to read my local files using XMLHttpRequest.
function getData(fileName)
{
var filePath = fileName;
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filePath, false);
xmlhttp.send(null);
var fileContent = xmlhttp.responseText;
var tempArr = csv2Arr(fileContent);
var returnLabelArr = tempArr[0].toString().split(',');
tempArr.shift();
var returnDataArr = tempArr;
return { 'dataArr' : returnDataArr, 'labelArr' : returnLabelArr };
}
fileName starts with "C://..." and my program works on browser with address "file:///...".
But, without "--allow-file-access-from-files" tag, my code doesn't work on Chrome. And also it doesn't work on IE and Firefox without changing some security options.
So, I tried to jquery API like this,
function getData(fileName)
{
var filePath = fileName;
var fileContent;
$.ajax({
type: "GET",
url: filePath
})
.done(function(data) {
alert(data);
fileContent = data;
});
var tempArr = csv2Arr(fileContent);
var returnLabelArr = tempArr[0].toString().split(',');
tempArr.shift();
var returnDataArr = tempArr;
return { 'dataArr' : returnDataArr, 'labelArr' : returnLabelArr };
}
The Problem also occurs. I think Same-origin policy prevents it.
Can anyone give me some suggestions for me to access local files without changing security options? Should I use some plug-ins to solve this?
Please let me know.
Thank you.
If you can use <input type="file"> to select files, then the solution is:
HTML:
<form action="">
<input type="file" id="file-input" multiple="multiple" accept="image/jpeg" />
</form>
JS:
var fileInput = document.querySelector('#file-input');
fileInput.addEventListener('change', function(event) {
var files = fileInput.files;
if (files.lenght == 0) {
return;
}
for(var i = 0; i < files.length; i++) {
readFile(files[i]);
}
fileInput.value = "";
}, false);
var readFile= function(file) {
var reader = new FileReader();
reader.onload = function(e) {
var dataUrl = e.target.result;
// now, load the data into some element
// if this is image, you can do this:
var image = new Image();
image.src = dataUrl;
document.body.appendChild(image);
};
reader.readAsDataURL(file);
};
Also, discover the FileReader API to find out, how you can use it otherwise, as it has more methods to read data.

Ajax Request generates html with potential for subsequent Ajax requests. Secondary requests return [object mouseevent] as opposed to generated value

I have a page that is loaded via php. One of the elements in the page is a <li> that has an onclick event. E.g. <li onclick="dynamiccall('1');">blah</li>. After clicking the element an ajax call is issued and the html output is inserted into the page, the tag looks as follows <li onclick="getubilling('1');">blah</li>.
After clicking the generated element with the onclick function getubilling('1');, an ajax call is sent to a php script. The query parameter in the second function to getubilling is displayed as 1, but upon passing it to the ajax call, it shows up as [object mouseevent]. Why is this happening?
the dynamiccall() function is defined as follows in the ajax.js file included in the page:
function dynamiccall(uid){
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
HandleResponse10(xmlHttp.responseText);
console.log(uid);
var holder = uid;
document.getElementById('orgcinfo').innerHTML = '<ul id="b_action_lst2"><li onclick="getuprofile('+holder+')" name="uprofile">Account Settings</li><li onclick="getubilling('+holder+')" name="billing">Billing</li><li onclick="getuchpass('+holder+')" name="chpass">Change Password</li><li onclick="getuadduser('+holder+')" name="adduser">Add User</li></ul>';
var ullist = document.getElementById('b_action_lst2');
var links = ullist.getElementsByTagName('li');
for(var i=0;i<links.length;i++){
var link = links[i];
if(link.getAttribute('name')=="uprofile"){
link.onclick = getuprofile;
}
if(link.getAttribute('name')=="chpass"){
link.onclick = getuchpass;
}
if(link.getAttribute('name')=="billing"){
link.onclick = getubilling;
}
}
//dothis();
}
}
xmlHttp.open("GET", "ajax.php?&p=anotherreq&uid="+uid+"&n="+Math.random(), true);
xmlHttp.send(null);
}
function getubilling(uid){
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
HandleResponse10(xmlHttp.responseText);
console.log(uid);
var holder = uid;
document.getElementById('orgcinfo').innerHTML = '<ul id="b_action_lst2"><li onclick="getuprofile('+holder+')" name="uprofile">Account Settings</li><li onclick="getubilling('+holder+')" name="billing">Billing</li><li onclick="getuchpass('+holder+')" name="chpass">Change Password</li><li onclick="getuadduser('+holder+')" name="adduser">Add User</li></ul>';
var ullist = document.getElementById('b_action_lst2');
var links = ullist.getElementsByTagName('li');
for(var i=0;i<links.length;i++){
var link = links[i];
if(link.getAttribute('name')=="uprofile"){
link.onclick = getuprofile;
}
if(link.getAttribute('name')=="chpass"){
link.onclick = getuchpass;
}
if(link.getAttribute('name')=="billing"){
link.onclick = getubilling;
}
}
//dothis();
}
}
xmlHttp.open("GET", "ajax.php?&p=gubilling&uid="+uid+"&n="+Math.random(), true);
xmlHttp.send(null);
}
A request is issued to http://www.domain.com/ajax.php?&p=gubilling&uid=1&n=2212.32313
The problem is that the resulting UID variable when rendered in the browser results to [object mouseevent] as opposed to the literal value of 1.
I was following this example the only difference I can see is that the example doesn't provide for
passing a dynamic element to the dynamicEvent function where mine does.
What am I missing? Any advice is appreciated.
I suspect this will be the default param passed into the onclick handler, the event object.
Why don't you use addEventListener for a start, rather than inline?
How does this:
dynamiccall('uniqueid');
Know what uniqueid's value is? where does it get it from? In this case, it's taking the value of the event that occurred. My suggestion would be to change the tag to look like this:
<li onclick="dynamiccall(this);" uniqueid="1">blah</li>
then you can set dynamiccall to:
function getubilling(elem) {
var uid = $(elem).attr('uniqueid');
...

Categories

Resources