都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

BHO ( Browser Helper Object ) で 自動的に ID, PASSWORD 入力してみた

 『 Google Chrome Frame をチェックしていたら、BHO ( Browser Helper Object ) が気になってきた 』 ので、C++、ATL を使って実装してみた で強制的に私のブログに遷移してしまうというサンプルを作成しました。そのサンプルをベースに BHO で HTML の要素にアクセスしてみたいと思います。

 今回コードは、https://www.hatena.ne.jp/login に遷移すると、ID, PASSWORD を入力するものです。まず、はてなログイン画面の HTML の要素を見てみましょう。F12 開発者ツールを使って調べてみましょう。 ログインページの要素が下図のように参照できます。

f:id:koogucc11:20140120022958p:plain

 ID, PASSWORD 部分の要素は下記の通りです。id で要素にアクセスしようかと思いましたが、PASSWORD の要素には id が付与されていないですね。なので、name 属性でアクセスすることにしましょう。

<table class="config">
  <tr>
    <th class="row">Hatena ID <br><span style="font-weight:normal">or</span> Email address</th>
    <td><input value="" name="name" autofocus="autofocus" pattern=".{3,}" required="required" type="text" class="text" id="login-name"></td>
  </tr>
  <tr>
    <th class="row">Password</th>
    <td><input required="required" value="" name="password" class="password" type="password"></td>
  </tr>
</table>

 下記のコードで ページロード後に、ID, PASSWORD をセットすることができます。ただし、下記のコードはエラー処理を一切入れていないので、みなさんはぜひ要素存在チェックなど、きちんとエラー処理を入れてくださいね。

void STDMETHODCALLTYPE CNativeBhoSample::OnDocumentComplete(IDispatch* pDisp, VARIANT *pvarURL)
{
	if (_tcsstr(pvarURL->bstrVal, _T("https://www.hatena.ne.jp/login")))
	{
		CComPtr<IWebBrowser2> spWebBrowser;
		CComPtr<IDispatch> spDisp;
		CComPtr<IDispatch> spPassDisp;
		CComPtr<IHTMLDocument3> spHtmlDoc3;
		CComPtr<IHTMLElement> spHtmlElem;
		CComPtr<IHTMLInputElement> spHtmlInput;
		CComPtr<IHTMLElementCollection> spHtmlElements;

		CComBSTR bstrTemp;
		// WebBrowser のポインタ取得
		pDisp->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&spWebBrowser));
		spWebBrowser->get_Document(&spDisp);
		// HTMLDocuemt の取得
		spDisp->QueryInterface(IID_IHTMLDocument3, reinterpret_cast<void**>(&spHtmlDoc3));
		// id = login-name の要素を取得
		spHtmlDoc3->getElementById(_T("login-name"), &spHtmlElem);
		spHtmlElem->QueryInterface(IID_IHTMLInputElement, reinterpret_cast<void**>(&spHtmlInput));
		// ID の設定
		spHtmlInput->put_value(_T("xxxxxxxx"));
		
		spHtmlInput.Release();		
		spHtmlElem.Release();
		
		// パスワードには、id 属性が付与されていない
		spHtmlDoc3->getElementsByName(_T("password"), &spHtmlElements);

                // passbox は一つしかないので....
		VARIANT index;
		VariantInit(&index);
		index.vt = VT_I4;
		index.lVal = 0;
		
		// パスワードの要素を取得
		spHtmlElements->item(index, index, &spPassDisp);
		spPassDisp->QueryInterface(IID_IHTMLInputElement, reinterpret_cast<void**>(&spHtmlInput));
		// パスワードの設定
		spHtmlInput->put_value(_T("xxxxxxxx"));
		
		spHtmlInput.Release();
		spPassDisp.Release();
		spHtmlElem.Release();

		spHtmlDoc3.Release();
		
		spDisp.Release();
		bstrTemp.Empty();

		spWebBrowser.Release();	
	}
}

 ページロード後、DocumentComplete イベントが実行され、ID および PASSWORD がセットされました。

f:id:koogucc11:20140120100700p:plain

 HTML へのアクセスは非常に簡単ですね。BHO 関連はあと何をしましょうか?

Pro Internet Explorer 8 & 9 Development: Developing Powerful Applications for The Next Generation of IE
 

 ※これほしいなぁ。10 or 11 版とかでないのかな?