谷歌插件开发(实现CSDN快速登陆)
谷歌浏览器插件带来了很大的方便,于是就想着是不是也可以开发一个来用用。几经折腾下,开发了个CSDN快速 登陆的插件。下面简述一下开发的步骤。
1、开发工具:谷歌浏览器(我开发时用的是chrome 30.0.1599.101 )、HTML/JS/CSS/JSON开发工具(UE、VS等,当然也可以用记事本)
2、开发过程
(1)新建清单文件manifest.json:该名字不可以改。下面是代码
{
"manifest_version": 2,
"background": {
"page": "main.html"//后台运行页,page和scrptis只能选择一个
},
"browser_action":{
"default_icon":"assets/images/Icon.png",//插件默认图标
"default_title":"__MSG_manifest_iconTitle__",//插件标题
"default_popup":"popup.html"//单击插件图标时弹出的页面
},
"default_locale":"en",//默认本地化语言
"description":"__MSG_manifest_appDescription__",//插件描述
"icons":{//显示的图标
"16":"assets/images/Icon.png",
"128":"assets/images/Icon.png"
},
"name":"__MSG_manifest_appName__",//插件名字
"options_page":"options.html",//插件选项页
"permissions":[ "proxy", "tabs", "<all_urls>","notifications"],//申请需要的权限
"version":"1.1.1",//插件版本
"minimum_chrome_version":"18.0.0"//浏览器最低版本
}
其中__MSG_manifest_iconTitle__、__MSG_manifest_appDescription__、__MSG_manifest_appName__是依据系统语言的本地化配置,比如在简体中文系统和英文系统时会本地化成相应的语言,见下图
(2)新建弹出页(popup.html)
写HTML和CSS代码,排布出如上图所示的界面
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="assets/styles/popup.css" type="text/css">
<script src="assets/libs/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="assets/scripts/Popup.js" type="text/javascript"></script>
</head>
<body>
<div id="set_config">
<div class="header title" data-i18n-content="popup_setting">Setting</div>
<div class="header light">
<table>
<tr>
<th>
<span data-i18n-content="popup_account_id">User</span>
</th>
<td>
<input type="text" id="setting_account_id" value="" /> </td> </tr>
<tr>
<th>
<span data-i18n-content="popup_password">Password</span>
</th>
<td>
<input type="password" id="setting_password" value="" />
</td>
</tr>
</table>
</div>
<div class="header light">
<table class="control">
<tr>
<td>
<button class="button bold" id="setting_login" data-i18n-content="popup_setting_login">Save</button>
</td>
<td> </td>
<td>
<button class="button bold" id="setting_cancel" data-i18n-content="popup_setting_cancel">Cancel</button>
</td>
</tr>
</table>
</div>
</div>
</body> </html>
注意:这里面也采用了本地化配置,data-i18n-content="popup_setting"一类的写法,就是进行本地化配置,不过需要通过i18n.js来配套实现。i18n表示的是国际化。人们常把I18N作为“国际化”的简称,其来源是英文单词 internationalization的首末字符i和n。18为中间的字符数。
这里面还用到了popup.js和jquery。jquery是JS库,网上可以下载到。popup.js代码如下
/// <reference path="Config.js"/>
/// <reference path="Settings.js"/>
/// <reference path="Notify.js"/> var Popup = {};
Popup.CONTROL_IDS = {
SET_CANCEL: "setting_cancel",
SET_LOGIN: "setting_login",
SETTING_ACCOUNT_ID: "setting_account_id",
SETTING_PASSWORD: "setting_password"
}; $(document).ready(function () {
Popup.init();
$("#" + Popup.CONTROL_IDS.SET_LOGIN).click(Popup.setLogin);
$("#" + Popup.CONTROL_IDS.SET_CANCEL).click(Popup.setCancel);
}); Popup.init = function () {
Popup.extension = chrome.extension.getBackgroundPage();
Settings = Popup.extension.Settings;//Settings in Settings.js
Config = Popup.extension.Config;//Config in Config.js
Notify = Popup.extension.Notify;
I18n = Popup.extension.I18n;//I18n in I18n.js
I18n.process(document);
document.body.style.visibility = "visible";
Popup.initUI();
} Popup.initUI = function () {
$("#" + Popup.CONTROL_IDS.SETTING_ACCOUNT_ID).attr("value", Settings.getValue(Config.KEYS.ACCOUNT_ID, ''));
$("#" + Popup.CONTROL_IDS.SETTING_PASSWORD).attr("value", Settings.getValue(Config.KEYS.PASSOWRD, ''));
} Popup.openPage = function () {
Popup.closePopup();
chrome.tabs.create({//新建标签页
url: Config.URLS.LOGIN
});
} Popup.openOptions = function () {
Popup.closePopup();
extension.openOptions();
} Popup.closePopup = function () {
window.close();
} Popup.setCancel = function () {
Popup.closePopup();
} Popup.setLogin = function () { Settings.setValue(Config.KEYS.ACCOUNT_ID, $("#" + Popup.CONTROL_IDS.SETTING_ACCOUNT_ID).val());
Settings.setValue(Config.KEYS.PASSOWRD, $("#" + Popup.CONTROL_IDS.SETTING_PASSWORD).val()); Notify.notifyText(Config.FILES.NOTIFY_IMAGE, '', 'OK'); Popup.openPage();
}
说明:
1) /// <reference path="Config.js"/>是VS中为了可以像类一样点出相应的字段和方法的引用方法。
2)$(document).ready是popup.html加载完成后进行相应的操作,比如初始化按钮的点击事件等。chrome是不可以在页面中直接写内连的JS的,那样有安全隐患。
<scritp type="text/javascript">
//内连脚本
function test(){ alert("test");}
</script>
如果非要进行内连,那必须将其转换成64码,然后连到src中(直接放到scrpit中的scr中不可以,需要放到iframe中。不知道具体是什么原因。),如下面代码。
<iframe id="sandbox-frame" sandbox="allow-scripts" src="data:text/html;base64,JTNDc2NyaXB0JTIwdHlwZSUzRCUyMnRleHQvamF2YXNjcmlwdCUyMiUzRSUwQWFsZXJ0JTI4JTIyQUFBQSUyMiUyOSUzQiUwQSUzQy9zY3JpcHQlM0U="></iframe>
3)最重要的是Popup.init函数,这个函数将后台的js引用到前台(popup.js是从前台界面popup.html中引用的,所以为前台JS),以便于更好的调用。
Popup.extension = chrome.extension.getBackgroundPage()先把后台引用到前台。
Config = Popup.extension.Config是从后台将Config引用到前台来,其中Config不是Config.js的脚本名字,而是Config.js中的var Config={}。其他的引用同理。
I18n.process(document)这是进行本地化配置。
(3)后台JS
后台JS需要放到main.html中,代码如下
<html>
<head>
<meta charset="UTF-8" />
<title></title>
<script src="assets/libs/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="assets/scripts/CSDN.js" type="text/javascript"></script>
<script src="assets/scripts/Settings.js" type="text/javascript"></script>
<script src="assets/scripts/Config.js" type="text/javascript"></script>
<script src="assets/scripts/I18n.js" type="text/javascript"></script>
<script src="assets/scripts/Notify.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
1)CSDN.js
/// <reference path="Config.js"/>
var CSDN = {}; chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {//添加监听事件
var url = tab.url;
var config = null;
if (tab.status !== "complete") {//需要增加这一判断,不然会在页面加载和加载完成后分别触发
return;
}
CSDN.login(url);
}); CSDN.CONTROL_IDS = {
ACCOUNT_ID: "u",
PASSWORD: "p",
LOGIN: "aLogin",
LOGIN_IFRAME: "logfrm"
}; CSDN.isLoginUrl = function (url) {
if (url === Config.URLS.LOGIN) { return true;
}
else {
return false;
}
} CSDN.login = function (url) {
if (!CSDN.isLoginUrl(url)) {
return;
}
var accountID = Settings.getValue(Config.KEYS.ACCOUNT_ID, '');
var password = Settings.getValue(Config.KEYS.PASSOWRD, '');
var scripts = "";
if (accountID === undefined || accountID === null || accountID.replace(/(^\s*)|(\s*$)/g, "").length <= 0) {
return;
} scripts += "var loginIFrame = document.getElementById('" + CSDN.CONTROL_IDS.LOGIN_IFRAME + "');"
+ " var loginDocument=loginIFrame.contentWindow.document;"
+ "loginDocument.getElementById('" + CSDN.CONTROL_IDS.ACCOUNT_ID + "').value='" + accountID + "';"
+ "loginDocument.getElementById('" + CSDN.CONTROL_IDS.PASSWORD + "').value='" + password + "';"
+ "loginDocument.getElementById('" + CSDN.CONTROL_IDS.LOGIN + "').click();"
chrome.tabs.executeScript(null, {//嵌入JS脚本到所打开的页面中。
code: scripts
});
}
2)Notify.js
从浏览器中发出桌面通知,代码如下
var Notify = {};
Notify.notifyText = function (iconUrl, title, content) {//这个要触发,必须在manifest.json中添加notifications,以申请桌面通知权限
var notification = window.webkitNotifications.createNotification(iconUrl, title, content);
notification.show();
}
3)其他JS代码如下
Config.js
var Config = {}; Config.KEYS = {
ACCOUNT_ID: "accountID",
PASSOWRD: "password"
}; Config.FILES = {
NOTIFY_IMAGE: "assets/images/Notify.png"
}; Config.URLS = {
LOGIN: "https://passport.csdn.net/account/login"
};
Setting.js
var Settings = {}; Settings.configCache = {}; Settings.setValue = function setValue(key, value) {
Settings.configCache[key] = value; var config = {};
if (localStorage.config)
config = JSON.parse(localStorage.config); config[key] = value;
localStorage.config = JSON.stringify(config);
return value;
}; Settings.getValue = function getValue(key, defaultValue) {
if (typeof Settings.configCache[key] != "undefined")
return Settings.configCache[key]; if (!localStorage.config)
return defaultValue; var config = JSON.parse(localStorage.config);
if (typeof config[key] == "undefined")
return defaultValue; Settings.configCache[key] = config[key];
return config[key];
}; Settings.keyExists = function keyExists(key) {
if (!localStorage.config)
return false; var config = JSON.parse(localStorage.config);
return (config[key] != undefined);
}; Settings.setObject = function setObject(key, object) {
localStorage[key] = JSON.stringify(object);
return object;
}; Settings.getObject = function getObject(key) {
if (localStorage[key] == undefined)
return undefined; return JSON.parse(localStorage[key]);
}; Settings.refreshCache = function refreshCache() {
Settings.configCache = {};
};
I18n.js
var I18n = {}; I18n.messages = null; I18n.init = function init() {
I18n.messages = I18n.readMessages();
// I18n.readMessages(function(messages) {
// I18n.messages = messages;
// });
}; I18n.buildMessages = function buildMessages() {
var result = "\n"; $("*[data-i18n-content]").each(function (i, item) {
result += '"' + item.getAttribute("i18n-content") + '"' +
': { "message": "' + item.innerHTML.replace(/[ \r\n\t]+/g, " ") + '" },\n';
}); $("*[data-i18n-values]").each(function (i, item) {
$(item.getAttribute("i18n-values").split(";")).each(function (i, subItem) {
var subItemParts = subItem.split(":");
if (subItemParts.length == 2 && subItemParts[0].charAt(0) != ".") {
result += '"' + subItemParts[1] + '"' +
': { "message": "' + item.getAttribute(subItemParts[0]).replace(/[\r\n]/g, "\\n") + '" },\n';
}
});
}); return result;
}; I18n.readMessages = function readMessages(callback) {
var async = (callback != undefined);
var data = null;
var request = new XMLHttpRequest();
request.open("GET", chrome.extension.getURL("_locales/en/messages.json"), async);
request.onreadystatechange = function () {
if (this.readyState == XMLHttpRequest.DONE) {
data = this.responseText;
data = JSON.parse(data.replace(/[\r\n\t]+/g, " "));
if (async)
callback(data);
}
};
request.send(""); return data;
}; I18n.getMessage = function getMessage(messageName, substitution) {
var result = chrome.i18n.getMessage(messageName, substitution);
if (result == undefined || result.length == 0) {
var messageObject = I18n.messages[messageName];
if (messageObject != undefined) {
result = messageObject.message;
if (result != undefined)
result = result.replace("$1", substitution);
}
}
return result;
}; I18n.process = function process(node) {
return I18nTemplate.process(node);
}; I18n.init(); //------------------------------------------------------- /**
* i18nTemplate: http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/resources/i18n_template.js
*/
var I18nTemplate = (function () {
var handlers = {
/**
* This handler sets the textContent of the element.
*/
'data-i18n-content': function (element, attributeValue) {
element.innerHTML/*textContent*/ = I18n.getMessage(attributeValue);
}, /**
* This is used to set HTML attributes and DOM properties,. The syntax
* is: attributename:key; .domProperty:key; .nested.dom.property:key
*/
'data-i18n-values': function (element, attributeValue) {
var parts = attributeValue.replace(/\s/g, '').split(/;/);
for (var j = 0; j < parts.length; j++) {
var a = parts[j].match(/^([^:]+):(.+)$/);
if (a) {
var propName = a[1];
var propExpr = a[2]; var value = I18n.getMessage(propExpr);
if (propName.charAt(0) == '.') {
var path = propName.slice(1).split('.');
var object = element;
while (object && path.length > 1) {
object = object[path.shift()];
}
if (object) {
object[path] = value;
// In case we set innerHTML (ignoring others) we need to
// recursively check the content
if (path.toString() === 'innerHTML') {
process(element);
}
}
} else {
element.setAttribute(propName, value);
}
}
}
}
}; var attributeNames = [];
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
attributeNames.push(key);
}
}
var selector = '[' + attributeNames.join('],[') + ']'; function process(node) {
var elements = node.querySelectorAll(selector);
for (var element, i = 0; element = elements[i]; i++) {
for (var j = 0; j < attributeNames.length; j++) {
var name = attributeNames[j];
var att = element.getAttribute(name);
if (att != null) {
handlers[name](element, att);
}
}
}
} return {
process: process
};
})();
开发时参考了SwitchProxy的源码https://code.google.com/p/switchysharp/source/。
转载请注明出处http://blog.csdn.net/xxdddail/article/details/13504259
源码在此处下载http://download.csdn.net/detail/xxdddail/6469683
谷歌插件开发(实现CSDN快速登陆)的更多相关文章
- qq快速登陆
http://www.cnblogs.com/1996V/p/7481823.html qq快速登陆
- JS脚本实现CSDN免登陆免关闭广告插件自动展开“阅读更多”内容
最近在CSDN查资料,总是弹出以下弹窗,然后就自动跳转到登录页面,蛋疼! 于是重新捣腾了一下,修改了原来的脚本,最新的脚本代码如下: 温馨提示:在打开CSDN页面后立刻执行以下脚本即可免登陆免关闭广告 ...
- CSDN不登陆看博文
做前端的朋友说,手动改太Low,给了段JS代码: javascript: void((function() {var divElement = document.getElementById('art ...
- 使用linux/macos 自带的shell实现证书方式的快速登陆
一般登陆机器都是需要使用证书安全登陆到跳板机上然后在跳板机去登陆到各个机器. 我们建立一个统一的文件夹mykey,将登陆的pem证书放上去,然后创建一个空白的文件,vim jump.sh #!/usr ...
- Chrome之谷歌插件开发
最近碰到一个需求,需要在某个平台上批量的添加好友,如果是人工点击,可以操作,但是效率并不高,人工成本较高.就打算使用浏览器插件的方式来完成这件重复性的工作. 介绍: Chrome插件的本质就是一个由 ...
- 快速登陆linux服务器
前言 本文适用于喜欢原生终端的用户,钟爱第三方ssh客户端的可以无视....客户端可以保存用户信息和密码,比较无脑.mac可以使用终端,win可以使用git的bash. 上次分享了配置非对称秘钥免密登 ...
- 360浏览器不能打开CSDN登陆页面
碰见个奇葩问题: 使用360浏览器(广大程序员不要鄙视我~ 我有我的理由)不能打开csdn的登陆页面~~你登陆的时候,他就一直在那里打转~~ 但是用ie就可以打开登陆页面.... 怎么回事???难道C ...
- 爬虫===登陆CSDN的方法
本文主要介绍csdn的登陆,可应用在爬虫上~ # -*- coding:utf-8 -*- import json import requestsfrom xlutils.copy import co ...
- Discuz插件开发中的困惑
1.关于缓存 这几天一直纠结于Discuz的缓存问题,今天终于有点小发现:首先Discuz的缓存可以通过数据库.文件等方式进行!在Discuz的配置文件config_global.php中有一个配置项 ...
随机推荐
- JS触发ASP.NET服务器端控件的方法
<asp:Button ID="Button_regId" runat="server" Font-Bold="False" OnCl ...
- UVA 10047 The Monocycle
大白图论第二题··· 题意:独轮车的轮子被均分成五块,每块一个颜色,每走过一个格子恰好转过一个颜色. 在一个迷宫中,只能向前走或者左转90度或右转90度(我曾天真的认为是向左走和向右走···),每个操 ...
- .net-.net试题2
ylbtech-doc:.net-.net试题2 .net试题2 1.A,.net试题2返回顶部 01.{DotNet题目}下列变量的赋值,正确的是:( )(选择2项) A )int myInteg ...
- mybatis返回HashMap结果类型与映射
<!-- 返回HashMap结果 类型--> <!-- 如果想返回JavaBean,只需将resultType设置为JavaBean的别名或全限定名 --> <!-- T ...
- Druid连接池简单入门
偶尔的机会解释Druid连接池,后起之秀,但是评价不错,另外由于是阿里淘宝使用过的所以还是蛮看好的. 1.jar包依赖--Druid依赖代码 <dependency> <groupI ...
- <转>Python 参数知识(变量前加星号的意义)
csdn上的牛人就是多,加油 —————————————————————————— 过量的参数 在运行时知道一个函数有什么参数,通常是不可能的.另一个情况是一个函数能操作很多对象.更有甚者,调用自身的 ...
- DbContext运行时动态附加上一个dbset
参考 Creating DbSet Properties Dynamically C# code? 1 DbSet<MyEntity> set = context.Set<MyEnt ...
- 在Lua里写unity游戏笔记
gameobject.GetComponent<Transform>(); 翻译成Lua: gameObject:GetComponent (luanet.ctype (Transform ...
- Cloudera的安装
To enable these parts of the tutorial, choose one of the following options: To use Cloudera Express ...
- 设计模式系列 1——StaticFactory(静态工厂),AbstractFactory(抽象工厂)
本文出自 代码大湿 代码大湿 本系列持续更新,敬请关注. 1 静态工厂 静态工厂介绍: 静态工厂模式可以实现接口封装隔离的原则.在客户端只知接口而不知实现的时候可以使用静态工厂模式. 源码请点击我 角 ...