ラベル Firefox の投稿を表示しています。 すべての投稿を表示
ラベル Firefox の投稿を表示しています。 すべての投稿を表示

2025年4月18日金曜日

firefox で userChrome.css を使う方法

firefox で userChrome.css を使う方法

概要

最新バージョンではデフォルト無効ですが有効にすることで使えます
今回はブックマークバーの間隔を調整する方法を紹介します

環境

  • Firefox Developer Edition 138.0b8

userChrome.css の有効化

  • about:config をアドレスバーに入力
  • toolkit.legacyUserProfileCustomizations.stylesheets の設定を検索
  • true に設定

userChrome.css の作成

プロファイル配下に chrome ディレクトリを作成しそこに userChrome.css を作成します

  • mkdir "/Users/username/Library/Application Support/Firefox/Profiles/uxiqfej5.dev-edition-default-1744936099514/chrome"
  • vim "/Users/username/Library/Application Support/Firefox/Profiles/uxiqfej5.dev-edition-default-1744936099514/chrome/userChrome.css"
/* ブックマークバーのアイコン間隔を狭くする */
toolbarbutton.bookmark-item {
  padding: 0px 4px !important; /* 左右のパディングを少なくする(デフォルトは6px前後) */
  margin: 0 !important;
}

プロファイルのパスは about:support からでも確認できます

Firefox の再起動

設定を反映させます

動作確認

ブックマークバーの間隔が狭くなっていることを確認します

最後に

有効にすれば userChrome.css はまだ使えるようです

2023年5月30日火曜日

emacsでFirefoxの拡張を開発する際にコード補完を設定する方法

emacsでFirefoxの拡張を開発する際にコード補完を設定する方法

概要

前回 emacs で Firefox 拡張を開発する環境を構築し lint やインデントの設定などを行いました

今回はコード補完を行う方法を紹介します

環境

  • macOS 11.7.6
  • emacs 28.2
  • nodejs 19.7.0
    • tern

tern のインストール

  • npm install -g tern

.tern.conf の作成

  • vim ~/.tern-config
{
  "libs": [
    "browser",
    "jquery",
    "ecma5",
    "underscore"
  ],
  "plugins": {
    "angular": {},
    "commonjs":{},
    "node":{},
    "requirejs":{},
    "node_resolve":{}
  }
}

tern-mode のインストール

  • M-x package-list-packages

tern-mode と tern-auto-complete をインストール

emacs の設定

前回の設定 (mode の起動や lint の設定) も記載しています
tern はどうやら company には対応しなくなったようで auto-complete 用の拡張があるのでそれを使うように変更しています

; for firefox extension (via js2-mode)
(require 'tern)
(require 'js2-mode)
(require 'flycheck)

# .js ファイルで js2-mode 起動
(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
# js2-mode 起動時に auto-complete-mode 起動
(add-hook 'js2-mode-hook 'auto-complete-mode)
# インデントはスペース2つにする
(add-hook 'js2-mode-hook
  (lambda ()
     (setq my-js-mode-indent-num 2)
     (setq js2-basic-offset my-js-mode-indent-num)
     (setq js-switch-indent-offset my-js-mode-indent-num)
    ))
# js2-mode のデフォルトの linter は無効にする
(setq js2-mode-show-strict-warnings nil)
# js2-mode 起動時に flycheck-mode 起動
(add-hook 'js2-mode-hook #'flycheck-mode)
# flycheck の linter は eslint にする
(setq flycheck-javascript-eslint-executable "eslint")
(with-eval-after-load 'flycheck
  (flycheck-add-mode 'javascript-eslint 'js2-mode))

# js2-mode 起動時に tern-mode 起動
(add-hook 'js2-mode-hook
  (lambda ()
    (tern-mode t)))
# tern-auto-complete を使って連携 
(eval-after-load 'tern
  '(progn
    (require 'tern-auto-complete)
    (tern-ac-setup)))
# 補完用のキーバインドを設定
(define-key tern-mode-keymap (kbd "M-.") 'tern-find-definition)
(define-key tern-mode-keymap (kbd "M-,") 'tern-pop-find-definition)

最後に

js2-mode + flycheck (eslint) + tern-mode はおそらく JavaScript 単体の開発であれば Firefox 以外の環境でも使えると思います

emacsでFirefoxの拡張を開発する環境を構築する

emacsでFirefoxの拡張を開発する環境を構築する

概要

emacs で Firefox 拡張を開発する環境を構築してみます

環境

  • macOS 11.7.6
  • emacs 28.2
  • nodejs 19.7.0
    • eslint 8.41.0

eslint のインストール

  • npm -g install eslint

firefox 拡張のプロジェクト配下で eslint 用の設定ファイルを記載します

  • npm init @eslint/config
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JavaScript
A config file was generated, but the config file itself may not follow your linting rules.
Successfully created .eslintrc.js file in 
  • cat .eslintrc.js
module.exports = {
  "env": {
    "webextensions": true,
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": "eslint:recommended",
  "overrides": [
  ],
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "rules": {
  }
}

js2-mode, company, flycheck のインストール

  • M-x package-list-packages

で js2-mode, company, flycheck を選択しインストールします

emacs の設定

(require 'company)
(require 'js2-mode)
(require 'flycheck)

# .js ファイルで js2-mode 起動
(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
# js2-mode 起動時に company-mode 起動
(add-hook 'js2-mode-hook 'company-mode)
# インデントはスペース2つにする
(add-hook 'js2-mode-hook
  (lambda ()
     (setq my-js-mode-indent-num 2)
     (setq js2-basic-offset my-js-mode-indent-num)
     (setq js-switch-indent-offset my-js-mode-indent-num)
    ))
# js2-mode のデフォルトの linter は無効にする
(setq js2-mode-show-strict-warnings nil)
# js2-mode 起動時に flycheck-mode 起動
(add-hook 'js2-mode-hook #'flycheck-mode)
# flycheck の linter は eslint にする
(setq flycheck-javascript-eslint-executable "eslint")
(with-eval-after-load 'flycheck
  (flycheck-add-mode 'javascript-eslint 'js2-mode))

課題

  • 補完をどうするか

2021年5月23日日曜日

Selenium + Firefox でファイルをダウンロードのダウンロードはできなさそう

Selenium + Firefox でファイルをダウンロードのダウンロードはできなさそう

概要

ブラウザでダウンロードする際にダウンロードするファイルをどうするかという確認のダイアログが表示されます これを Selenium + Firefox で消そうと思ったのですがどうやってもできなかったので紹介します

環境

  • macOS 11.3.1
  • Ruby 3.0.0
    • selenium-webdriver 4.0.0.beta3
  • Firefox 88

Ruby3 を使う場合は selenium-webdriver 4 が必要になります

インストール

  • bundle init
  • vim Gemfile
gem "selenium-webdriver", "4.0.0.beta3"
  • bundle install

プロファイルを指定して Firefox を起動すれば特定のファイルのダウンロードルールを使えるのでは

既存の Firefox でダウンロードしたいファイルを一度ダウンロードします その際に指定のファイルは次回以降同じ設定でダウンロードすることができるという機能があります

この機能を使ってプロファイルを作成しそのプロファイルを selenium で指定することでプロファイル付きの Firefox を起動することができるようになります

options = Selenium::WebDriver::Firefox::Options.new(args: ['-profile', '/path/to/profile'])

@driver = Selenium::WebDriver.for :remote, url: "http://#{host}:4444/wd/hub", options: options

一応公式でも手順が公開されてはいるのですがバグの回避策として紹介されている感じです 確かにプロファイル付きで Firefox は起動できるのですがそのあと selenium に接続することができません

どうやらプロファイル付きだと geckodriver が見つからなくなってしまうようで結局動作しません

調べてみると marionette を有効にすれば動作するという記事もみたのですが自分はダメでした

プロファイルを設定すればいけるという情報がかなりあったがダメだった

例えば以下のような感じでプロファイルを設定し Firefox ドライバを作成します これで localhost でも docker 上でも試したのですが結局ダイアログが出なくなることはありませんでした

profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.folderList'] = 2
profile['browser.download.useDownloadDir'] = true
profile['browser.download.dir'] = '/tmp'
profile['browser.download.lastDir'] = '/tmp'
profile['browser.download.downloadDir'] = '/tmp'
profile['browser.download.defaultFolder'] = '/tmp'
profile['browser.download.manager.showWhenStarting'] = false
profile['browser.download.manager.useWindow'] = false
profile['browser.download.manager.focusWhenStarting'] = false
profile['browser.download.manager.showAlertOnComplete'] = false
profile['browser.download.manager.closeWhenDone'] = true
profile['browser.download.viewableInternally.enabledTypes'] = ""
profile['browser.helperApps.alwaysAsk.force'] = false
profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/plane,text/csv,application/x-ofx,text/comma-separated-values,application/octet-stream,application/vnd.ms-excel,application/x-gzip,text/txt,application/gzip,application/zip,text/html,txt,text'

options = Selenium::WebDriver::Firefox::Options.new(:profile => profile)

@driver = Selenium::WebDriver.for :remote, url: "http://#{host}:4444/wd/hub", options: options

原因を考える

もしかしたら自分の設定が足りていないだけかもしれないので少し原因を考えてみました

content-type が足りていない

browser.helperApps.neverAsk.saveToDisk にダイアログを表示しない content-tyep を記載するのですがそこにダウンロードするファイルの content-type がない可能性があります

しかし自分の場合はちゃんとブラウザなどで content-type を調べた上で記載したので漏れはないかなと思っています

handlers.json が優先されているのか

上記のプロファイルの記載よりもプロファイルフォルダ配下にある handlers.json の設定が優先されているのかもしれません むしろここに記載がないと意味がない可能性すらありそうです

なので今回プロファイル付きの Firefox を起動するようにしたのですが結局 selenium 経由では動作できませんでした 別の方法で handlers.json を上書きできればもしかしたら動作させることができるかもしれません

最後に

いろいろ試してみたのですが結局 Selenium + Firefox でダウンロードのダイアログを消すことはできませんでした

回避策としては chrome や edge ドライバを使うことかなと思います

参考サイト

2020年6月22日月曜日

Firefox WebExtension マウスのクリックイベントを特定のタグにだけ発生される方法

概要

querySelectAll を使うとページ内の特定のタグをすべて取得できます
取得したタグに対して addEventListener してあげます

環境

  • Firefox 77.0.1

サンプルコード

querySelectorAll で取得したタグは forEach で回せます
あとはそれぞれに対してイベントリスナーを追加すれば OK です

function clickedLeft(e) {
  if ('object' == typeof e){
    btnCode = e.button;
    switch (btnCode){
      case 0:
        alert('Left button clicked');
        break;
    }
  }
}

document.querySelectorAll("a").forEach(function(a) {
  a.addEventListener("mousedown", clickedLeft);
})

ちなみにどのタグでもいい場合は document.addEventListener("mousedown", func); で OK です

manifest.js

content_scripts にすることを忘れないようにしましょう

{
  "manifest_version": 2,
  "name": "test",
  "version": "1.0.0",
  "description": "test",
  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "js": ["main.js"]
    }
  ],
  "applications": {
    "gecko": {
      "id": "test@hawksnowlog.blogspot.com"
    }
  }
}

2018年10月16日火曜日

ブックマークの一覧を取得する方法

概要

Firefox の extension に bookmark の API があります
これを使えばブックマークのタイトルや URL を取得することができます
今回はブックマークツールバーにあるブックマークの一覧を取得してみました

環境

  • macOS 10.13.6
  • Firefox 62.0

manifest.json

  • vim manifest.json
{
  "manifest_version": 2,
  "name": "Test bookmarks",
  "version": "1.0",
  "description": "Fetch bookmarks info",
  "background": {
    "scripts": ["main.js"]
  },
  "permissions": [
    "bookmarks"
  ]
}

permissions.bookmarks が必要です

main.js

  • vim main.js
browser.bookmarks.getTree(function(results) {
  results[0].children.forEach(function(toolbar) {
    if (toolbar.id == "toolbar_____") {
      toolbar.children.forEach(function(bookmark) {
        console.log(bookmark.id);
        console.log(bookmark.url);
      })
    }
  });
});

browser.bookmarks.getTree でブックマーク全体の情報を取得します
次に results[0].children で直下にあるブックマークのディレクトリ情報を取得します
このディレクトリの中にある "toolbar_____" という ID を持つディレクトリがブックマークツールバーになります

この配下の toolbar.children でブックマークの一覧の配列を取得しあとは forEach で回すだけです

取得できる情報は BookmarkTreeNode のオブジェクトになります
今回は id と url の情報を表示しています

動作確認

about:debugging からデバッグ画面を表示して確認すると以下のように表示されると思います
bookmark1.png

最後に

Firefox の extension でブックマークの操作をしてみました
今回は取得しかしませんでしたがブックマークの登録や削除などもできます
提供されている API は以下の参考サイトのリンクに記載されています

参考サイト

2018年10月15日月曜日

Firefox の WebExtension で簡単なローカルストレージを使う方法

概要

Firefox の Webextension で設定内容などを保存したい場合にはブラウザのローカルストレージが使えます
特にクラウドでデータを連携する必要がない場合などは簡単かつ軽量に使えるので便利です
今回は簡単な使い方を紹介します

環境

  • macOS 10.13.6
  • Firefox 62.0

manifest.json

  • vim manifest.json
{
  "manifest_version": 2,
  "name": "Local storage demo",
  "version": "1.0",
  "description": "Store and save your data in local storage",
  "icons": {
    "48": "icons/border-48.png"
  },
  "background": {
    "scripts": ["main.js"]
  },
  "permissions": [
    "storage"
  ]
}

permissions.storage が必要になります

main.js

  • vim main.js
browser.storage.local.get("config", function(value) {
  if (value.config === undefined) {
    browser.storage.local.set({
      config: {
        count: 1
      }
    });
  } else {
    var c = value.config.count;
    c++;
    console.log(c);
    browser.storage.local.set({
      config: {
        count: c
      }
    });
  }
});

あまり良いサンプルじゃないかもしれません、、
ローカルストレージからのデータの取得は browser.storage.local.get で行います
ローカルストレージへのデータの保存は browser.storage.local.set で行います

データは JSON 形式で保存します
そして取得するときも JSON になるのでキーをドットでつないで参照します
初回はデータがなく undefined になるので、その場合は初期化する処理を書いています

今回のサンプルの場合 extension を読み込むたびにカウントアップしていくサンプルになります
about:debugging の画面でデバッグ画面を開いて何度も最読み込みするとカウントアップするのがわかると思います
普通はオプション画面などで使うと思います
ちなみにオプション画面は manifest.json に options_ui を定義することがで実現できます

"options_ui": {
  "page": "options.html"
}

この HTML 内で更に js ファイルを参照してそこで browser.storage.local.set を呼ぶ感じです
こうすることでページやタブを跨いでもデータを横断して参照することができるようになります

最後に

Firefox の Webextension でローカルストレージを使ってみました
データは extension が削除されたりユーザがブラウザのキャッシュ情報などを意図的に削除するとなくなります

用途してはテンポラリー的な感じかなと思うので重要なデータなどはクラウドストレージなどと連携すると良いと思います
storage.sync などを使えば Firefox Account 同士でデータを共有することができます
ただその場合は認証なども必要になるので少し大変な実装になるかとは思います

2018年10月11日木曜日

Firefox の Webextension で Notifications を出す方法

概要

Firefox の Webextension では新たに Notification が使えるようになりました
今回は簡単な使い方を紹介します

環境

  • macOS 10.13.6
  • Firefox 62.0

manifest.json

  • vim manifest.json
{
  "manifest_version": 2,
  "name": "Notifications sample",
  "version": "1.0",
  "description": "Display a notification when starting",
  "icons": {
    "48": "icons/border-48.png"
  },
  "background": {
    "scripts": ["main.js"]
  },
  "permissions": [
    "notifications"
  ]
}

ポイントは permissionsnotifications を追加するところです

main.js

  • vim main.js
browser.notifications.create({
  "type": "basic",
  "iconUrl": browser.extension.getURL("icons/icon-48.png"),
  "title": "Hello",
  "message": "This notification is test"
});

type は basic を使っています
他にも image や list, progress などがあります
詳細はこちらをご覧ください
iconUrl は通知時にアイコンを指定することができます
指定のアイコンがない場合はデフォルトで Firefox のアイコンが表示されます
title, message は通知に表示する文字列情報になります

今回の場合はアドオンを読み込みした時点で通知します
本来であればクリックのイベントやコールバック処理などで呼び出しましょう

動作確認

about:debugging から manifest.json を読み込みましょう
すると以下のように通知が来ると思います
notification1.png

最後に

Firefox の Webextension で Notifications 機能を使ってみました
background で動作させる場合には window.alert などが使えないので代用として Notifications は良いかもしれません
また HTML が不要なのも嬉しい点かなと思います

通知時のイベントもあり onButtonClicked, onClicked, onClosed, onShown があります (参考)

通知はウザがられがちですが使い方によっては便利なのでうまく活用してみてください

2018年10月9日火曜日

ツールバーに独自のアイコンを表示する方法

概要

ツールバーは URL バーの隣にある領域です
ここに独自にアイコンをセットすることでクリック時の処理などを extension で書くことができます
今回は設置方法とクリックイベントのハンドリングをしてみたいと覆います

環境

  • macOS 10.13.6
  • Firefox 62.0

manifest.json

  • vim manifest.json
{
  "manifest_version": 2,
  "name": "Toolbar test",
  "version": "1.0",
  "description": "Display icon on toolbar and click test.",
  "background": {
    "scripts": ["main.js"]
  },
  "browser_action": {
    "default_icon": {
      "20": "icons/icon-20.png"
    },
    "default_title": "test"
  }
}

browser_action でツールバーにアイコンを配置できます
icons/icon-20.png を適当に配置しましょう
画像がない場合は透明なアイコンが表示されます、透明なのでアイコンがあるかどうかはカーソルを合わせないとわからないので画像を準備しましょう
default_title はカーソルを合わせた際のツールチップの情報です

main.js

  • vim main.js
function onClicked() {
  console.log("clicked");
}

browser.browserAction.onClicked.addListener(onClicked);

browser.browserAction.onClicked にリスナーを追加することでクリックイベントを監視することができます

動作確認 

about:debugging にアクセスして manifest.json を読み込みましょう
アイコンが表示されたクリックすると console.log が表示されると思います
browser_action1.png

最後に

Firefox の Webextension でツールバーを操作する方法を紹介しました
コンテキストメニューの場合は右クリックが必要でしたがツールバーの場合はクリックのみなのでやることが一つ減ります

ただツールバーの場合はアイコン用の画像が必要になります
extension でやりたいことに合わせて適切な UI を選択しましょう

参考サイト

2018年9月26日水曜日

現在開いているタブの URL を取得する方法

概要

Firefox の Webextension で現在開いているタブの URL 情報を取得する方法を紹介します

環境

  • macOS 10.13.6
  • Firefox 62.0

manifest.json

  • vim manifest.json
{
  "manifest_version": 2,
  "name": "Tab URL",
  "version": "1.0",
  "description": "Fetching active tab's url",
  "icons": {
    "48": "icons/border-48.png"
  },
  "background": {
    "scripts": ["main.js"]
  },
  "permissions": [
    "tabs"
  ]
}

タブの操作をするので permissionstags を追加します

main.js

  • vim main.js
function getCurrentWindowTabs() {
  return browser.tabs.query({currentWindow: true, active: true});
}

getCurrentWindowTabs().then(tabs => {
  console.log(tabs[0].url);
});

browser.tabs.query でタブを取得します
タブは配列で取得できるので、それの一番始めを参照するとアクティブなタブを取得することができます
あとはタブの url プロパティを参照すれば URL 情報が取得できます

今回のサンプルの場合は extension が読み込まれたときに動作するので about:debugging の URL しか取得できないと思います

クリックイベントなどと合わせてクリック時に取得するようにすれば別ページなどでも動作させることができます

最後に

Firefox の Webextension でアクティブなタブの URL を取得する方法を紹介しました
タブが配列で取得できるので、そこから必要なタブだけを取得するのがポイントになると思います

参考サイト

2018年9月25日火曜日

マウスで選択した部分の文字列を取得する方法

概要

Firefox の Webextension でマウスで選択した部分の文字列の情報を取得する方法を紹介します
基本は選択 -> 右クリックの流れなのでコンテキストメニューから取得するのが早いです

環境

  • macOS 10.13.6
  • Firefox 62.0

manifest.json

  • vim manifest.json
{
  "manifest_version": 2,
  "name": "Selected text",
  "version": "1.0",
  "description": "Show selected text in console.log",
  "icons": {
    "48": "icons/border-48.png"
  },
  "background": {
    "scripts": ["main.js"]
  },
  "permissions": [
    "menus"
  ]
}

コンテキストメニューを使うので permissionsmenus を追加します

main.js

  • vim main.js
browser.menus.create({
  id: "select-text",
  title: "Show select text",
  contexts: ["all"]
});

browser.menus.onClicked.addListener((info, tab) => {
  switch (info.menuItemId) {
    case "select-text":
      if (info.selectionText !== undefined) {
        console.log(info.selectionText);
      }
      break;
  }
});

info.selectionText これで取得できます
info は OnClickData のオブジェクトです
selectionText 以外にも様々なプロパティがあります

動作確認

about:debugging から extension をインストールして動作確認してみましょう
文字列を選択してコンテキストメニューから追加した項目をクリックすると文字列が console.log で表示されると思います

cosole.log で表示するだけなのでデバッグからコンソール画面を表示しておいてください

おまけ (アンカーテキストの URL を取得する)

info から linkUrl を参照するだけで OK です

if (info.linkUrl !== undefined) {
  url = info.linkUrl;
}

最後に

Firefox の Webextension でマウスで選択した部分の文字列を取得してみました
コンテキストメニューのクリックイベントを拾うと簡単に取得できます

むしろそれ以外で取得する方法がわかりませんでした
ユースケースを考えるとそれ以外で必要な場面は少ないので API 的にもそうしているのかもしれません

参考サイト

2018年9月24日月曜日

コンテキストメニュー (右クリックのメニュー) に項目を追加する方法

概要

Firefox の Webextension でコンテキストメニューに独自のメニューを追加する方法を紹介します

環境

  • macOS 10.13.6
  • Firefox 62.0

manifest.json

  • vim manifest.json
{
  "manifest_version": 2,
  "name": "Context menu extension",
  "version": "1.0",
  "description": "Add original item into context menu",
  "icons": {
    "48": "icons/border-48.png"
  },
  "background": {
    "scripts": ["main.js"]
  },
  "permissions": [
    "menus"
  ]
}

context_scripts ではなく background で動作させる必要があります
また permissions に「menus」を追加する必要があります

main.js

  • vim main.js
function onCreated() {
  if (browser.runtime.lastError) {
    console.log(`Error: ${browser.runtime.lastError}`);
  } else {
    console.log("Item created successfully");
  }
}

browser.menus.create({
  id: "my-context-menu",
  title: "Hello!",
  contexts: ["all"]
}, onCreated);

browser.menus.onClicked.addListener((info, tab) => {
  switch (info.menuItemId) {
    case "my-context-menu":
      console.log("clicked");
      break;
  }
});

まず browser.menus.create でコンテキストメニューに項目を追加します
引数に id, title, contexts を指定します
id はクリックしたときの識別子として使うので好きな文字列を設定してください
title はコンテキストメニューに表示される項目名を指定します
contexts は項目を表示するのをどんなときにするか設定することができます
all にしておけばどんなときのコンテキストメニューでも追加した項目が表示されます
指定可能なタイプはこちらに記載されています

最後に項目がメニューに追加された際のコールバック用のメソッドを設定します
今回は onCreated メソッドをコールバックメソッドとして設定しています
このコールバックメソッドは項目が追加されたかどうかチェックするためのメソッドになります

実際に項目がクリックされたときの挙動を実装するには browser.menus.onClicked.addListener を設定します
onClicked というイベントにリスナーを設定します
リスナー内で info.menuItemId を取得し先程設定した id だった場合にどういう挙動をするか実装することができます

とりあえず今回は console.log しかしていませんがここで DOM の操作や XMLHttpRequest などを使ったりします
ちなみに console.log は background モードでないと表示することができないので注意してください

動作確認

about:debugging を開いて extension をインストールしましょう
すると右クリックのメニューに新しく項目が追加されていることが確認できると思います
context_menu2.png

今回はアイコンを配置していないので左にアイコンが表示されていません
またクリックするとデバッグ画面にしっかりとログが表示されているのも確認できると思います
context_menu1.png

キーボードショートカットを割り当てるには

コンテキストメニューが表示されたときに特定のキーボードを押すと項目をクリックしないでも実行することができる機能があります

WebExtension の場合には API として明示的に提供されていません
しかし項目のタイトルの先頭に割り当てたい文字を設定すると同じようなことができるようになります
例えば今回の場合であれば以下のように定義すれば「H」キーで実行することができます

browser.menus.create({
  id: "my-context-menu",
  title: "H) Hello!",
  contexts: ["all"]
}, onCreated);

最後に

Firefox の Webextension でコンテキストメニューに新たに項目を追加する方法を紹介しました
コンテキストメニューであればすべて Javascript だけでできます
またここから新たに UI (ウィンドウなど) を表示する場合には HTML の追加が必要になります

参考サイト

2018年9月21日金曜日

Firefox の Webextension を開発してみよう

概要

昔の Firefox のアドオン開発は XUL と呼ばれる XML 形式の UI と JavaScript で開発していました
しかし Firefox Quantum が登場し XUL が廃止され Chrome の Webextension と同じく HTML + JavaScript で開発するようになりました

今回は初めて Webextension を開発するチュートリアルを紹介します

環境

  • macOS 10.13.6
  • Firefox 62.0

ワークスペース作成

  • mkdir my_first_extension
  • cd my_first_extension

manifest.json の作成

必須のファイルになります
extension のメタデータなどを記載します

  • touch manifest.json
  • vim manifest.json
{
  "manifest_version": 2,
  "name": "My first extension",
  "version": "1.0",
  "description": "Test extension",
  "content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": ["main.js"]
    }
  ]
}

main.js の作成

manifest.json で指定したスクリプトになります
ここにブラウザの操作や DOM の操作などを記載していきます
今回は超簡単な処理として表示したページの枠を青色にする処理を記載します

  • touch main.js
  • vim main.js
document.body.style.border = "5px solid blue";

body の情報を取得して CSS を当てているだけです

動作確認

Firefox を起動して about:debugging にアクセスします
「一時的なアドオンを読み込む」を選択して manifest.js を選択しましょう
webextension1.png

これで Webextension のテストができます
適当にサイトにアクセスすると枠が青くなっているが確認できると思います
webextension2.png

Tips

アイコンを設定する場合は以下の情報を manifest.json を追記します

"icons": {
  "48": "icons/border-48.png",
  "96": "icons/border-96.png"
}

そして icons ディレクトリ配下に border-48.png などを配置すれば OK です
2 サイズ分用意しなくても良いですが用意したほうが良いです

拡張機能 ID は Webextension を公開するときには指定が必要です
manifest.json に以下を追記しましょう

"applications": {
  "gecko": {
    "id": "my-first-extension@example.com"
  }
}

メールアドレス形式で指定します
これは XUL の時代にもありました
もし XUL で開発していたアドオンの新しいバージョンとして公開する場合は XUL 時代に使っていた ID と同じ値を指定してください

今回は content_scripts で動作させましたが他に background というモードがあります
XMLHttpRequest などは background モードでしか使えません
逆にアラート表示などは content_scripts でないとできません
background の場合は変わりに notifications などを使います
という感じでやりたいことによってモードを使い分ける必要があります

最後に

Firefox の Webextension に入門してみました
HTML + Javascript で書けるようになったので導入障壁はかなり下がったかなと思います
ただ、XUL 時代に使っていた UI などはすべて HTML に書き換える必要があるのでそこは大変かもしれません

また Firefox Quantum から API もだいぶ変わっているのでその辺りも開発時には注意が必要かなと思います

参考サイト

2017年2月12日日曜日

Firefox のアドオンでビルドした xpi ファイルに内に JAR を含める必要がなくなった

概要

Firefox のアドオンのレビューでタイトルの理由でアドオンの公開がリジェクトされました
その対応方法を紹介します

環境

  • Firefox 47.0
  • Eclipse Mars
  • Spket IDE Plugin 1.0.0.787

エラー詳細

レビュアーから来たメールに記載されていたリジェクトの理由は以下の通りです

1) The add-on contains JAR file. This can result in performance issues in add-ons that target Gecko 4 and above. You should no longer use JAR files to package your chrome files. Please unpack this package to chrome directory and remove JAR file. Please see (https://developer.mozilla.org/en/Extensions/Updating_extensions_for_Firefox_4#XPI_unpacking) for more information."

対応内容

今までアドオンのソースファイルなどは JAR ファイルに圧縮して chrome フォルダ配下に配置して、その上で xpi ファイルにしていました
構造としては以下の通りです

$ tree
.
├── chrome
│   └── stu.jar
├── chrome.manifest
└── install.rdf

今まではこの構造で審査が通っていたのですが、これからは以下の通りでないと審査が通らなくなったようです

$ tree
.
├── chrome
│   ├── content
│   │   ├── about.xul
│   │   ├── pref.xul
│   │   ├── stu.js
│   │   └── stu.xul
│   ├── locale
│   │   └── en-US
│   │       └── stu.dtd
│   └── skin
│       ├── stu.css
│       ├── stu.png
│       └── stu64.png
├── chrome.manifest
└── install.rdf

要するに chrome 配下に配置していた JAR ファイルを JAR にしないでそのまま配置する必要があるということです

最後に

紹介は以上です
自分の場合は Spket IDE で開発をしており xpi ファイルを作成するために Ant を使っていました
なので、build.xml ファイルを修正することで正しい xpi ファイルを作成できるようにしました

自分の場合は結構昔からアドオンの開発を行っていたので JAR にする構成になっていたのかもしれません
もしかすると別の環境でビルドすれば全く問題ないかもしれません

参考サイト