如何向Chrome扩展发送数据?
我正在为我的书签扩展开发用户认证功能。这个扩展使用的是 Google App Engine(Python)作为后台,网址是 http://ting-1.appspot.com/。
扩展第一次运行时,background.html
会在新标签页中打开 options.html
,用户需要输入他们的电子邮件地址。我打算这样把电子邮件地址发送到应用程序(还没试过):
in options.html
---------------
var formData = new FormData();
formData.append("extension_user", userEmail);
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://ting-1.appspot.com/authsender", true);
xhr.send(formData);
在应用程序中,AuthSender
负责向用户发送确认邮件:
class AuthSender(webapp.RequestHandler):
def post(self):
new_user = self.request.get("extension_user")
mail.send_mail(
sender="Ting <ting@gmail.com>",
to=new_user,
subject="Ting Bookmarking: confirm your email",
body="""click on the link below to confirm your email:
<a href="http://ting-1.appspot.com/authHandler"></a>
Happy Bookmarking!""")
如果用户点击邮件中的链接,应用程序中的 AuthReceive
处理程序会处理这个请求,并向扩展发送确认。但我还没弄明白怎么把确认信息发送回扩展。
当用户点击链接时,我该如何把确认信息发送回扩展呢?我需要再次使用 XMLHttpRequest
吗?怎么做?扩展里需要放什么样的监听器?
下面是应用程序中 AuthReceive
处理程序的草图:
class AuthReceive(InboundMailHandler):
def receive(self, message):
#---------------------------------------
#receive email // I know this part
#send confirmation to extension // I need help with this
#--------------------------------------
...
还有在 background.html
中的内容:
//...
// add listener and save the variable to localStorage
//...
谢谢你的帮助。
更新
这是为了符合 Moishe 的回答 的代码。除了最后一步 handler.onmessage
没有被触发,其他都正常。
options.html
<html>
<head><title>Extension Options</title></head>
<body>
<p>Enter your gmail address:</p>
<textarea id="getEmail" style="margin-bottom: 4px; width: 250px; height: 20px">
</textarea><br />
<button id="save">Save</button>
<!--<button id="save">Clear</button>-->
<script type="text/javascript">
document.getElementById("getEmail").placeholder = "your gmail address" ;
//send entered gmail address to the server
document.getElementById("save").addEventListener
(
"click",
function ()
{
var userEmail = document.getElementById("getEmail").value;
var formData = new FormData();
formData.append("extension_user", userEmail);
var channel;
var socket;
var handler = new Object();
handler.onmessage =
function (evt)
{
//evt.data will be what the server sends in channel.send_message
console.log("evt.data received from authhandler: " + evt.data);
};
var xhr = new XMLHttpRequest();
xhr.onReadyStateChange = function()
{
//error handling etc not included
if (xhr.readyState == 4 && xhr.status == 200)
{
token = xhr.responseText;
channel = new goog.appengine.Channel(token);
socket = channel.open(handler);
}
};
xhr.open("POST", "http://ting-1.appspot.com/authsender", true);
xhr.send(formData);
console.log("formData sent to authsender: " + formData);
}, false
)
//...
</script>
</body>
</html>
AuthSender 和 AuthHandler
class AuthSender(webapp.RequestHandler):
def post(self):
new_user = self.request.get("extension_user")
link = "http://ting-1.appspot.com/authhandler?new_user=%s" % new_user
message = mail.EmailMessage()
message.sender="Ting <ting@gmail.com>"
message.to=new_user
message.subject="Ting Bookmarking - Confirm your email"
message.body="""Click on the link to confirm your email: %s """ % link
message.send()
logging.info("message sent to: %s " % message.to)
token = channel.create_channel(new_user)
self.response.out.write(token)
class AuthHandler(webapp.RequestHandler):
def get(self):
new_user = self.request.get("new_user")
channel.send_message(new_user, new_user)
logging.info("new_user sent to client: %s" % new_user)
工作版本
(相关问题)
options.html
<html>
<head>
<title>Extension Options</title>
<!-- this does not work because it is local url
<script type="text/javascript" src="/_ah/channel/jsapi"></script>
-->
<script type="text/javascript" src="https://talkgadget.google.com/talkgadget/channel.js"></script>
</head>
<body>
<p>Enter your gmail address:</p>
<textarea id="getEmail" style="margin-bottom: 4px; width: 250px; height: 20px">
</textarea><br />
<button id="save">Save</button>
<script>
document.getElementById("getEmail").placeholder = "your gmail address" ;
document.getElementById("save").addEventListener
(
"click",
function ()
{
var userEmail = document.getElementById("getEmail").value;
var formData = new FormData();
formData.append("extension_user", userEmail);
var channel;
var socket;
var handler =
{
onopen: function () { alert("onopen") },
onerror: function () { alert("onerror") },
onclose: function () { alert("onclose") },
onmessage:
function (evt)
{
alert("evt.data is: " + evt.data)
}
};
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4 && xhr.status == 200)
{
token = xhr.responseText;
channel = new goog.appengine.Channel(token);
socket = channel.open(handler);
}
};
xhr.open("POST", "http://ting-1.appspot.com/authsender", true);
xhr.send(formData);
}, false
)
</script>
</body>
</html>
AuthSender 和 AuthHandler
class AuthSender(webapp.RequestHandler):
def post(self):
new_user = self.request.get("extension_user")
link = "http://ting-1.appspot.com/authhandler?new_user=%s" % new_user
message = mail.EmailMessage()
message.sender="Ting <ting@gmail.com>"
message.to=new_user
message.subject="Ting Bookmarking - Confirm your email"
message.body="""Click on the link to confirm your email: %s """ % link
message.send()
token = channel.create_channel(new_user)
self.response.out.write(token)
class AuthHandler(webapp.RequestHandler):
def get(self):
new_user = self.request.get("new_user")
self.response.out.write(new_user)
channel.send_message(new_user, new_user)
1 个回答
你可以使用Channel API来实现这个功能。在你发起XMLHttpRequest请求的时候,同时请求一个令牌,并打开一个频道来接收消息。当你的应用处理用户点击链接时的HTTP请求时,向为该用户的扩展创建的频道发送一条消息。
更详细的说明:
基本上,在options.html中,当你发起XHR请求时,可以这样做:
var channel;
var socket;
var handler = {
onmessage: function(evt) {
// evt.data will be what your server sends in channel.send_message
}
};
var xhr = new XMLHttpRequest();
xhr.onReadyStateChange = function() {
// error handling and whatnot elided
if (xhr.readyState == 4 and xhr.status == 200) {
// We got a response from the server. The responseText is
// a channel token so we can listen for a "verified" message.
token = xhr.responseText;
channel = new goog.appengine.Channel(token);
socket = channel.open(handler);
}
};
xhr.open("POST", "http://ting-1.appspot.com/authsender", true);
xhr.send(formData);
然后在你的服务器上,处理'authsender'页面的代码会这样写:
class AuthSenderHandler(webapp.RequestHandler):
def post(self):
# get whatever data is in the form to send an email.
# let's say that user_id is a field we extracted either from a cookie or from
# the POST parameters themselves.
link = "http://your.server.com/authHandler?user_id=%s" % user_id
message = mail.EmailMessage()
message.body = """some stuff %s""" % link
# fill in other message fields, then send it.
# now we'll create a channel token using the user_id and return
# it to the client.
token = channel.create_channel(user_id)
self.response.out.write(token)
上面这两个函数会让你的客户端在一个频道上监听。接下来的步骤是:用户点击链接后会发生什么呢?
之前,我们通过电子邮件发送了一个链接,并包含了一个user_id参数(为了说明方便;你也可以用其他东西)。现在,当用户点击这个链接时,它会向authHandler
路径发起一个HTTP请求,并将user_id
作为参数传递。所以我们可以用user_id来确定要发送消息的频道,像这样:
class AuthHandler(webapp.RequestHandler):
def get(self):
user_id = self.request.get("user_id")
# send a message indicating the user received the email and
# verified to our client page. You may want to send other data.
channel.send_message(user_id, "authorized")
# probably want to show a nice "you've been authorized" page or something
然后handler.onmessage回调会被调用,这样你就可以在用户验证了他们的电子邮件地址后,进行你需要的操作。
希望这能帮到你一点!