Google终于放出了Chrome的第一个扩展示例,虽然还十分简陋,但对喜欢扩展的firefox粉丝来说可说是个大好消息。
准备工作:你需要使用a recent developer build或者Google Chrome 2.0 beta.
1)首先创建一个文件夹,例如c:"myextension,在这个目录下创建一个文本文件,命名为manifest.json,在其中放入下面几句:
"format_version":1,
"id":"00123456789ABCDEF0123456789ABCDEF0123456",
"version":"1.0",
"name":"MyFirstExtension",
"description":"ThefirstextensionthatImade."
}
其中各个参数含义如下:
format_version(必需的):向Chrome指明扩展所使用的清单格式版本。目前只有一个格式版本,因此设为1.
id(必需的):扩展的ID号(唯一的)。目前可以设为任何40个十进制数字,将来会改为扩展的公钥的SHA-1的哈希值。
version(必需的):扩展的版本号。可以使用任意点分格式的数字串
name(必需的):扩展的名称。
description(可选的):扩展的描述信息
2)在目录下加入一个hello_world.html文件,在其中加入
3)为了让Chrome支持扩展,右键桌面上Chrome的快捷键,选择“属性”,在“目标”这一栏中空一格后,加入

4)启动Chrome,输入下列URL:
如图所示:

5)输入下列URL:
将会列出所有已经安装的扩展,同时还会显示扩展系统启动时发生的错误信息。

6)内容脚本。它是由Chrome加载进来在web页面上运行的JavaScript文件。这和firefox扩展类似。要加入一个内容脚本,首先在清单文件中对其进行注册,如下所示:
"format_version":1,
"id":"00123456789ABCDEF0123456789ABCDEF0123456",
"version":"1.0",
"name":"MyFirstExtension",
"description":"ThefirstextensionthatImade.",
"content_scripts":[
{
"matches":["http://www.google.com/*"],
"js":["foo.js"]
}
]
}
然后创建一个脚本文件foo.js,其中代码如下:
document.images[ 0 ].style.height = " auto " ;
在Chrome中输入http://www.google.com/,你将看到如下画面:

注:内容脚本可以在页面开头或结尾执行,默认情况下是结尾处执行,当然你也可以加入”run_at”:”document-start”来告诉Chrome在开头处执行。
7)NPAPI插件。Chrome扩展可以包含NPAPI插件这样的二进制组件。如果你想在扩展中使用一个NPAPI插件,首先在扩展中为其创建一个目录,名为”plugins”,然后在清单文件中为其注册如下:
"format_version":1,
"id":"00123456789ABCDEF0123456789ABCDEF0123456",
"version":"1.0",
"name":"MyFirstExtension",
"description":"ThefirstextensionthatImade.",
"plugins_dir":"plugins"
}
8)打包发布。要对扩展进行打包发布前,首先确认你安装了Python2.6,然后使用下述脚本文件chromium_extension.py
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#!/usr/bin/python
#Copyright(c)2006-2008TheChromiumAuthors.Allrightsreserved.
#UseofthissourcecodeisgovernedbyaBSD-stylelicensethatcanbe
#foundintheLICENSEfile.
#chromium_extension.py
importarray
importhashlib
importlogging
importoptparse
importos
importre
importshutil
importsys
importzipfile
ifsys.version_info<(2,6):
importsimplejsonasjson
else:
importjson
ignore_dirs=[".svn","CVS"]
ignore_files=[re.compile(".*~")]
MANIFEST_FILENAME="manifest.json"
classExtensionDir:
def__init__(self,path):
self._root=os.path.abspath(path)
self._dirs=[]
self._files=[]
forroot,dirs,filesinos.walk(path,topdown=True):
fordirinignore_dirs:
ifdirindirs:
dirs.remove(dir)
root=os.path.abspath(root)
fordirindirs:
self._dirs.append(os.path.join(root,dir))
forfinfiles:
formatchinignore_files:
ifnotmatch.match(f):
self._files.append(os.path.join(root,f))
defvalidate(self):
ifos.path.join(self._root,MANIFEST_FILENAME)notinself._files:
logging.error("packageismissingavalid%sfile"%MANIFEST_FILENAME)
returnFalse
returnTrue
defwriteToPackage(self,path):
ifnotself.validate():
returnFalse
try:
f=open(os.path.join(self._root,MANIFEST_FILENAME))
manifest=json.load(f)
f.close()
zip_path=path+".zip"
ifos.path.exists(zip_path):
os.remove(zip_path)
zip=zipfile.ZipFile(zip_path,"w")
(root,dir)=os.path.split(self._root)
root_len=len(self._root)
forfileinself._files:
arcname=file[root_len+1:]
logging.debug("%s:%s"%(arcname,file))
zip.write(file,arcname)
zip.close()
zip=open(zip_path,mode="rb")
hash=hashlib.sha256()
whileTrue:
buf=zip.read(32*1024)
ifnotlen(buf):
break
hash.update(buf)
zip.close()
manifest["zip_hash"]=hash.hexdigest()
#Thisisabitodd-we'reactuallyappendinganewzipfiletotheend
#ofthemanifest.Believeitornot,thisisactuallyanexplicit
#featureofthezipformat,andmanyziputilities(thislibrary
#andthreeothersItried)canstillreadtheunderlyingzipfile.
ifos.path.exists(path):
os.remove(path)
out=open(path,"wb")
out.write("Cr24")#Extensionfilemagicnumber
#Therestoftheheaderiscurrentlymadeupofthreeints:
#version,headersize,manifestsize
header=array.array("l")
header.append(1)#version
header.append(16)#headersize
manifest_json=json.dumps(manifest);
header.append(len(manifest_json))#manifestsize
header.tofile(out)
out.write(manifest_json);
zip=open(zip_path,"rb")
whileTrue:
buf=zip.read(32*1024)
ifnotlen(buf):
break
out.write(buf)
zip.close()
out.close()
os.remove(zip_path)
logging.info("createdextensionpackage%s"%path)
exceptIOError,(errno,strerror):
logging.error("errorcreatingextension%s(%d,%s)"%(path,errno,
strerror))
try:
ifos.path.exists(path):
os.remove(path)
except:
pass
returnFalse
returnTrue
classExtensionPackage:
def__init__(self,path):
zip=zipfile.ZipFile(path)
error=zip.testzip()
iferror:
logging.error("errorreadingextension:%s",error)
return
logging.info("%scontents:"%path)
files=zip.namelist()
forfinfiles:
logging.info(f)
defRun():
logging.basicConfig(level=logging.INFO,format="[%(levelname)s]%(message)s")
parser=optparse.OptionParser("usage:%prog--indir=<dir>--outfile=<file>")
parser.add_option("","--indir",
help="aninputdirectorywheretheextensionlives")
parser.add_option("","--outfile",
help="extensionpackagefilenametocreate")
(options,args)=parser.parse_args()
ifnotoptions.indir:
parser.error("missingrequiredoption--indir")
ifnotoptions.outfile:
parser.error("missingrequiredoption--outfile")
ext=ExtensionDir(options.indir)
ext.writeToPackage(options.outfile)
pkg=ExtensionPackage(options.outfile)
return0
if__name__=="__main__":
retcode=Run()
sys.exit(retcode)
这个脚本运行方式如下所示:
这将会产生一个.crx文件,然后将其拖拽进Chrome即可实现扩展的安装
参考资料
本文介绍如何在Google Chrome浏览器上创建并安装第一个扩展程序。从创建文件夹到编写基本的HTML和JavaScript代码,再到最终的打包发布,一步步引导读者了解整个过程。
1940

被折叠的 条评论
为什么被折叠?



