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": "My First Extension",
- "description": "The first extension that I made."
- }
其中各个参数含义如下:
format_version(必需的):向Chrome指明扩展所使用的清单格式版本。目前只有一个格式版本,因此设为1.
id(必需的):扩展的ID号(唯一的)。目前可以设为任何40个十进制数字,将来会改为扩展的公钥的SHA-1的哈希值。
version(必需的):扩展的版本号。可以使用任意点分格式的数字串
name(必需的):扩展的名称。
description(可选的):扩展的描述信息
2)在目录下加入一个hello_world.html文件,在其中加入
- Hello, World!
3)为了让Chrome支持扩展,右键桌面上Chrome的快捷键,选择“属性”,在“目标”这一栏中空一格后,加入
- --enable-extensions --load-extension="c:\myextension"
4)启动Chrome,输入下列URL:
- chrome-extension://00123456789ABCDEF0123456789ABCDEF0123456/hello_world.html
如图所示:
5)输入下列URL:
- chrome-ui://extensions/
将会列出所有已经安装的扩展,同时还会显示扩展系统启动时发生的错误信息。
6)内容脚本。它是由Chrome加载进来在web页面上运行的JavaScript文件。这和firefox扩展类似。要加入一个内容脚本,首先在清单文件中对其进行注册,如下所示:
- {
- "format_version": 1,
- "id": "00123456789ABCDEF0123456789ABCDEF0123456",
- "version": "1.0",
- "name": "My First Extension",
- "description": "The first extension that I made.",
- "content_scripts": [
- {
- "matches": ["http://www.google.com/*"],
- "js": ["foo.js"]
- }
- ]
- }
然后创建一个脚本文件foo.js,其中代码如下:
- document.images[0].src = "http://bit.ly/1293Af";
- 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": "My First Extension",
- "description": "The first extension that I made.",
- "plugins_dir": "plugins"
- }
8)打包发布。要对扩展进行打包发布前,首先确认你安装了Python2.6,然后使用下述脚本文件chromium_extension.py
- #!/usr/bin/python
- # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- # chromium_extension.py
- import array
- import hashlib
- import logging
- import optparse
- import os
- import re
- import shutil
- import sys
- import zipfile
- if sys.version_info < (2, 6):
- import simplejson as json
- else:
- import json
- ignore_dirs = [".svn", "CVS"]
- ignore_files = [re.compile(".*~")]
- MANIFEST_FILENAME = "manifest.json"
- class ExtensionDir:
- def __init__(self, path):
- self._root = os.path.abspath(path)
- self._dirs = []
- self._files = []
- for root, dirs, files in os.walk(path, topdown=True):
- for dir in ignore_dirs:
- if dir in dirs:
- dirs.remove(dir)
- root = os.path.abspath(root)
- for dir in dirs:
- self._dirs.append(os.path.join(root, dir))
- for f in files:
- for match in ignore_files:
- if not match.match(f):
- self._files.append(os.path.join(root, f))
- def validate(self):
- if os.path.join(self._root, MANIFEST_FILENAME) not in self._files:
- logging.error("package is missing a valid %s file" % MANIFEST_FILENAME)
- return False
- return True
- def writeToPackage(self, path):
- if not self.validate():
- return False
- try:
- f = open(os.path.join(self._root, MANIFEST_FILENAME))
- manifest = json.load(f)
- f.close()
- zip_path = path + ".zip"
- if os.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)
- for file in self._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()
- while True:
- buf = zip.read(32 * 1024)
- if not len(buf):
- break
- hash.update(buf)
- zip.close()
- manifest["zip_hash"] = hash.hexdigest()
- # This is a bit odd - we're actually appending a new zip file to the end
- # of the manifest. Believe it or not, this is actually an explicit
- # feature of the zip format, and many zip utilities (this library
- # and three others I tried) can still read the underlying zip file.
- if os.path.exists(path):
- os.remove(path)
- out = open(path, "wb")
- out.write("Cr24") # Extension file magic number
- # The rest of the header is currently made up of three ints:
- # version, header size, manifest size
- header = array.array("l")
- header.append(1) # version
- header.append(16) # header size
- manifest_json = json.dumps(manifest);
- header.append(len(manifest_json)) # manifest size
- header.tofile(out)
- out.write(manifest_json);
- zip = open(zip_path, "rb")
- while True:
- buf = zip.read(32 * 1024)
- if not len(buf):
- break
- out.write(buf)
- zip.close()
- out.close()
- os.remove(zip_path)
- logging.info("created extension package %s" % path)
- except IOError, (errno, strerror):
- logging.error("error creating extension %s (%d, %s)" % (path, errno,
- strerror))
- try:
- if os.path.exists(path):
- os.remove(path)
- except:
- pass
- return False
- return True
- class ExtensionPackage:
- def __init__(self, path):
- zip = zipfile.ZipFile(path)
- error = zip.testzip()
- if error:
- logging.error("error reading extension: %s", error)
- return
- logging.info("%s contents:" % path)
- files = zip.namelist()
- for f in files:
- logging.info(f)
- def Run():
- logging.basicConfig(level=logging.INFO, format="[%(levelname)s] %(message)s")
- parser = optparse.OptionParser("usage: %prog --indir=<dir> --outfile=<file>")
- parser.add_option("", "--indir",
- help="an input directory where the extension lives")
- parser.add_option("", "--outfile",
- help="extension package filename to create")
- (options, args) = parser.parse_args()
- if not options.indir:
- parser.error("missing required option --indir")
- if not options.outfile:
- parser.error("missing required option --outfile")
- ext = ExtensionDir(options.indir)
- ext.writeToPackage(options.outfile)
- pkg = ExtensionPackage(options.outfile)
- return 0
- if __name__ == "__main__":
- retcode = Run()
- sys.exit(retcode)
这个脚本运行方式如下所示:
- chromium_extension.py --indir="c:\myextension" --outfile="myextension.crx"
这将会产生一个.crx文件,然后将其拖拽进Chrome即可实现扩展的安装
参考资料
1,Chrome Extension HOWTO
2,First Google Chrome Extensions