I am developing a browser extension using crossrider.
I have added a context menu (background.js)
var ContextData;
appAPI.contextMenu.add("key1", "Send Data To Server", function (data) {
var ContextData = 'pageUrl: ' + data.pageUrl + '\r\n' +
'linkUrl: ' + data.linkUrl + '\r\n' +
'selectedText:' + data.selectedText + '\r\n' +
'srcUrl:' + data.srcUrl;
}, ["all"]);
On user click I want to send ContextData to extension.js. At extension.js some function will receive the data and send it to my server (A Rest API which will accept the data).
To send data to the server I have tested this and it works fine (code sample in extension.js)
appAPI.ready(function($) {
var dataToSend =="test data";
appAPI.request.post({
url: 'REST API URL',
postData: dataToSend,
onSuccess: function(response, additionalInfo) {
var details = {};
details.response = response;
},
onFailure: function(httpCode) {
// alert('POST:: Request failed. HTTP Code: ' + httpCode);
}
});
});
How can I write a function to accept ContextData from background.js and assign it to dataToSend in extension.js?
#Neel If I understand your requirements correctly, #Rob is essentially correct though a little clarification may help
By design/architecture, the extension.js code runs on each HTML page i.e. a separate extension.js instance is run for each URL that loads. In contrast, the context menu runs at the browser level (not HTML page) and is hence correctly coded in background.js file. However, the background.js code does not have direct access to the extension.js instance code running on the HTML page in the active tab and must therefore communicate the data via messaging. (For more information about scopes, see Scopes Overview)
Obviously, a user clicks the context menu item on the active tab (i.e. the page showing the HTML page being viewed); hence, once the ContextData string is created, you can use appAPI.message.toActiveTab to send the string to the extension.js instance running on the page/tab where the the context menu item was clicked.
This being the case, using your code example you can achieve this goal as follows:
background.js:
appAPI.ready(function($) {
var ContextData;
appAPI.contextMenu.add("key1", "Send Data To Server", function (data) {
var ContextData = 'pageUrl: ' + data.pageUrl + '\r\n' +
'linkUrl: ' + data.linkUrl + '\r\n' +
'selectedText:' + data.selectedText + '\r\n' +
'srcUrl:' + data.srcUrl;
appAPI.message.toActiveTab({type:'dataToSend', data: ContextData});
}, ["all"]);
});
extension.js:
appAPI.ready(function($) {
var dataToSend =="test data";
appAPI.message.addListener(function(msg) {
if (msg.type === 'dataToSend') {
appAPI.request.post({
url: 'REST API URL',
postData: dataToSend,
onSuccess: function(response, additionalInfo) {
var details = {};
details.response = response;
},
onFailure: function(httpCode) {
// alert('POST:: Request failed. HTTP Code: ' + httpCode);
}
});
}
});
});
[Disclaimer: I am a Crossrider employee]
Related
I am working on a project where I need to capture the browser close event (unload or beforeunload). For that I have tried the code below but it's not working.
The code is working only if I open the browser console window (maybe just for a second) but it is required otherwise it's not working.
Example
$(window).on('beforeunload', function(e) {
$.ajax({
type: "POST",
url: "url",
data : {'value' : 1},
dataType:'json'
});
return false;
});
The beacon API is meant specifically for that. Sending a request as the page is unloading. https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API
Beacon requests use the HTTP POST method and requests typically do not require a response. Requests are guaranteed to be initiated before a page is unloaded and they are run to completion, without requiring a blocking request (for example XMLHttpRequest).
window.onunload = function analytics(event) {
if (!navigator.sendBeacon) return;
var url = "https://example.com/analytics";
// Create the data to send
var data = "state=" + event.type + "&location=" + location.href;
// Send the beacon
var status = navigator.sendBeacon(url, data);
// Log the data and result
console.log("sendBeacon: URL = ", url, "; data = ", data, "; status = ", status);
};
I have mixed content error, on web site used both http and https protocols.
Here's the error from Chrome console:
Mixed Content: The page at 'https://www.amazon.com/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://www.amazon.com/../?redirect=true'. This request has been blocked; the content must be served over HTTPS.
Here's screenshot with the error: http://prntscr.com/9os5li
Was found some solution like:
Change link from "http://" to "https://" in
Blocked loading mixed active content.
Nothing helped me, because Amazon server drop it all the time when I change link in code or manual from http to https drop it and make it as http.
For example this one Link 2 I can't use here https, because of this I have mixed content error.
Here's my AJAX where I make a call:
$.ajax({
url: "//" + MWS_URL + rest_path,
data: request,
dataType: 'text',
type: 'POST',
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
beforeSend: function(req) {
//req.setRequestHeader("User-Agent", "chrome extension");
req.setRequestHeader("x-amazon-user-agent", "chrome extension");
},
success: function(data){
if (onSuccess) {
onSuccess(data);
}
},
error: function(jqXHR, textStatus, errorThrown) {
if (onError) {
onError(jqXHR, textStatus);
}
}
});
setTimeout(callService, 1000);
}
Request:
requests.push(
$.get(link.URL, function (data) {
if (IsCancel()) {
return;
}
var jdata = $($.parseHTML(data));
var parser = new ProductPageParser(jdata, link.URL);
if (!parser.isValidProduct()) {
console.log(link.URL + " is not a valid product, skipped.");
link.processed = true;
return;
}
// Process associated (linked) product on this page according to user preferences.
crawlLinkedProducts(jdata, link.URL, config);
// Store product into a collection.
var product = getProductForParser(parser, link);
//product.dbRawProductURL = urlRaw;
if (product) {
products.push(product);
}
link.processed = true;
})
);
And as I have parse in parser, here's second level parser. I parsed products on main page:
$(productUrls).each(function (index, link) {
if (!link.processed) {
console.log("Download second level -> " + link.URL);
requests_2level.push(
$.post(link.URL, "", function (data) {
if (IsCancel()) {
return;
}
console.log("End download second level -> " + link.URL);
var jdata = $($.parseHTML(data));
var parser = new ProductPageParser(jdata, link.URL);
if (!parser.isValidProduct()) {
console.log(link.URL + " is not a valid product, skipped.");
link.processed = true;
return;
}
var hackUrl = "//amazon.com/o/ASIN/" + parser.getAsin();
link.URL = hackUrl;
var product = getProductForParser(parser, link);
if (product) {
products.push(product);
}
link.processed = true;
})
);
}
});
Anyone have idea how to fix this problem?
If Amazon keep redirecting you from HTTPS to HTTP then there is nothing you can do about that short of:
Complaining hard enough at Amazon that they fix it or
Using a difference service
Decide whether to use http or https and use the same on for every call.
I am trying to send a form thru POST to my REST Resource (Java) and I am not able to, as my request gets sent as OPTIONS instead. I Know that the REST Resource is fine since it works perfectly while I test it with Poster Firefox.
jQuery/Ajax call:
function loadTwitter(){
arrayTweets = new Array();
var urlTwitter = "http://localhost:8081/streamingvideoservice/services/twitter/retrieveTweets";
$.ajax({
type: "POST",
url: urlTwitter,
contentType: "application/x-www-form-urlencoded",
//accept: "application/json",
data: $("form#mapForm").serialize(),
dataType: "json",
async: false,
success: function (resp, status, xhr) {
$("#message").html("STATUS: " + xhr.status + " " + xhr.statusText + "\n" + resp);
$("#message").hide();
$.each(resp, function() {
$.each(this, function(i, item) {
arrayTweets.push(item);
});
});
displayTweets();
},
error: function(resp, status, xhr){
$("#message").html("ERROR: " + xhr.status + " " + xhr.statusText + "\n" + resp.e);
$("#message").show();
}
});
}
REST Resource:
#POST
#Path("/retrieveTweets")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces("application/json")
public List<Tweet> retrieve(#FormParam("lat") Double Latitude, #FormParam("lon") Double Longitude, #FormParam("rad") Integer Radius, #FormParam("from") String From, #FormParam("to") String To) {
ArrayList<Tweet> lTweets = new ArrayList<Tweet>();
boolean status = false;
Twitter twitter = new TwitterFactory().getInstance();
AccessToken accessToken = new AccessToken(TwitterInterface.ACCESS_TOKEN, TwitterInterface.ACCESS_TOKEN_SECRET);
twitter.setOAuthConsumer(TwitterInterface.CONSUMER_KEY, TwitterInterface.CONSUMER_SECRET);
twitter.setOAuthAccessToken(accessToken);
try {
Query query = new Query("");
GeoLocation geo = new GeoLocation(Latitude, Longitude);
query.setGeoCode(geo, Radius, Query.KILOMETERS);
query.setCount(100);
query.setSince(From);
query.setUntil(To);
QueryResult result;
result = twitter.search(query);
List<Status> tweets = result.getTweets();
for (Status tweet : tweets) {
System.out.println("#" + tweet.getUser().getScreenName() + " - " + tweet.getText() + " - " + tweet.getCreatedAt());
Tweet t = new Tweet();
t.setUser(tweet.getUser().getScreenName());
t.setText(tweet.getText());
lTweets.add(t);
}
}
catch (TwitterException te) {
te.printStackTrace();
System.out.println("Failed to search tweets: " + te.getMessage());
System.exit(-1);
}
return lTweets;
}
I am using jQuery 1.9.1 and hosting the Resource on Tomcat 6.
Any help is appreciated.
Thanks in advance.
You appear to be making a cross origin Ajax request. This requires that the server provides an Access-Control-Allow-Origin header to grant permission to the site hosting the page containing the JS to read the data.
Something about the request (probably the X-Requested-With header that jQuery adds to Ajax requests) is triggering a preflight request which uses an OPTIONS request to ask the server for permission before making the main request.
You will need to configure the server to provide an OPTIONS response with suitable Access Control headers as per the CORS specification (linked above).
Solved it with a GET instead and passing the parameters in the URI.
I am working on a browser extension using crossrider. I need to send some data from popup to extension.js
My code of popup
<!DOCTYPE html>
<html>
<head>
<!-- This meta tag is relevant only for IE -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript">
/************************************************************************************
This is your Popup Code. The crossriderMain() code block will be run
every time the popup is opened.
For more information, see:
http://docs.crossrider.com/#!/api/appAPI.browserAction-method-setPopup
*************************************************************************************/
function crossriderMain($) {
// var to store active tab's URL
var activeTabUrl = null;
// Message listener for response from active tab
appAPI.message.addListener(function(msg) {
if (msg.type === 'active-tab-url') activeTabUrl = msg.url;
});
// Request URL from active tab
appAPI.message.toActiveTab({type: 'active-tab-url'});
alert(activeTabUrl);
// THE REST OF YOUR CODE
}
</script>
</head>
<body>
Hello World
</body>
</html>
Code of Extension.js
appAPI.ready(function($) {
// Message listener
appAPI.message.addListener(function(msg) {
if (msg.type === 'active-tab-url')
// Send active tab's URL to popup
appAPI.message.toPopup({
type: 'active-tab-url',
url:encodeURIComponent(location.href)
});
});
// THE REST OF YOUR CODE
});
The value of activeTabUrl is not getting updated. It gives NULL value.
P.S : I am able to communicate between background.js and popup. But for some reason appAPI.message.toActiveTab function is not working for me. Where I am doing the mistake?
Background.js (Edit)
var tabUrl='';
/* appAPI.tabs.getActive(function(tabInfo) {
tabUrl = tabInfo.tabUrl;
}); */
appAPI.message.addListener(function(msg) {
appAPI.tabs.getActive(function(tabInfo) {
tabUrl = tabInfo.tabUrl;
});
var dataString = '{"url":"'+tabUrl+'","access":"'+msg.access+'","toread":"'+msg.toread+'","comment":"'+msg.comment+'"}';
alert(dataString);
appAPI.request.post({
url: 'REST API URL',
postData: dataString,
onSuccess: function(response, additionalInfo) {
var details = {};
details.response = response;
appAPI.message.toPopup({
response:response
});
},
onFailure: function(httpCode) {
// alert('POST:: Request failed. HTTP Code: ' + httpCode);
}
});
});
Working code of Background.js
appAPI.message.addListener(function(msg) {
appAPI.tabs.getActive(function(tabInfo) {
var dataString = '{"url":"'+tabInfo.tabUrl+'","access":"'+msg.access+'","toread":"'+msg.toread+'","comment":"'+msg.comment+'"}';
// alert(dataString);
appAPI.request.post({
url: 'http://fostergem.com/api/bookmark',
postData: dataString,
onSuccess: function(response, additionalInfo) {
var details = {};
details.response = response;
appAPI.message.toPopup({
response:response
});
},
onFailure: function(httpCode) {
// alert('POST:: Request failed. HTTP Code: ' + httpCode);
}
});
});
});
In this code sample, the activeTabUrl variable is only set once a response is received from the extension.js file since the messaging is asynchronous by design. Hence, when calling alert(activeTabUrl); in the code, the message has not yet been received back fro the extension.js code thus the value is still null as it was initialized.
To use the activeTabUrl variable you must wait for the mesage from the extension.js file, and hence you should place the code using the variable in the callback of the message listener, preferably as a function. Also note that using an alert in the popup code causes the popup to close and should hence not be used in the popup scope.
I tested the following popup code, which does away with the variable to avoid confusion and passes the active tab URL as a parameter to the function called in the message listener, and it worked as expected:
function crossriderMain($) {
// Message listener for response from active tab
appAPI.message.addListener(function(msg) {
if (msg.type === 'active-tab-url') ShowPageUrl(msg.url);
});
function ShowPageUrl(url) {
$('#page-url').html('<b>Page URL</b>: ' + url);
}
// Request URL from active tab
appAPI.message.toActiveTab({type: 'active-tab-url'});
//alert(activeTabUrl);
// THE REST OF YOUR CODE
}
[Disclaimer: I am a Crossrider employee]
i want to download a file using extjs 4.1.
The file name is "wsnDataModel.xml".
I've tryed with all things suggested in other posts:
//function invoked clicking a button
DwDataModel : function(th, h, items) {
//direct method that build in file in the location calculated below with "certurl" (I've verified)
Utility.GetDataModel(function(e, z, x) {
if (z.message) {
//the server method should give an error message
Ext.create('AM.view.notification.toast', {
title : 'Error',
html : z.message,
isError : true
}).show();
} else {
// navigate to get data
var certurl = 'http://' + window.location.host
+ '/AdminConsole3/' + e;
Ext.Ajax.request({
method : 'GET',
url : 'http://' + window.location.host
+ '/AdminConsole3/' + e,
success : function(response, opts) {
//the following navigate and openthe file in the current browser page.
//I don't want to change the current browser page
//window.location.href = certurl;
//the same behaviour with
//document.location = certurl;
//and this don't work at all
window.open(certurl,'download');
},
failure : function(response, opts) {
console
.log('server-side failure with status code '
+ response.status);
console.log('tried to fetch ' + url);
}
}, this, [certurl]);
}
}, th);
}
the "navigation" redirect the application (i don't want to redirect the application) like this:
and I'would like to download the file like this image:
I think it's very simple. How to do that?
thank you
Very simple: this is the success function.
success: function (response, opts) {
var link = document.createElement("a");
//this gives the name "wsnDataModel.xml"
var fileName = certurl.substring(certurl.lastIndexOf('/') + 1);
link.download = fileName;
link.href = certurl;
link.click();
}