奔跑中的奶酪

Firefox 火狐不完全开发手册

Firefox 火狐不完全开发手册

开发流程

国内关于 Firefox 开发的教程少之又少,要么全是英文的,要么太过官方,要么过于老旧,要么过于零散,所以我整理了一份详实接地气的 Firefox 开发手册,包括了开发案例,源代码和源文件,还包括了火狐相关的优秀网站和开发者,欢迎补充还没添加的内容。本手册希望可以给喜欢 Firefox 的人一些参考, Firefox 有你的加入会变得更好。

随着新版 Firefox 启用了全新的框架,Firefox 的很多功能受到了限制,然而尽管如此,Firefox 还是有着非常大的自定义空间,随着更多 API 的加入, Firefox 会在速度能比肩 Chrome 的情况下,功能也会更加强大,Firefox 会变得更加 Firefox。

1、要不要用 Firefox 开发者版本?
可以用,也可以不用。开发者版的好处在于它支持直接双开Firefox,并可直接安装未签名拓展和修改的拓展。

2、将官方安装版 Firefox 便捷化
利用 adonais 开发的工具 libportable 将 Firefox 便携化,可以避开配置文件之间的干扰。

3、如何双开 Firefox ?
常规方法:新建一个快捷方式,然后在”目标“一栏,空一格再加上 “-no-remote -p” (不包括分号)就会调出用户配置的对话框,你可以创建和删除用户配置。如果在 “-no-remote -p” 后,再空一格加上“用户配置名称”,就可以跳过选择用户配置的对话框,直接一键双开Firefox了。

快捷方法:我写了一个DOS批处理文件,让上述过程一键启用,点击下载
简单方法:使用拓展 Open With 来调用多个浏览器,使用方法 点这里

4、使用 Firefox 自带开发者工具
按F12弹出Dev Tools,点击“齿轮”图标,在“高级设置”里勾选“启用浏览器界面和附加组件调试工具箱”和“启用远程调试器”,然后在菜单栏里的 "工具" 中“Web开发者”选择“浏览器工具箱”。

三道杠——web开发者——查看器(Ctrl+Shift+C 或 F12)
三道杠——web开发者——浏览器工具箱(Ctrl+Shift+Alt+I)(在RC Firefox V10中可以直接按 Shift+F1 调出)

5、如何安装未签名拓展?
使用 Firefox 开发者版本可以直接安装,如果使用的是正式版的话,打开 about:debugging 也可以临时安装本地扩展,但如果想要永久安装的话,

1),用压缩软件解压 .xpi 文件,找到文件 manifest.json,将其中的 ID 修改为其他值,接着重新打包为 .zip 文件,
2),打开 Firefox 开发者中心 ,登录帐号,在提交上传附加组件时,选择“我自己托管”。
3),这时可能还会提示一些附加组件验证错误信息,点击查看“完整验证报告”,接着修正提示的严重错误。
4),修改后,重新打包,重新上传,后续可能会出现“您可能需要提交源代码”的问题,选择“不提交”。
5),完成!

6、如何关闭 Firefox 自动更新?
在 firefox.exe 所在目录,新建一个名为 distribution 的文件夹,里面创建一个 policies.json 文件,内容:

{
"policies": {
"DisableAppUpdate": true
}
}

7、如何分享自己的配置?
不正确的配置分享可能会导致个人私密的泄露,在分享你的配置前,你需要:

1),按快捷键 Shift + Ctrl + Del,删除全部浏览记录,一些拓展的网页,可以不删除它的网站设置和Cookies,不然会恢复默认。
2),注销已登录的Firefox帐号,包括 Firefox Account,Lastpass,Pocket等所有登录的同步帐号。Lastpass 还需要清除本地缓存,点击 “更多选项-->高级-->清除本地缓存”。
3),打开“选项-->隐私与安全”,点击 “已经已保存的登录信息”,如果有,则要删除。
4),删除配置文件夹下的:

places.sqlite 书签和历史,
urlclassifier3.sqlite 钓鱼网站库,
cookies.sqlite 已登录网站的cookie,
bookmarkbackups 自动备份的书签,
OfflineCache 脱机缓存,
startupCache 启动缓存,
signons.sqlite 保存的密码,
key3.db 密码数据库,
permissions.sqlite 网站设置,
webappsstore.sqlite 保存的会话。

5),根据自己配置的实际情况,其他包含个人隐私的文件和文件夹也要删除,之后就可以打包压缩上传分享了,推荐使用7Zip,压缩效率更高。

常用工具

Firefox开发者版 和正式版区别不大,但无需命名可以直接双开Firefox
Line Icons V系列Firefox所用到的线性图标及源文件
Notepad2 编码工具,还有同类软件Notepad++,Sublime Text 3
Beyond Compare 文件对比工具
libportable 让官方安装版Firefox变成便携版
DB Browser for Sqlite Sqlite 查看编辑器
Regester 正则表达测试工具

常用代码

Firefox Quantum 由于 API 的变化,许多脚本代码都失效了,奶酪重新修复并整理了一份兼容 Firefox Quantum (Firefox 67+) 的列表清单。测试方法是使用快捷键 Shift + F4,在弹出的代码草稿纸窗口中将选项“环境”更改为“浏览器”,再将代码粘贴到上面,点击“执行—>运行”即可(Ctrl + R)。

一、导航命令:

// 1,后退
document.getElementById("Browser:Back").doCommand();
或者 getWebNavigation().canGoBack && getWebNavigation().goBack();
// 2,前进
document.getElementById("Browser:Forward").doCommand();
或者 getWebNavigation().canGoForward && getWebNavigation().goForward();
// 3,刷新当前页面
document.getElementById("Browser:Reload").doCommand();
// 4,跳过缓存刷新当前页面
document.getElementById("Browser:ReloadSkipCache").doCommand();
// 5,刷新所有页面
gBrowser.reloadAllTabs();
// 6,主页
BrowserHome(); 或者 document.getElementById("Browser:Home").doCommand();
// 7,停止载入当前页面
document.getElementById("Browser:Stop").doCommand();
// 8,添加书签
document.getElementById("Browser:AddBookmarkAs").doCommand();
// 9,打开文件
document.getElementById("Browser:OpenFile").doCommand();
// 10,保存文件
document.getElementById("Browser:SavePage").doCommand();
// 11,打印预览
document.getElementById("cmd_printPreview").doCommand();
// 12,打印
document.getElementById("cmd_print").doCommand();
// 13,显示/隐藏书签工具栏
var bar = document.getElementById("PersonalToolbar"); setToolbarVisibility(bar, bar.collapsed);
// 14,显示/隐藏菜单栏
document.getElementById("toolbar-menubar").setAttribute("autohide", document.getElementById("toolbar-menubar").getAttribute("autohide") == "true" ? "false" : "true");
// 15,显示/隐藏导航栏
var toolbar = document.getElementById("nav-bar"); toolbar.collapsed = !toolbar.collapsed; document.persist(toolbar.id, "collapsed");
// 16,显示/隐藏查找栏
if ("isFindBarVisible" in gFindBar) gFindBar.isFindBarVisible() ? gFindBar.closeFindBar() : gFindBar.onFindCmd(); else gFindBar.hidden ? gFindBar.onFindCommand() : gFindBar.close();
或者 gFindBar.hidden ? gFindBar.onFindCommand() : gFindBar.close();
// 17,清除搜索栏内容
document.getElementById("searchbar").value = "";
// 18,重启浏览器
Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
// 19,关闭浏览器
goQuitApplication();
// 20,打开书签管理
document.getElementById("Browser:ShowAllBookmarks").doCommand();
// 21,打开Cookies管理
window.open("chrome://browser/content/preferences/siteDataSettings.xul ", "Browser:Cookies", "chrome,resizable=yes");
// 22,打开密码管理
window.open("chrome://passwordmgr/content/passwordManager.xul", "Toolkit:PasswordManager", "chrome,resizable=yes");
// 23,打开证书管理
window.open("chrome://pippki/content/certManager.xul", "mozilla:certmanager", "chrome,resizable=yes,all,width=600,height=400");
// 24,打开下载窗口
BrowserDownloadsUI();
// 25,打开我的足迹窗口
PlacesCommandHook.showPlacesOrganizer('History');

二、窗口命令:

// 1,新建窗口
document.getElementById("cmd_newNavigator").doCommand();
或者 OpenBrowserWindow();
// 2,关闭窗口
document.getElementById("cmd_closeWindow").doCommand();
// 3,窗口最小化
window.minimize(); 或者 minimize();
// 4,窗口常规化和最大化间切换
window.windowState == window.STATE_MAXIMIZED ? window.restore() : window.maximize();
// 5,窗口全屏
document.getElementById("View:FullScreen").doCommand();
// 6,在小窗口打开指定页面
格式是:toOpenWindowByType('标题', '地址);,比如 打开about:config 页面,
toOpenWindowByType('about:config', 'about:config');
如果要指定窗口大小,
window.open("about:config", "about:config", "chrome,resizable=yes,centerscreen").resizeTo(800, 600);
// 7,窗口占用屏幕左半部分
resizeTo(screen.availWidth / 2, screen.availHeight, moveTo(0, 0));
// 8,窗口占用屏幕右半部分
resizeTo(screen.availWidth / 2, screen.availHeight, moveTo(screen.availWidth / 2, 0));
// 9,显示所有标签页缩略图
allTabs.open(); // 可能失效

三、标签命令:

// 1,新建标签
document.getElementById("cmd_newNavigatorTab").doCommand();
或者 BrowserOpenTab();
// 2,关闭标签
document.getElementById("cmd_close").doCommand();
或者 gBrowser.removeCurrentTab();
// 3,恢复最后一次关闭的标签
document.getElementById("History:UndoCloseTab").doCommand();
// 4,将标签移动到左边
var tab = gBrowser.selectedTab; var pos = Math.max(0, tab._tPos - 1); gBrowser.moveTabTo(tab, pos);
// 5,将标签移动到右边
var tab = gBrowser.selectedTab; var pos = Math.max(0, tab._tPos + 1); gBrowser.moveTabTo(tab, pos);
// 6,激活上一个标签页
gBrowser.tabContainer.advanceSelectedTab(-1, true);
// 7,激活下一个标签页
gBrowser.tabContainer.advanceSelectedTab(1, true);
// 8,激话第一个标签页
gBrowser.selectedTab = gBrowser.tabContainer.firstChild;
// 9,激话最后一个标签页
gBrowser.selectedTab = gBrowser.tabContainer.childNodes[gBrowser.tabContainer.childNodes.length-1];
// 10,复制当前标签页
duplicateTabIn(gBrowser.selectedTab, 'tab');
// 11,关闭左边标签页
var tab = gBrowser.selectedTab.boxObject.previousSibling; if(tab) gBrowser.removeTab(tab);
// 12,关闭右边标签页
var tab = gBrowser.selectedTab.boxObject.nextSibling;if(tab) gBrowser.removeTab(tab);
// 13,关闭左侧标签页
for (let i = gBrowser.selectedTab._tPos - 1; i >= 0; i--) if (!gBrowser.tabs[i].pinned){ gBrowser.removeTab(gBrowser.tabs[i], {animate: true});}
// 14,关闭右侧标签页
gBrowser.removeTabsToTheEndFrom(gBrowser.selectedTab);
// 15,关闭其他标签页
gBrowser.removeAllTabsBut(gBrowser.selectedTab);
// 16,关闭所有标签页
gBrowser.removeAllTabsBut(gBrowser.selectedTab); gBrowser.removeCurrentTab();
// 17,在当前标签页右边新建标签页:
var x = gBrowser.selectedTab._tPos + 1; gBrowser.moveTabTo(gBrowser.selectedTab =gBrowser.addTab("https://www.baidu.com", {triggeringPrincipal: gBrowser.contentPrincipal}), x)
// 18,关闭重复标签页
var num = gBrowser.browsers.length;
var msg = "";
for (var i = 0; i < num; i++) { var a = gBrowser.getBrowserAtIndex(i); try { for (var j = 0; j < num; j++) { if (j != i) { var b = gBrowser.getBrowserAtIndex(j); if (a.currentURI.spec == b.currentURI.spec) { if (msg != "") msg += "\n"; msg += b.currentURI.spec; gBrowser.removeTab(gBrowser.tabContainer.childNodes[j]); num--; j-- } } } } catch (e) { Components.utils.reportError(e) } } if (msg != "") {} else alert("\u6CA1\u6709\u91CD\u590D\u6807\u7B7E\u9875");

四、页面命令:

// 1,向上滚动一屏
goDoCommand("cmd_scrollPageUp");
// 2,向下滚动一屏
goDoCommand("cmd_scrollPageDown");
// 3,向右滚动一屏
goDoCommand('cmd_scrollRight');
// 4,向左滚动一屏
goDoCommand('cmd_scrollLeft');
// 5,滚动至页首
goDoCommand("cmd_scrollTop");
// 6,滚动至页尾
goDoCommand("cmd_scrollBottom");
// 7,查看页面源代码
document.getElementById("View:PageSource").doCommand();
// 8,查看页面信息
document.getElementById("View:PageInfo").doCommand();
或者 BrowserPageInfo();
// 9,进入阅读模式
var url = "about:reader?url=" + gBrowser.currentURI.spec; gBrowser.addTab(url, {triggeringPrincipal: gBrowser.contentPrincipal});
// 10,关闭当前标签声音
gBrowser.selectedTab.toggleMuteAudio();

五、工具栏命令:

// 1,打开下载界面
document.getElementById("Tools:Downloads").doCommand();
// 2,打开附加组件
document.getElementById("Tools:Addons").doCommand();
或者 BrowserOpenAddonsMgr();
// 3,删除历史记录
document.getElementById("Tools:Sanitize").doCommand();
// 4,打开设置
openPreferences();

六、侧边栏命令:

// 1,侧边栏打开书签栏
SidebarUI.toggle("viewBookmarksSidebar");
// 2,侧边栏打开历史记录
SidebarUI.toggle("viewHistorySidebar");
// 3,关闭侧边栏
var sidebarBox = document.getElementById("sidebar-box"); if (!sidebarBox.hidden) toggleSidebar(sidebarBox.getAttribute("sidebarcommand")); //可能失效
// 4,侧边栏打开当前网页
安装拓展 Sidebar View,然后调用代码:
document.getElementById("side-view_mozilla_org-menuitem-_open-link-in-sidebar").click();

七、地址栏命令:

// 1,在当前标签打开网页
gBrowser.loadURI("https://www.baidu.com", {triggeringPrincipal: gBrowser.contentPrincipal});
// 2,在新标签打开网页 (后台)
gBrowser.addTab("https://www.baidu.com",{triggeringPrincipal: gBrowser.contentPrincipal});
// 3,在新标签打开网页 (前台)
gBrowser.selectedTab = gBrowser.addTab("https://www.baidu.com",{triggeringPrincipal: gBrowser.contentPrincipal});
// 4,在当前标签右侧打开网页
var x = gBrowser.selectedTab._tPos + 1; gBrowser.moveTabTo(gBrowser.selectedTab =gBrowser.addTab("https://www.baidu.com",{triggeringPrincipal: gBrowser.contentPrincipal}), x);
// 5,复制当前标签页标题
var gClipboardHelper = Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper); gClipboardHelper.copyString(gBrowser.contentTitle);
// 6,复制当前标签页地址
var gClipboardHelper = Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper); gClipboardHelper.copyString(gBrowser.currentURI.spec);
// 7,复制当前标签页标题和地址
(function(){var gClipboardHelper=Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper); var txt="";var url=gBrowser.currentURI.spec;var title=gBrowser.contentTitle;txt+=title+"\n"+url+"\n";gClipboardHelper.copyString(txt)})();
// 8,复制当前标签页源代码
(function(){var gClipboardHelper = Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper); var txt="";var url=gBrowser.currentURI.spec;var title=gBrowser.contentTitle;txt+=""+title+""+"\r";gClipboardHelper.copyString(txt);})();
// 9,复制当前标签页MD源代码
(function(){var gClipboardHelper = Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper); var txt="";var url=gBrowser.currentURI.spec;var title=gBrowser.contentTitle;txt+="["+title+"]"+"("+url+")";gClipboardHelper.copyString(txt);})();
// 10,复制所有标签页标题
var gClipboardHelper = Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper); var titles="";Array.slice(gBrowser.tabContainer.childNodes).forEach(function(tab){titles+=tab.label+"\n"});gClipboardHelper.copyString(titles);
// 11,复制所有标签页地址
var gClipboardHelper = Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper); var URLs="";Array.slice(gBrowser.tabContainer.childNodes).forEach(function(tab){var url=gBrowser.getBrowserForTab(tab).currentURI.spec;URLs+=url+"\n"});gClipboardHelper.copyString(URLs);
// 12,复制所有标签页标题和地址
var gClipboardHelper = Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper); var txt="";Array.slice(gBrowser.tabContainer.childNodes).forEach(function(tab){var url=gBrowser.getBrowserForTab(tab).currentURI.spec;txt+=tab.label+"\n"+url+"\n"});gClipboardHelper.copyString(txt);
// 13,复制所有标签页源代码
(function(){var gClipboardHelper=Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper);var txt="";Array.slice(gBrowser.tabContainer.childNodes).forEach(function(tab){var url=gBrowser.getBrowserForTab(tab).currentURI.spec;txt+=""+tab.label+""+"
"+"\r"});gClipboardHelper.copyString(txt)})();
// 14,复制所有标签页MD源代码
(function(){var gClipboardHelper=Components.classes['@mozilla.org/widget/clipboardhelper;1'].getService(Components.interfaces.nsIClipboardHelper);var txt="";Array.slice(gBrowser.tabContainer.childNodes).forEach(function(tab){var url=gBrowser.getBrowserForTab(tab).currentURI.spec;txt+="["+tab.label+"]"+"("+url+")\\"+"\r"});gClipboardHelper.copyString(txt)})();
// 15,打开剪切板内容
(function(){let url=readFromClipboard();try{switchToTabHavingURI(url,true)}catch(ex){var reg=/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/;if(!reg.test(url)){url='https://www.baidu.com/s?wd='+encodeURIComponent(url)}else{if(url.substring(4,0).toLowerCase()=="http"){url=encodeURIComponent(url)}else{url='http://'+encodeURIComponent(url)}}switchToTabHavingURI(url,true)}e.preventDefault();e.stopPropagation()});
// 16,一键打开常用标签组
var newtabs=["https://weibo.com/","https://www.inoreader.com/","https://www.twitter.com/","https://www.runningcheese.com/"];var i=0;while(i<=newtabs.length-1){gBrowser.selectedTab=gBrowser.addTrustedTab(newtabs[i]);i=i+1;};

八、其他命令:

// 1,模拟按钮点击
比如,模拟点击三道杠按钮,双引号之间的ID内容需要在当前界面可见。(包括下拉选项)
document.getElementById("PanelUI-menu-button").click();
或者 document.getElementById("PanelUI-menu-button").doCommand();
// 2,模拟键盘点击
比如,模拟点击回车键,DOM_VK_RETURN 代表 回车键,更多虚拟键码可参考 这里
window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).sendKeyEvent('keypress', KeyEvent.DOM_VK_RETURN, 0, 0); //可能失效
// 3,运行小书签命令
小书签的优点在于全平台兼容,各大浏览器都能运行,命令也非常多,可参考《中文网最全小书签合集》。比如,开启夜晚模式:
gBrowser.loadURI("javascript:(function(){var%20night=function(w){(function(d){var%20css='html{opacity:0.9!important;background:black!important;}body{background:white!important;}';var%20s=d.getElementsByTagName('style');for(var%20i=0,si;si=s[i];i++){if(si.innerHTML==css){si.parentNode.removeChild(si);return}};var%20heads=d.getElementsByTagName('head');if(heads.length){var%20node=d.createElement('style');node.type='text/css';node.appendChild(d.createTextNode(css));heads[0].appendChild(node)}})(w.document);%20for(var%20i=0,f;f=w.frames[i];i++){try{arguments.callee(f)}catch(e){}}};night(window)})();", {triggeringPrincipal: gBrowser.contentPrincipal});
// 4,运行相对路径文件 (以打开配置文件夹下的 user.js 为例)
FileUtils.getFile('ProfD',['user.js']).launch();
再比如打开脚本文件夹下的某个文件,代码是:(来自 File I/O
FileUtils.getFile('UChrm',['Local', 'Colors','Colors.exe']).launch();
// 5,运行绝对路径文件 (以打开IE为例)
var path="C:\\Program Files\\Internet Explorer\\iexplore.exe"; var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile); file.initWithPath(path); file.launch();
// 6,使用其他浏览器打开当前页面 (以IE浏览器为例)
var path='C:\\Program Files\\Internet Explorer\\iexplore.exe';var file=Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsIFile);file.initWithPath(path);var process=Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);process.init(file);process.run(false,[gBrowser.currentURI.spec],1);
// 7,运行系统文件 (以打开资源管理器为例)
var path ="..\\..\\explorer.exe"; var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);file.initWithPath(path.replace(/^\./, Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("SysD", Components.interfaces.nsIFile).path));file.launch();
// 8,设置指定的整数值 (以设置链接以什么样的方式打开为例)
Services.prefs.setIntPref("browser.link.open_newwindow",3);
// 9,设置指定的字符串 (以设置默认主题为例)
// 字符串通常内容比较复杂,为避免不必要的错误,可以加上双引号。
Services.prefs.setCharPref("lightweightThemes.selectedThemeID","firefox-compact-light@mozilla.org");
// 10,设置指定的布尔值 (以设置侧边栏是否靠左为例)
Services.prefs.setBoolPref("sidebar.position_start",true);
// 11,布尔值切换 (以设置侧边栏靠左还是靠右为例)
var key = "sidebar.position_start"; Services.prefs.setBoolPref(key, ! Services.prefs.getBoolPref(key));
或者 Services.prefs.setBoolPref("sidebar.position_start", ! Services.prefs.getBoolPref("sidebar.position_start"));
如果在切换布尔值的时候,同时显示提醒的话
var key="sidebar.position_start";Services.prefs.setBoolPref(key,!Services.prefs.getBoolPref(key));if(getBoolPref(key)==true){alert('左侧打开侧边栏')}else{alert('右侧打开侧边栏')}
如果想让提醒显示在状态栏的话
var key="sidebar.position_start";Services.prefs.setBoolPref(key,!Services.prefs.getBoolPref(key));if(getBoolPref(key)==true){XULBrowserWindow.statusTextField.label="左侧打开侧边栏"}else{XULBrowserWindow.statusTextField.label="右侧打开侧边栏"}
// 12,根据键值来做 if 判断 (以侧边栏靠左时窗口常规化为例)
if (Services.prefs.getPrefType("sidebar.position_start") === true) {window.restore();} else {window.maximize();}
如果是多重判断的话用 &&,比如
(Services.prefs.getPrefType("general.useragent.override") == 0 && Services.prefs.getPrefType("general.platform.override") == 0) {window.restore();} else {window.maximize();}
// 13,重置指定键值 (以重置侧边栏停靠位置为例)
Services.prefs.clearUserPref("sidebar.position_start")
// 14,命令切换启用 (以显示或者隐藏查找栏为例)
gFindBar.open() || gFindBar.close();

注意事项:
(1). 以上代码如果太长不便于理解,可以借助 JS代码美化 工具来展开代码。
(2). 当引用的代码段有双引号时,使用 function() { 引用的代码 }; 来转义,有多重双引号时,外面一层用单引号。
(3). 当代码较长遇到隔断时,可以借助 JS代码净化 工具来压缩代码。
(4). 如果还是有隔断,可以使用 URL编码工具
(5). 你还可以通过使用”开发者工具箱“来查找更多命令,或者访问 MDN 开发者中心。

参数设置

Firefox 可以通过修改参数来修改设置,方法是在地址栏打开 about:config 来手动修改。你在浏览器上做的选项修改,Firefox 会将记录保存到文件 pref.js 中去。而且,你还可以将一些常用的设置写入到文件 user.js 中去,这样即使遇到配置出了问题, 将 prefs.js 文件删除, 重启 Firefox 后一切都又回到熟悉的样子。 在 user.js 中参数有两种写法, 一种是pref,一种是user_pref:

pref(key,value) 会覆盖默认设置,在删除之后会恢复默认设置。
user_pref(key,value)等同于从about:config修改,删除之后,修改的设置仍然有效,需要再次修改。

Firefox 火狐不完全开发手册

about:config 可以对 Firefox 的界面进行修改(参考本文“用户样式”篇),也可以对 Firefox 的功能进行修改,下面这些常见的选项是你应该知道的:

1,控制Firefox内存使用

// 关闭标签动画:
toolkit.cosmeticAnimations.enabled 设置为 false。(老机器可以设置为false,高配电脑无需设置)
// 设置标签页面缓存的数量:
browser.sessionhistory.max_total_viewers 设置为 8。电脑内存小于4GB的,可以设置为4,默认为-1,意为无限大。
// 设置标签前进/后退历史记录缓存:
browser.sessionhistory.max_entries 设置为 25。默认为50。
// 最小化时释放物理内存:
config.trim_on_minimize,设置为 true。这个值不存在,需要手动建立新的布尔值。

2,设置标签打开方式

// 设置链接是否在新窗口中打开:
browser.link.open_newwindow 设置为 3。
默认为3,3表示在新标签页中打开,2表示在新窗口中打开,1表示在当前窗口或者标签页中打开。
// 设置通过 JavaScript 打开的链接是否与上面的方式保持一致:
browser.link.open_newwindow.restriction 设置为0。
默认为0,0表示保持一致,1表示在新窗口中打开,2表示依据 JavaScript 的具体设置。

3,更多选项设置
Firefox 有非常多的 about:config 高级设置,目前已知对 about:config 参数进行解释的地方有:About:config entries火狐参数目录Ghack user.js。其中 Ghack user.js 最为详细具体,告诉你各个版本有什么变化、新增和删除,更新也非常及时,还提供了一些很实用的脚本操作命令(预览),https://ffprofile.com 是一个引导式的 user.js 生成器,还有一份奶酪在用的 user.js 供你参考。

用户代理

User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。

一些网站常常通过判断 UA 来给不同的操作系统、不同的浏览器发送不同的页面,因此可能造成某些页面无法在某个浏览器中正常显示,但通过伪装 UA 可以绕过检测。比如一些网站只支持Chrome,而不支持Firefox,比如斗鱼在Chrome上可以启用HTML5播放器,这时可以通过修改UA的方法解决。

一、用 About:config 修改

新建字符串 general.useragent.override,输入
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36
则会修改整个浏览器的 UA。

新建字符串 general.useragent.override.douyu.com,输入
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36
则会单单修改访问 douyu.com 时的浏览器 UA,修改其他的网站和UA,方法相同。

虎牙要使用HTML5播放器,需要额外将 javascript.options.streams 和 dom.streams.enabled 设置为 ture。

二、用拓展修改

当然,上面这些步骤都一些麻烦,我们可以利用拓展 Header Editor 来快速修改。还是以将国内常见直播平台伪装成Chrome浏览器HTML5播放器为例:
Firefox 火狐不完全开发手册

注意事项:
(1). 红色圈为必填内容,可能需要一些正则表达式的知识,但你可以按^https?://www\.douyu\.com.* 依葫芦画瓢,修改网址就可以了,多个正则之间用“|”隔开(不包括分号)表示并列。

(2). 支持列表订阅:
常用图片反盗链和反跳转 by dupontjoy
常用重定向和用户代理 by runningcheese

(3). 常见UA列表:

// 1,iPad:
Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25
// 2,iPhone:
Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16
// 3,Opera:
Opera/9.80 (Windows NT 6.1; U) Presto/2.6.30 Version/10.60
// 4,Safari:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:48.0) Gecko/20100101 Firefox/48.0
// 5,Chrome:
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36
// 6,Android:
Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17
// 7,Wechat:
Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; NX510J Build/LMY47V) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025489 Mobile Safari/533.1 V1_AND_SQ_6.2.3_336_YYB_D QQ/6.2.3.2700 NetType/WIFI WebP/0.3.0 Pixel/1080
// 8,Google爬虫:
Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
// 9,Firefox 52:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
// 10,Firefox 57:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0

(4). 当前浏览器UA查询工具:UA分析,还可以用 小书签 来查询,所有浏览器UA查询:List of User Agent Strings

用户规则

一个网页里有百度联盟的广告,我们可以通过用 hosts 的方法将百度联盟的广告指向 127.0.0.1,这样百度联盟的广告就屏蔽了。然而,这个网页同时又加入了谷歌Ads的广告,过加入了淘宝联盟的广告,这时用户规则就诞生了。

1,广告过滤规则
拓展推荐: uBlock Origin,AdBlock Plus 或者 YiClear,省事可以用 YiClear
EasyList:广告过滤必须订阅的主规则。
EasyList China:中文订阅规则,配合 EasyList 主规则使用。
Adblock Warning Removal List:针对于那种“警告,你正在使用Adblock”的提示,可以理解为反“反ABP”。
ABP Subscriptions :已知所有的 Adblock Plus 规则
广告净化器规则 :视频去广告

2,隐私保护规则
拓展推荐:同上
EasyPrivacy:反跟踪,隐私保护主规则。
CJX’s Annoyance List:针对中文网站的隐私保护补充规则。

3,用户代理规则
拓展推荐: Header Editor
一网站通过判断字符串头来给不同的操作系统、不同的浏览器发送不同的页面,因此可能造成某些页面无法在某个浏览器中正常显示,但通过伪装 UserAgent 用户代理来绕过检测。

Dupontjoy Redirctor:网页重定向
RunningCheese Redirtor:参考自Dupontjoy Redirctor,修改了部分重定向,无需重复订阅。
Dupontjoy Referer:反反图片盗链。
RunningCheese UserAgent:常见网站 UserAGent 修改。

4,代理规则
拓展推荐: Proxy SwitchyOmega
用户代理是指用户身份的代理(UserAgnet),代理是指代理服务器(Proxy Server),就国内而言,无非就是那个“List”。

5,其他规则
还有一些其他类型的规则,比如通过规则批量定义网页的样式,但是样式管理器也有同样的功能,而且更加方便好用,所以这种规则不常用。还有自动翻页的规则,看个人的使用情况是否添加,还有一些是白名单规则,比如 NoScript 的白名单。

通常情况下,订阅规则就可以满足绝大部分的情况,也可以根据自己的使用情况添加一些自定义规则。需要注意的是,应该要避免添加太多的规则列表,这会减慢浏览器的处理速度,进而影响浏览体验。

附加组件

(Firefox有什么可以折腾的?)

1、拓展 Extensions

拓展是一种具有一些新功能的加载项,在 Firefox拓展中心 上有着丰富的优秀拓展,相信Firefox拓展强大的功能会让你再也离不开Firefox,你可以根据个人需求来安装适合个人需求的拓展。

2、插件 Plugins

初学者最容易把拓展和插件混淆了,通俗的讲,扩展是基于Firefox本身增加的一些实用功能,而插件则是在Firefox之外独立编写的程序,用于显示网页中的特定内容,比如Flash,上传插件,网银插件和Java等。

3、用户样式 Userstyles

我们可以利用它来定制目标网页或网站的css样式,甚至一些Firefox 拓展的样式,让浏览效果更加舒适。而且在 UserStyles 网站上已经有不少现成的样式可供下载,让不会写css的普通用户也可以享受到它的便利。

4、用户脚本 Userscripts

能通过脚本来改变被访问网页,能使你访问的网站更便于阅读或者更便于使用。在 GreasyFork 上有许多用户分享的用户脚本,打开脚本的安装页面,点击 “Install” 按钮就可以完成安装了。

5、UC脚本 UserchromeJS

区别于用户脚本,UC脚本可以针对于火狐浏览器进行定制来实现效果,而用户脚本的功能只能针对网页页面,UC脚本可以代替某些用户脚本和某些拓展,而UC脚本的优势在于它是轻量级的。在 Github 上有许多开发者发布的UC脚本。

PS: 看了上面这些术语名词,你可能还会想另外一个词 (附加组件Addons),它并不特指某一个东西,而是以上术语名词的统称。

拓展资源

Mozilla MDN Mozilla 开发者网络
MDN Addons 开始编写你的第一个浏览器扩展
Mozilla Knowledge Base Mozilla 知识库
MozillaWiki Mozilla 产品开发指南
Mozilla Central Source Mozilla 源码索引
Bugzilla Main Page 火狐 Bug 反馈中心
Demos MDN MDN 开发网络技术演示
About:config entries about:config 说明
火狐参数目录 about:config 说明中文版
Ca-archive 传统拓展档案,下载已经被AMO移除了的传统拓展
Are We XBL Still? 新版Firefox API变化
火狐中文教程 非常详细,by @江3
Firefox Webext List 非常详细,WE拓展替代传统拓展进度表
DXR 源代码库
MozillaWiki Mozilla 项目Wiki文档
Web 技术文档 Firefox 开发所需语言技术
正则表达式 正则表达式入门教程
拓展推荐 奶酪2019年度最喜欢拓展

如何将 Chrome 拓展移植到 Firefox 上使用?

Firefox 支持 WebExtension API,它们大多数情况下与 Google Chrome 和 Opera 支持的扩展 API 兼容,因此使您的扩展在 Firefox 中运行只需很少的更改。如果一款拓展只有 Chrome 版,而没有 Firefox 版,那么我们可以尝试将其移植到 Firefox 浏览器上来。

1,我们可以使用 Moziila 官方提供的拓展兼容性测试网站 https://www.extensiontest.com,将后缀名为 .crx 的 Chrome 拓展上传检测。

2,将 .crx 的文件解压,然后重新压缩为 .xpi,接着上传至 附加组件开发者中心,同时选择“我自己托管”。

用户样式

Firefox 除了自带的“定制”功能外,你还可以通过强大的 userChrome.css 来自定义浏览器外观,Firefox 有着强大的自定义能力,这是其他任一一款浏览器都做不到的。

一、什么是 userChormeCSS

什么是 userChorme.css?

要理解它,首先要知道 Chrome 是什么意思,Chrome 是金属铬的意思,但在浏览器中指的是浏览器的框架,所以在 Firefox 的目录文件夹下会有 "chrome" 文件夹,谷歌的 Chrome 浏览器的命名就很讨巧,有点“面包牌面包”的意思。

这里我们延伸拓展一下,Firefox 默认有四个支持自定义功能的文件,它们都位于配置文件夹下的 “chrome” 文件夹里,总的说来就是:Chrome 代表浏览器界面,Content 代表网页内容,分别是:

userChrome.css -浏览器界面的样式表 (无管理拓展)
userContent.css -网页的样式表 (管理拓展:比如 xStyle)
userChrome.js -浏览器界面的脚本 (无管理拓展)
userContent.js -网页的脚本 (管理拓展:比如 ViolentMonkey)



比如,通过 userChrome.css 修改浏览器界面字体的大小:
window { font-size: 5mm !important; font-family: helvetica !important;}

比如,通过 userContent.css 修改网页字体的大小:
html>body { font-size: 100% !important; line-height: normal !important;}

二、如何编写用户样式

userChrome.css 位于浏览器配置文件夹下的“chrome”文件夹下,如果没有,你则需要手动新建。每次启动 Firefox,Firefox 都会加载这个样式表应用到全局浏览器中去,Firefox 57+ 版本以后,无法通过拓展直接修改,只能在 userChrome.css 上修改。如果CSS代码过长,可以使用 @import url("xxxx.css"); 来导入。需要注意的几个方面:

(1). 当你的 CSS 代码只做用于浏览器界面时,可以在代码放到下面的规则里,以避免与网页的样式表冲突。
@-moz-document url(chrome://browser/content/browser.xul) {/* 你的CSS代码 */}

(2). 需要在CSS样式表前声明 /* AGENT_SHEET */ 吗?
一般来说,userChrome.css 会覆盖Firefox的内置的样式表,特别是你使用了 !important 声明代码,但是还是有一些本地匿名元素,比如滚动栏,会不起作用,这时你就需要在样式表前加入 /* AGENT_SHEET */

(3). 在 userChrome.css 的同一文件夹内还会有一个叫 userContent.css 的文件,这个是将样式应用到网页上的,但使用 xStyle 等样式管理拓展更加方便,所以这个文件不常用。但是对于一些 Firefox 浏览器的内建页,比如 about:addons, about:preferences, about:newtab,样式管理拓展是不起作用的,这时就要用到 userContent.css 了,比如:
@-moz-document url(about:preferences),url-prefix(about:preferences) {/* 你的CSS代码 */}

(4). 如何即见即所得的编辑CSS样式表,避免每次修改后都要重启,就像旧版 Stylish 那样?
使用浏览器自带的“开发者工具”可以做到即见即所到,点击“保存”按钮可以将当前修改直接保存到样式表中去。
DOM

(5). 启用开发者工具需要按F12在设置中勾选两个选项,查找浏览器元素时,使用"DOM"更加方便准确,DOM标签默认并未勾选,查找弹出式菜单需要点击“弹窗自动隐藏”选项,更多使用方法可以参考 MDN
DOM

(6). 最常用的选择器 ID, class, name,他们之间的区别就是ID是你的身份证号码,class是你的姓别和民族,name就是你的名字,如果使用label选择器的话,需要用中括号括起来,像[label="XXXX"]这样。

(7). 要想知道当前选中的选择器是不是你想要的,可以给它定义一下属性,比如 color:#0063dc !important; 或者 display:none !important; 这样就很明显了,加 !important 是为了让这个属性值具有优先权。

(8). 在修改其他人的CSS样式表时,要想快速地知道某个属性具体是那条代码影响的,可以在100行代码中选择第50-100行,删除应用后,看看效果还在不在,如果还在,那么继续删除第25-50行的代码,直到效果消失后就可以缩小查找范围了。

(9). CSS编辑工具可以选项V系列Firefox自带的 Notepad2,也可以使用 Notepad++,还可以使用更加美观的 Atom。

(10). 一些选择符 是Firefox 特有的,只在Firefox上有效。比如以-moz-开头的,比如以两个横线"--sidebar-hover-width"开头的,详细列表查看:https://developer.mozilla.org/en-US/docs/Web/CSS/Mozilla_Extensions

三、案例:如何修改按钮图标?

以修改拓展 In My Pocket 图标为例,使用“开发者工具箱”选择 Pocket 图标,得到其ID为“_cd7e22de-2e34-40f0-aeff-cec824cbccac_-browser-action”,那CSS写法就是:

#_cd7e22de-2e34-40f0-aeff-cec824cbccac_-browser-action {
list-style-image: url("../images/pocket.png") !important;
}

双引号中间的指定图像可以是像上面代码所示的图片相对路径地址,也可以是以http://开头的绝对路径地址,也可以是以 data:image/png;base64 开头的图片base64编码。

四、通过“定制”和"about:config"来修改浏览器界面

Firefox 上的一些界面改变是可以通过“定制”和"about:config"来修改的,比如下载按钮是否自动隐藏,标签栏上方是否有拖拽空间,这里有一份中文解释说明可供参考:

1,通过“定制”

// 1,工具栏模式:
定制模式 > 密度 > (紧凑 / 普通 / 触控)
// 2,标签栏上方拖拽空间:
定制模式 > 拖拽空间 > 勾选选择
// 3,下载按钮一直可见:
定制模式 > 下载按钮 > 点击按钮取消勾选“自动隐藏”
// 4,RSS 图标放入地址栏:
可以安装拓展 Awesome RSS

2,通过”about:config“
地址栏输入 about:config,搜索相应的参数修改,布尔值为是和否,整数值为数值,字符串为字母和数字。右键点击选择“重置”可以恢复到默认数值。

// 1,标签栏最小宽度:(建议为100)
browser.tabs.tabMinWidth
//2,是否在标签上显示音频播放按钮:(建议选是)
browser.tabs.showAudioPlayingIcon
// 3,在当前标签右边插入相关标签:(建议选是)
browser.tabs.insertRelatedAfterCurrent
// 4,是否隐藏地址栏前的 http:// 标识:(建议选否)
browser.urlbar.trimURLs
// 5,新标签打开限制: (建议为0,用新标签来代替新窗口)
browser.link.open_newwindow.restriction
// 6,是否使用 Tabs 键来预览标签:(建议选否)
browser.ctrlTab.previews
// 7,关闭最后一个标签时关闭浏览器:(建议选否)
browser.tabs.closeWindowWithLastTab
// 8,使用旧版拨号页和主页界面:(建议选否)
browser.newtabpage.activity-stream.enabled
browser.newtabpage.activity-stream.aboutHome.enabled
// 9,HTML5 全屏警告:(修改时间,-1为不显示)
full-screen-api.warning.delay
full-screen-api.warning.timeout
// 10,书签栏显示最近添加的书签:(建议选否)
browser.bookmarks.showRecentlyBookmarked
// 11,是否显示标签动画:(建议选否)
toolkit.cosmeticAnimations.enabled
// 12,HTML5 全屏淡进和淡出动画时间:(修改时间,-1为不显示)
full-screen-api.transition-duration.enter
full-screen-api.transition-duration.leave
// 13,是否在附加组件页面移除“获取拓展”选项:(建议选否)
extensions.getAddons.showPane
// 14,搜索栏结果动画变暗高亮:(建议选否)
findbar.modalHighlight
// 15,是否在地址栏底部添加搜索引擎切换的按钮:(建议选否)
browser.urlbar.oneOffSearches
// 16,是否启用阅读模式按钮:
reader.parse-on-load.enabled
// 17,是否启用地理位置定位:(根据个人情况选择)
geo.enabled
// 18,是否启用Pocket按钮:(建议选否,功能很弱)
extensions.pocket.enabled
// 19,是否启用截图按钮:(建议选是,不错,支持永久图床)
extensions.screenshots.disabled
// 20,是否启用容器标签页:(建议选是,不错,也就是小号功能)
privacy.userContext.enabled
// 21,是否启用物联网扩展:(建议选否)
dom.flyweb.enabled
// 22,字体渲染:(默认即可,如果要使用MacType,要修改为 direct2d1.1,cairo,skia)
gfx.canvas.azure.backends
gfx.content.azure.backends

五、用户样式资源列表

开发资源

UC脚本

新架构的 Firefox Quantum 最大的变化就是抛弃了原有的XUL语言界面,这使得以 .uc.xul 为后缀名的UC脚本完全失效,同时因为一些API的变化,也使得一部分以 .uc.js 为后缀名的UC脚失效。但总的来说,Firefox 官方对UC脚本的态度是开放的,UC脚本依然大有可为,因为UC脚本真的实在太好用了。

1. UC脚本到底是什么东西?
UC脚本的全称是 userchrome.js,从本质上来说,它和一般的 javascript 脚本一样,都是js语言,只不过它引用了 Firefox 专有的库,只能在 Firefox 上运行。

2. 让 Firefox Quantum 支持 UC脚本
使用的是 Endor8 的方案,通过配置脚本来完成userChrome的配置,共计4个文件。
..\Firefox\defaults\pref\config-prefs.js
..\Firefox\defaults\pref\channel-prefs.js
..\Firefox\config.js
..\Firefox\userChromeJS.js

3. 有哪些保持着更新的UC脚本开发者?
alice0775/userChrome.js
Endor8/userChrome.js
ardiman/userChrome.js
userChrome.js用スクリプト
harv/userChromeJS
scdhao/userChrome
胖子阿康/userChrome
RunningCheese/userChrome.js

一些已经停止更新的UC脚本开发者名单就没有列出来了,同样十分感谢脚本原开发者。
可能用得上的参考资料:ywzhaiqi/userChromeJSdefpt/userChromeJs
更多UC脚本,可搜索 Search · userChrome

官方网站

桌面版下载:Firefox 官方FTP下载Firefox 国际多语言下载火狐中文(谋智)版Firefox 每夜体验版
移动版下载:Firefox iOS版Firefox 安卓版附加组件下载:Firefox Addons

Mozilla Firefox Firefox 官方网站
火狐浏览器 Firefox 中文官方网站
The Mozilla Blog Mozilla 官方博客
Mozilla Blog Directory Mozilla 博客目录
Mozilla Add-ons Blog Mozilla 附加组件博客
Mozilla Future Releases Mozilla 发展方向博客
Mozilla Security Blog Mozilla 安全博客
Open Policy & Advocacy Mozilla 隐私保护博客
Mozilla Hacks Web开发技巧与资讯
Mozilla Community Mozilla 社区
Planet Mozilla Mozilla 社区人员博客汇总

新闻资讯

Firefox News Firefox 新闻 (英文)
Firefox News Firefox 新闻 (中文)
Firefox Facebook Firefox Facebook 社交网络
Firefox Twitter Firefox Twitter 社交网络
火狐的微博 Firefox 微博社交网络
Firefox Release Notes Mozilla 更新日志
Ghacks Firefox Firefox 资讯技巧
Solidot Firefox Solidot Firefox资讯
Solidot Mozilla Solidot Mozilla资讯
Techdows Firefox Techdows Firefox资讯
浏览器国内市场份额 StatCounter Global Stats 浏览器全球市场份额
Firefox 信仰充值中心 Firefox 知乎专栏

论坛社区

Mozilla Discourse Mozilla官方交流论坛
MozillaZine Forums 全球最大用户交流论坛
谋智火狐社区 火狐中国(谋智)官方论坛
Stackoverflow Firefox 英文问答
Reddit Firefox 英文版Firefox贴吧
Mozilla Firefox中文社区 最忠实
Mozilla Mozest 最可惜
卡饭论坛Firefox版 最技术
Firefox贴吧 最活跃
Mozilla 台灣社群 宝岛朋友
知乎 Firefox话题 知乎 Firefox话题
简书 Firefox专题 简书 Firefox专题
V2EX Firefox V2EX Firefox话题
Camp Firefox 德国 Firefox 论坛
Mozilla Support Moziila 技术支持论坛
Pale Moon forum Pale Moon forum

博客项目

个人博客:
Mike's Musings Mozilla元老级员工博客
iceweasel 编译版Firefox
奔跑中的奶酪 定制版
Kaiyuan Liu GM脚本
CingFox 定制版
阳光盒子 定制版
火狐范 资讯
反斗软件 资讯
wiki@nothing UC脚本(日文)




注:本文由 奔跑中的奶酪 作者:奔跑中的奶酪 发表,其版权均为作者所有,如需转载,请注明作者名字以及文章来源。
122
avataravatar

评论:

22 条评论,访客:21 条,站长:0 条
  1. 燧火孤眠
    燧火孤眠发布于: 

    现在pref(key,value)是不是不起作用了?我看 Ghack user.js里边没有pref(key,value)的示例了?

  2. Electronics
    Electronics发布于: 

    What you said made a bunch of sense.

发表评论