Chrome extension gmail API cookiePolicy? - javascript

I'm building a chrome extension that will read the user's emails and check them for typos. However, when trying to authenticate the user in my background.js I'm running into this error:
uO {message: "Invalid cookiePolicy", stack:
"gapi.auth2.ExternallyVisibleError: Invalid cookieP… at handleResponse
(extensions::sendRequest:67:7)"}
Here is how I'm trying to authenticate them:
background.js
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://apis.google.com/js/client.js?onload=callbackFunction";
head.appendChild(script);
chrome.identity.getAuthToken({interactive: true}, authorize);
function authorize(token) {
gapi.auth.authorize({
client_id: '800382879116-k3luktdc1lmb1e1fml8i8u.apps.googleusercontent.com',
immediate: true,
scope: 'https://www.googleapis.com/auth/gmail.readonly'
},
function(result){
console.log(result);
gapi.client.load('gmail', 'v1', callback);
});
}
background.html
<!DOCTYPE html>
<html>
<body>
<script src='scripts/background.js'></script>
</body>
</html>
manifest.json
{
"name": "Gmail Typo Analyzer",
"version": "0.1",
"description": "Gmail Typo Analyzer",
"permissions": [
"identity",
"storage"
],
"content_security_policy": "script-src 'self' https://apis.google.com; object-src 'self'",
"oauth2": {
"client_id": "82879116-k3luktdc1li8u.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/userinfo.email"
]
},
"browser_action": {
"default_popup": "popup.html",
"default_icon": "images/Icon_16.png"
},
"background": {
"page": "background.html",
"persistent": false
},
"icons": {
"16": "images/Icon_16.png",
"32": "images/Icon_32.png",
"48": "images/Icon_48.png",
"128": "images/Icon_128.png"
},
"manifest_version": 2,
"key": "c0Kn5f+t92r4P8lmmoDlKtQ6X9Q42UfFtkkiSRBAVMPHnIHqOQvYC67VczJefSNTGpUYa8+wQDFoFj/clH9SfR+BvOGgI6BUVKBNGGoFS"
}
I'm super lost right now as their doesn't seem to be a definitive guide on achieving what I'm trying to do anywhere. Does anyone know what I might be doing wrong?

You didn't post your manifest.json file, where you would set the oauth2 credentials, so I would try something like:
manifest.json
...
"oauth2" : "client_id": "800382879116-k3luktdc1lmb1e1fml8i8u.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/gmail.readonly"
]
...
background.js
chrome.identity.getAuthToken({interactive: true}, authorize);
function authorize(token) {
if (token) {
//user has given authorization, use token for requests.
//...
} else {
//no authorization received.
console.log('No authorization. Error: ' + chrome.runtime.lastError);
}
};
And you don't need to load Google API client, you can access Gmail's Restful API with XMLHttpRequests or Fetch API.

I used to get that cookie error too, but for Chrome extensions I only know how to load them from unpacked in the Extensions tab. So using gapi directly never worked for me.
As Ivan mentioned, Chrome extensions have this support "built-in" by setting the "oauth2" section in the manifest. Then you can call the APIs directly with Ajax like Ivan's example.
To build on Ivan's example, this is my working code to get a list of contacts. I haven't read from the XHR object yet, but Fiddler confirms that the data is coming back fine without any cookie or CORS errors. Of course make sure you enable these APIs in console.developers.google.com.
chrome.identity.getAuthToken({ interactive: true }, authorize);
function authorize(token) {
if (token) {
console.log(token);
var xhr = new XMLHttpRequest();
xhr.open('GET',
"https://people.googleapis.com/v1/people/me/connections?personFields=names");
xhr.setRequestHeader('Authorization',
'Bearer ' + token);
xhr.send();
//user has given authorization, use token for requests.
//...
} else {
console.log('No authorization. Error: ' + chrome.runtime.lastError);
}
};

Related

XMLHttpRequest working on chrome but not in firefox

I'm currently working on an extension to integrate two systems at my work,
The chrome extension is running just fine and working well, but my team also asked for a firefox version, in firefox I'm having trouble with the xmlhttprequest(),
the function that calls the request is this one:
function getModelList(API_KEY)
{
return new Promise(resolve => {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "POST", 'http://10.255.12.128/api/get_models/', true );
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.onload = function(e) {
resolve(xmlHttp.response);
};
xmlHttp.onerror = function (e) {
resolve(undefined);
console.error("** An error occurred during the XMLHttpRequest");
};
xmlHttp.send( 'API_KEY='+API_KEY );
})
}
(I know it not secure to send the API_KEY in the POST, but it only runs in our localnetwork so its probably fine for now)
When I run it, it goes direcly to onerror, It is faster then the timeout, and don't show in the network tab on inspection, I think I need to give it some permissions or something in firefox so it can run?
also, the manifest for the extension is this one(maybe the problem is here?):
{
"name" : "Zabbix-Bitrix Integration",
"version": "0.0.4",
"manifest_version": 2,
"description" : "Insere funções extras ao zabbix",
"options_ui": {
"page": "options.html",
"open_in_tab": false,
"browser_style": true,
"chrome_style": true
},
"content_scripts" : [
{
"js" : ["init.js"],
"css": ["styles.css"],
"matches" : ["*://zabbix.monitor.redeunifique.com.br/zabbix.php?action=problem.view*"]
}
],
"permissions": ["storage","webRequest"]
}
#edit, after some digging, found an error message:
Error: Got a request http://10.255.12.128/api/get_models/ without a browsingContextID set
The function that calls the error has this comment:
// Ensure that we have a browsing context ID for all requests when debugging a tab (=`browserId` is defined).
// Only privileged requests debugged via the Browser Toolbox (=`browserId` null) can be unrelated to any browsing context.
if (!this._browsingContextID && this._networkEventWatcher.browserId) {
throw new Error(
`Got a request ${this._request.url} without a browsingContextID set`
);
}
How and where do I set this Context ID ?

Unable to connect different files of Chrome Extension

I have been trying to make a chrome extension that gives the meaning of the selected text using urban dictionary API. I have tried different approaches but unable to connect all the files for proper execution.
manifest.json
{
"manifest_version": 2,
"name": "Urban Dictionary",
"version": "0.1",
"description": "Dictionary based on Urban Dict.",
"browser_action": {
"default_popup": "popup.html"
},
"icons": {
"16": "images/images.jpg",
"32": "images/images.jpg",
"48": "images/images.jpg",
"128":"images/images.jpg"
},
"permissions": [
"tabs",
"activeTab"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>meaning</title>
</head>
<body>
<h1>meaning</h1>
<button id="test"></button>
<script src="popup.js"></script>
<script src="getword.js"></script>
</body>
</html>
popup.js
chrome.tabs.executeScript(null, {file: "getword.js"},(results)=>{ console.log(results); } );
getword.js
var something;
var term = window.getSelection().toString()
fetch("https://mashape-community-urban-dictionary.p.rapidapi.com/define?term="+term, {
"method": "GET",
"headers": {
"x-rapidapi-key": "My_API_KEY",
"x-rapidapi-host": "mashape-community-urban-dictionary.p.rapidapi.com"
}
})
.then(response => response.json())
.then(result => {
console.log(result)
something=result.list[0].definition
}
)
.catch(err => {
console.error(err);
});
console.log(something)
document.getElementById("test").innerHTML = something;
When trying to manipulate HTML using getword.js. The result comes out to be undefined.
I would be highly obliged if anyone can help me in any way to refactor this code.
In chrome extensions you always define your background scripts in manifest file otherwise it wont work.
like this :
"background": {
"scripts": [
"back.js"
],
"persistent": true
},
Secondly Popup.js needs to be included in your pop.html like we normally do <script src="popup.js"></script>
and lastly there is another type of script that is called content script which also needs to be included in manifest to work at all.
like this:
"content_scripts": [
{
"js": ["jquery-3.5.0.min.js","content.js"]
}
],
According to your need you should probably study content scripts i think.
There are several problems:
Injected code can't make cross-origin network requests.
getword.js's purpose is to be injected as a content script so it runs in the web page and thus shouldn't be listed in popup.html as the popup is a separate extension page in a separate window not related to the web page.
The solution is straightforward:
get the selected text from the web page,
transfer it to the popup script,
make the network request and show the result.
manifest.json (MV2) should list the API site in permissions:
"manifest_version": 2,
"permissions": [
"activeTab",
"https://mashape-community-urban-dictionary.p.rapidapi.com/"
]
popup.html: remove getword.js from html and delete getword.js file.
popup.js:
const API_HOST = 'mashape-community-urban-dictionary.p.rapidapi.com';
const API_OPTS = {
headers: {
'x-rapidapi-key': 'My_API_KEY',
'x-rapidapi-host': API_HOST,
},
};
chrome.tabs.executeScript({
code: 'getSelection().toString()',
}, async pageData => {
try {
const term = pageData[0].trim();
if (!term) throw new Error('No selection!');
const apiUrl = `https://${API_HOST}/define?term=${encodeURIComponent(term)}`;
const apiRes = await (await fetch(apiUrl, API_OPTS)).json();
const def = apiRes.list[0].definition;
document.getElementById('test').textContent = def;
} catch (e) {
document.getElementById('test').textContent =
chrome.runtime.lastError ? 'Cannot access this page' : e.message;
}
});

OAuth for GAPI - Avoid Authentication and Authorization after initial sign in for Javascript

I have created a chrome extension that reads email, does something and create tasks using google client API for javascript.
I am using chrome identity for authentication and authorization.
The extension works as expected. However, it keeps asking for sign every once in a while. What I want is to authorize the user in the background script so that they don't need to do it over and over again, after the initial authentication and authorization.
What I have done so far:
I read that I need a refresh token to avoid this. However, refresh tokens are expected to be exchanged and stored on the server side and not client side (which wouldn't work because the background script is doing the job here which is client side)
Using gapi.auth.authorize with immediate true. That gives error regarding external visibility. When I read else, they suggested using it inside a server. I am not sure how can I do that in a chrome extension.
Turn interactive to false in getAuthToken, which starts giving error 401 due to authentication problem after the access token expires.
Following is the code I am using for authentication and authorization, with function onGoogleLibraryLoaded being called after loading the google api's client js file.
var signin = function (callback) {
chrome.identity.getAuthToken({interactive: true}, callback);
};
function onGoogleLibraryLoaded() {
signin(authorizationCallback);
}
var authorizationCallback = function (data) {
gapi.auth.setToken({access_token: data});
gapi.client.load('tasks', 'v1')
gapi.client.load('gmail', 'v1', function () {
console.log("Doing my stuff after this ..")
});
};
UPDATE:
As per the suggestion in the answer, I made some changes to the code. However, I am still facing the same issue. Following is the updated code snippet
jQuery.loadScript = function (url, callback) {
jQuery.ajax({
url: url,
dataType: 'script',
success: callback,
async: false
});
}
//This is the first thing that happens. i.e. loading the gapi client
if (typeof someObject == 'undefined') $.loadScript('https://apis.google.com/js/client.js',
function(){
console.log("gapi script loaded...")
});
//Every 20 seconds this function runs with internally loads the tasks and gmail
// Once the gmail module is loaded it calls the function getLatestHistoryId()
setInterval(function() {
gapi.client.load('tasks', 'v1')
gapi.client.load('gmail', 'v1', function(){
getLatestHistoryId()
})
// your code goes here...
}, 20 * 1000); // 60 * 1000 milsec
// This is the function that will get user's profile and when the response is received
// it'll check for the error i.e. error 401 through method checkForError
function getLatestHistoryId(){
prevEmailData = []
var request = gapi.client.gmail.users.getProfile({
'userId': 'me'
});
request.execute(function(response){
console.log("User profile response...")
console.log(response)
if(checkForError(response)){
return
}
})
}
// Now here I check for the 401 error. If there's a 401 error
// It will call the signin method to get the token again.
// Before calling signin it'll remove the saved token from cache through removeCachedAuthToken
// I have also tried doing it without the removeCachedAuthToken part. However the results were the same.
// I have left console statements which are self-explanatory
function checkForError(response){
if("code" in response && (response["code"] == 401)){
console.log(" 401 found will do the authentication again ...")
oooAccessToken = localStorage.getItem("oooAccessTokenTG")
console.log("access token ...")
console.log(oooAccessToken)
alert("401 Found Going to sign in ...")
if(oooAccessToken){
chrome.identity.removeCachedAuthToken({token: oooAccessToken}, function(){
console.log("Removed access token")
signin()
})
}
else{
console.log("No access token found to be remove ...")
signin()
}
return true
}
else{
console.log("Returning false from check error")
return false
}
}
// So finally when there is 401 it returns back here and calls
// getAuthToken with interactive true
// What happens here is that everytime this function is called
// there is a signin popup i.e. the one that asks you to select the account and allow permissions
// That's what is bothering me.
// I have also created a test chrome extension and uploaded it to chrome web store.
// I'll share the link for it separately.
var signin = function (callback) {
console.log(" In sign in ...")
chrome.identity.getAuthToken({interactive: true}, function(data){
console.log("getting access token without interactive ...")
console.log(data)
gapi.auth.setToken({access_token: data});
localStorage.setItem("oooAccessTokenTG", data)
getLatestHistoryId()
})
};
Manifest goes like this:
{
"manifest_version": 2,
"name": "Sign in Test Extension ",
"description": "",
"version": "0.0.0.8",
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
},
"content_security_policy": "script-src 'self' 'unsafe-eval' https://apis.google.com; object-src 'self'",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"identity",
"storage"
],
"oauth2": {
"client_id": "1234.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/gmail.readonly"
]
},
"background":{
"scripts" : ["dependencies/jquery.min.js", "background.js"]
}
}
Anyone else facing the same issue?
I am also using the identity API for google authorization in my chrome extension. I used to get the 401 status when my google token expired. So I added a check that if I am getting 401 status response of my request, then I will again authorize and get the token (it will happen in background) and continue my work.
Here is an example from my background.js
var authorizeWithGoogle = function() {
return new Promise(function(resolve, reject) {
chrome.identity.getAuthToken({ 'interactive': true }, function(result) {
if (chrome.runtime.lastError) {
alert(chrome.runtime.lastError.message);
return;
}
if (result) {
chrome.storage.local.set({'token': result}, function() {
resolve("success");
});
} else {
reject("error");
}
});
});
}
function getEmail(emailId) {
if (chrome.runtime.lastError) {
alert(chrome.runtime.lastError.message);
return;
}
chrome.storage.local.get(["token"], function(data){
var url = 'https://www.googleapis.com/gmail/v1/users/me/messages/id?alt=json&access_token=' + data.token;
url = url.replace("id", emailId);
doGoogleRequest('GET', url, true).then(result => {
if (200 === result.status) {
//Do whatever from the result
} else if (401 === result.status) {
/*If the status is 401, this means that request is unauthorized (token expired in this case). Therefore refresh the token and get the email*/
refreshTokenAndGetEmail(emailId);
}
});
});
}
function refreshTokenAndGetEmail(emailId) {
authorizeWithGoogle().then(getEmail(emailId));
}
I don't need to log in again and again manually. The google token is refreshed automatically in the background.
So this is what I believe would be the answer to my question.
Few important things to know
Chrome sign in is not same as gmail sign in. You could have UserA signed into chrome, while you plan to use the chrome extension with UserB. chrome.identity.getAuthToken won't work in that case, because it looking for the user signed into chrome.
For using other google accounts i.e. the one not signed into chrome, you would need to use chrome.identity.launchWebAuthFlow. Following are the steps you can use. I am referring the example given here (Is it possible to get an Id token with Chrome App Indentity Api?)
Go to google console, create your own project > Credentials > Create Credentials > OAuthClientID > Web Application. On that page in the field Authorized redirect URIs, enter the redirect url in the format https://.chromiumapp.org. If you don't know what chrome extension ID is, refer this (Chrome extension id - how to find it)
This would generate a client id that would go into your manifest file. Forget about any previous client id you might have created. Let's say in our example the client id is 9999.apps.googleusercontent.com
Manifest file:
{
"manifest_version": 2,
"name": "Test gmail extension 1",
"description": "description",
"version": "0.0.0.1",
"content_security_policy": "script-src 'self' 'unsafe-eval' https://apis.google.com; object-src 'self'",
"background": {
"scripts": ["dependencies/jquery.min.js", "background.js"]
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"identity",
"storage"
],
"oauth2": {
"client_id": "9999.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/tasks"
]
}
}
Sample code for getting user's info in background.js
jQuery.loadScript = function (url, callback) {
jQuery.ajax({
url: url,
dataType: 'script',
success: callback,
async: false
});
}
// This is the first thing that happens. i.e. loading the gapi client
if (typeof someObject == 'undefined') $.loadScript('https://apis.google.com/js/client.js',
function(){
console.log("gapi script loaded...")
});
// Every xx seconds this function runs with internally loads the tasks and gmail
// Once the gmail module is loaded it calls the function getLatestHistoryId()
setInterval(function() {
gapi.client.load('tasks', 'v1')
gapi.client.load('gmail', 'v1', function(){
getLatestHistoryId()
})
// your code goes here...
}, 10 * 1000); // xx * 1000 milsec
// This is the function that will get user's profile and when the response is received
// it'll check for the error i.e. error 401 through method checkForError
// If there is no error i.e. the response is received successfully
// It'll save the user's email address in localstorage, which would later be used as a hint
function getLatestHistoryId(){
var request = gapi.client.gmail.users.getProfile({
'userId': 'me'
});
request.execute(function(response){
console.log("User profile response...")
console.log(response)
if(checkForError(response)){
return
}
userEmail = response["emailAddress"]
localStorage.setItem("oooEmailAddress", userEmail);
})
}
// Now here check for the 401 error. If there's a 401 error
// It will call the signin method to get the token again.
// Before calling the signinWebFlow it will check if there is any email address
// stored in the localstorage. If yes, it would be used as a login hint.
// This would avoid creation of sign in popup in case if you use multiple gmail accounts i.e. login hint tells oauth which account's token are you exactly looking for
// The interaction popup would only come the first time the user uses your chrome app/extension
// I have left console statements which are self-explanatory
// Refer the documentation on https://developers.google.com/identity/protocols/OAuth2UserAgent >
// Obtaining OAuth 2.0 access tokens > OAUTH 2.0 ENDPOINTS for details regarding the param options
function checkForError(response){
if("code" in response && (response["code"] == 401)){
console.log(" 401 found will do the authentication again ...")
// Reading the data from the manifest file ...
var manifest = chrome.runtime.getManifest();
var clientId = encodeURIComponent(manifest.oauth2.client_id);
var scopes = encodeURIComponent(manifest.oauth2.scopes.join(' '));
var redirectUri = encodeURIComponent('https://' + chrome.runtime.id + '.chromiumapp.org');
// response_type should be token for access token
var url = 'https://accounts.google.com/o/oauth2/v2/auth' +
'?client_id=' + clientId +
'&response_type=token' +
'&redirect_uri=' + redirectUri +
'&scope=' + scopes
userEmail = localStorage.getItem("oooEmailAddress")
if(userEmail){
url += '&login_hint=' + userEmail
}
signinWebFlow(url)
return true
}
else{
console.log("Returning false from check error")
return false
}
}
// Once you get 401 this would be called
// This would get the access token for user.
// and than call the method getLatestHistoryId again
async function signinWebFlow(url){
console.log("THE URL ...")
console.log(url)
await chrome.identity.launchWebAuthFlow(
{
'url': url,
'interactive':true
},
function(redirectedTo) {
if (chrome.runtime.lastError) {
// Example: Authorization page could not be loaded.
console.log(chrome.runtime.lastError.message);
}
else {
var response = redirectedTo.split('#', 2)[1];
console.log(response);
access_token = getJsonFromUrl(response)["access_token"]
console.log(access_token)
gapi.auth.setToken({access_token: access_token});
getLatestHistoryId()
}
}
);
}
// This is to parse the get response
// referred from https://stackoverflow.com/questions/8486099/how-do-i-parse-a-url-query-parameters-in-javascript
function getJsonFromUrl(query) {
// var query = location.search.substr(1);
var result = {};
query.split("&").forEach(function(part) {
var item = part.split("=");
result[item[0]] = decodeURIComponent(item[1]);
});
return result;
}
Feel free to get in touch with me if you have any questions. I have spent quite a few days joining these dots. I wouldn't want someone else to do the same.

XMLHttpRequest from Firefox WebExtension

I've seen loads of examples of creating xhr requests from Firefox Add-ons, but I am trying to use the new WebExtensions stuff (where require and Components are undefined) and can't seem to see why I can't send a simple XmlHttpRequest from within the extension?
It's worth noting that the ajax request is going to a completely different URL, but the host has CORs set to allow all origins.
As soon as .send() is fired I get the error:
[Exception... "Failure" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: resource://gre/modules/ExtensionContent.jsm -> moz-extension://9ca18411-9a95-4fda-8184-9dcd3448a41a/myapp.js :: GM_xmlhttpRequest :: line 162" data: no]"1 whatsapp.js:166:9
The code looks like this:
function GM_xmlhttpRequest(orders) {
try {
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", function(a1, a2, a3) {
console.log('xhr.load: %s, %s, %s', a1, a2, a3);
});
// open synchronously
oReq.open(orders.method, orders.url, false);
// headers
for (var key in orders.headers) {
oReq.setRequestHeader(key, orders.headers[key]);
}
// send
var res = oReq.send(orders.data);
console.log('xhr result: %s', res);
} catch(e) {
debugger;
console.warn('could not send ajax request %s to %s, reason %s', orders.method, orders.url, e.toString());
}
}
I've added webRequest permissions to my manifest.json, I realise that is not what it means, but am struggling to understand what is stopping the ajax request? Any ideas?
{
"manifest_version": 2,
"name": "MyApp",
"version": "1.0",
"description": "TestXHR",
"icons": {
"48": "icons/myapp-48.png"
},
"applications": {
"gecko": {
"id": "software#vigilantapps.com",
"strict_min_version": "45.0"
}
},
"content_scripts": [
{
"matches": ["*://web.myapp.com/*"],
"js": ["myapp.js"]
}
],
"permissions": [
"https://thehost.all-xhr-sent-here.net/*",
"webRequest"
]
}
The problem was the permissions URL specified. I changed the sub domain to an asterisk and the protocol to an asterisk and it seemed to work after that.

Chrome Extension - Channels Not Working

I am trying to create a channel to my Google App Engine (Python) server, and there seems to be a problem but I am unsure why. When the user toggles the extension, it authenticates the user. If successful, the server replies with a channel token which I use to create the channel. When I authenticate the user, alert("a") appears, but alert("b") does not which makes me believe there is a problem with the line var channel = new goog.appengine.Channel(msg.token);, but the console does not report an error.
I have also copied the javascript code from here and placed it in my manifest as oppose to putting <script type="text/javascript" src="/_ah/channel/jsapi"></script> in background.html.
//script.js
function authenticate(callback) {
var url = "https://r-notes.appspot.com/init/api/authenticate.json?username=" + username + "&password=" + password;
$.post(url, function(data) {
if (data.status == "200") {
channelToken = data.channeltoken;
if (callback) {
callback();
}
var port = chrome.extension.connect({name: "myChannel"});
port.postMessage({token: channelToken});
port.onMessage.addListener(function(msg) {
console.log(msg.question);
});
}
});
}
//background.html
chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
alert("a"); //pops up
var channel = new goog.appengine.Channel(msg.token);
alert("b"); //does not pop up
console.log(channel); //display error ' Error in event handler for 'undefined': ReferenceError: goog is not defined '
var socket = channel.open()
socket.onopen = function() {
// Do stuff right after opening a channel
console.log('socket opened');
}
socket.onmessage = function(evt) {
// Do more cool stuff when a channel message comes in
console.log('message recieved');
console.log(evt);
}
});
});
//manifest.json
{
"name": "moot",
"description": "Clicking on the moot button will display a sidebar!",
"version": "0.2.69",
"background_page": "html/background.html",
"browser_action": {
"default_icon": "img/icon_64.png",
"default_title": "moot"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/channelApi.js",
"js/script.js", "js/mootsOnSidebar.js", "js/mootsOnPage.js", "js/authenticate.js", "js/otherFunctions.js",
"js/jquery/jquery-1.7.1.js", "js/jquery/jquery.mCustomScrollbar.js", "js/jquery/jquery-ui.min.js",
"js/jquery/jquery.autosize.js", "js/jquery/jquery.mousewheel.min.js", "js/jquery/jquery.easing.1.3.js",
"js/channel.js"],
"css": ["css/cssReset.css", "css/sidebar.css", "css/onPageCreate.css", "css/onPageExists.css", "css/scrollbar.css", "css/authenticate.css"]
}
],
"permissions": [
"tabs", "contextMenus", "http://*/*", "https://*/"
],
"icons": {
"16": "img/icon_16.png",
"64": "img/icon_64.png"
}
}
EDIT - After doing console.log(channel), I discovered the error ' Error in event handler for 'undefined': ReferenceError: goog is not defined '. I am unsure why I receive this error as I did include the required javascript file as I followed this post.
So the solution is that you need to include the file <script type="text/javascript" src="https://talkgadget.google.com/talkgadget/channel.js"></script> in a HTML page. I placed this on the first row of background.html.
My mistake was saving a local copy of channel.js, and refer to it in manifest.json.
I'm now going to place a copy of channel.js on my server, and refer to my server's copy. I don't think there will be any issues with that.
Make a console log for the value of msg direct between alert("a") and var channel = ...
and inspect the value.

Categories

Resources