第50回 「スクリプト実行」「ActiveX実行」「画像表示」などをON/OFFする (タブブラウザーを作る)

tabbrowser212.gif
前回はツールバーにリンククリック時に鳴る音をON/OFFするためのボタンを追加した。今回は同じように「スクリプトの実行」「画像の表示」「AvtiveXコントロールの実行」「BGMの再生」の各項目をON/OFFするため機能を実装する。

「スクリプトの実行」や「ActiveXコントロールの実行」を今回のような手法で制御することはセキュリティ上の弱点となる。セキュリティ的に少しは弱みとならないような切り替え方法を少し考えてみたのだがどうも複雑になりそう。もともとステータスバーやアドレスバーの実装方法などセキュリティ的に最悪な部分がたくさんあるので細かいことは気にせずに単純にON/OFFを切り替えるに留める。

まずツールバーに4つのボタンを追加する。スクリプト実行のON/OFF用の「ID_SCRIPT」、画像表示用の「ID_IMAGE」、ActiveXコントロール実行用の「ID_ACTIVEX」、BGM再生用の「ID_BGM」を用意した。

tabbrowser213.gif 「MainFrm.h」で用意したボタンをツールバーのUI_ELEMENTとして登録すると同時にOnIdle内でボタン状態が設定されるようにする。
	virtual BOOL OnIdle()
	{
		CTabBrowser100View*	pView;

		pView = GetActivePageView();

		//「戻る」「進む」ボタンの状態設定
		{
			bool	bBack = false;
			bool	bNext = false;

			if(pView)
				pView->IsButtonEnable(bBack,bNext);

			UIEnable(ID_IE_BACK,bBack ? TRUE : FALSE);
			UIEnable(ID_IE_NEXT,bNext ? TRUE : FALSE);
		}

		//「編集」メニュー項目更新
		{
			bool	bCopy		= false;
			bool	bCut		= false;
			bool	bPaste		= false;
			bool	bSelectAll	= false;

			if(pView)
				pView->IsEnable_EditCommand(bCopy,bCut,bPaste,bSelectAll);

			UIEnable(ID_EDIT_COPY		,bCopy ? TRUE : FALSE);
			UIEnable(ID_EDIT_CUT		,bCut ? TRUE : FALSE);
			UIEnable(ID_EDIT_PASTE		,bPaste ? TRUE : FALSE);
			UIEnable(ID_EDIT_SELECT_ALL	,bSelectAll ? TRUE : FALSE);
		}


		//未実装メニュー項目を全部無効に設定
		{
			UIEnable(ID_FILE_COPY_TAB, FALSE);
			UIEnable(ID_FILE_NEW_WINDOW, FALSE);
			UIEnable(ID_FILE_NEW_SESSION, FALSE);
			UIEnable(ID_FILE_OPEN, FALSE);
			UIEnable(ID_FILE_EDIT, FALSE);
//			UIEnable(ID_FILE_SAVE, FALSE);				//有効/無効設定必要
//			UIEnable(ID_FILE_SAVE_AS, FALSE);			//有効/無効設定必要
			UIEnable(ID_FILE_SEND_PAGE, FALSE);
			UIEnable(ID_FILE_SEND_LINK, FALSE);
//			UIEnable(ID_FILE_CREATE_SHORTCUT, FALSE);	//有効/無効設定必要
			UIEnable(ID_FILE_INPORT_EXPORT, FALSE);
//			UIEnable(ID_FILE_PROPERTY, FALSE);			//有効/無効設定必要
			UIEnable(ID_FILE_OFFLINE, FALSE);
//			UIEnable(ID_EDIT_FIND, FALSE);				//有効/無効設定必要
			UIEnable(ID_VIEW_FIXED, FALSE);
			UIEnable(ID_VIEW_QUICKTAB, FALSE);
			UIEnable(ID_VIEW_FAVORITE, FALSE);
			UIEnable(ID_VIEW_HISTORY, FALSE);
			UIEnable(ID_VIEW_FEED, FALSE);
(...省略...)
			UIEnable(ID_TOOL_DEVELOP, FALSE);
			UIEnable(ID_TOOL_INTERNET_OPTION, FALSE);
		}

		//ツールバーボタン。クリック音を鳴らす
		{
			bool	bDisable;

			bDisable = IsFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS);
			UISetCheck(ID_CLICK_SOUND,! bDisable);
		}

		//■追加
		//ダウンロードコントロール
		if(pView)
		{
			bool	bEnable;

			//何度もフラグを読み出してるので効率が悪いが気にしない
			bEnable = pView->IsEnableAmbientDownloadControl(DLCTL_DLIMAGES);
			UISetCheck(ID_IMAGE,bEnable);

			bEnable = pView->IsEnableAmbientDownloadControl(DLCTL_BGSOUNDS);
			UISetCheck(ID_BGM,bEnable);

			bEnable = pView->IsEnableAmbientDownloadControl(DLCTL_NO_SCRIPTS);
			UISetCheck(ID_SCRIPT,! bEnable);		//反転

			bEnable = pView->IsEnableAmbientDownloadControl(DLCTL_NO_RUNACTIVEXCTLS);
			UISetCheck(ID_ACTIVEX,! bEnable);		//反転
		}

		UIUpdateToolBar();
		return FALSE;
	}


	bool	IsFeatureEnabled(INTERNETFEATURELIST FeatureEntry)
	{
		HRESULT	hr;

		hr = ::CoInternetIsFeatureEnabled(FeatureEntry,SET_FEATURE_ON_PROCESS);
		if(hr == S_OK)
			return	true;
		return	false;
	}

	BEGIN_UPDATE_UI_MAP(CMainFrame)
		UPDATE_ELEMENT(ID_SCRIPT, UPDUI_TOOLBAR)		//■追加
		UPDATE_ELEMENT(ID_IMAGE, UPDUI_TOOLBAR)			//■追加
		UPDATE_ELEMENT(ID_ACTIVEX, UPDUI_TOOLBAR)		//■追加
		UPDATE_ELEMENT(ID_BGM, UPDUI_TOOLBAR)			//■追加
		UPDATE_ELEMENT(ID_CLICK_SOUND, UPDUI_TOOLBAR)
		UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_IE_BACK, UPDUI_TOOLBAR)
		UPDATE_ELEMENT(ID_IE_NEXT, UPDUI_TOOLBAR)
		UPDATE_ELEMENT(ID_EDIT_COPY, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)

tabbrowser214.gif そしてツールバーが押されたときの動作を実装する。
	BEGIN_MSG_MAP(CMainFrame)
		MESSAGE_HANDLER(WM_DNP_CREATENEWTAB, OnDnpCreateNewTab)
		MESSAGE_HANDLER(WM_DNP_CHANGEFOCUS, OnDnpChangeFocus)
		MESSAGE_HANDLER(WM_DNP_CHANGEADDRESS, OnDnpChangeAddress)
		NOTIFY_CODE_HANDLER(CBEN_ENDEDIT, OnAddressbarEnter)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
		COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
		COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
		COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
		COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
		COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose)
		COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll)
		COMMAND_ID_HANDLER(ID_FILE_PRINT, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_PRINT_PREVIEW, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_PRINT_SETUP, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_COPY, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_CUT, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_SAVE, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_SAVE_AS, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_CREATE_SHORTCUT, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_PROPERTY, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_FIND, OnFileCommand)
		COMMAND_ID_HANDLER(ID_CLICK_SOUND, OnFileCommand)
		COMMAND_ID_HANDLER(ID_IMAGE, OnFileCommand)			//■追加
		COMMAND_ID_HANDLER(ID_BGM, OnFileCommand)			//■追加
		COMMAND_ID_HANDLER(ID_SCRIPT, OnFileCommand)		//■追加
		COMMAND_ID_HANDLER(ID_ACTIVEX, OnFileCommand)		//■追加
		COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
		COMMAND_ID_HANDLER(ID_IE_BACK, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_NEXT, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_STOP, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_REFRESH, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_ADDFAVORITE, OnIEAddFavorite)
		COMMAND_ID_HANDLER(ID_IE_ORGANIZE_FAVORITE, OnIEOrganizeFavorite)
		NOTIFY_CODE_HANDLER(TBVN_CONTEXTMENU, OnTabContextMenu)
		NOTIFY_CODE_HANDLER(TBVN_PAGEACTIVATED, OnTabPageActivated)
		MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
		COMMAND_RANGE_HANDLER(ID_FAVORITE_FIRST,ID_FAVORITE_LAST,OnFavorite)
		CHAIN_MSG_MAP_MEMBER(_cFovMenu)
		CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
		CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
	END_MSG_MAP()


	LRESULT OnFileCommand(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& bHandled)
	{
		CTabBrowser100View*	pView;

		pView = GetActivePageView();
		if(pView == NULL)
		{
			bHandled = FALSE;
			return	0;
		}

		bHandled = TRUE;
		switch(wID)
		{
			//■追加
		case	ID_IMAGE:			//画像表示
		case	ID_BGM:				//BGM再生
		case	ID_SCRIPT:			//スクリプト実行
		case	ID_ACTIVEX:			//ActiveXコントロール実行
			{
				bool	bEnable;
				long	nFlag;

				nFlag = 0;
				switch(wID)
				{
				case	ID_IMAGE:		nFlag = DLCTL_DLIMAGES;					break;
				case	ID_BGM:			nFlag = DLCTL_BGSOUNDS;					break;
				case	ID_SCRIPT:		nFlag = DLCTL_NO_SCRIPTS;				break;
				case	ID_ACTIVEX:		nFlag = DLCTL_NO_RUNACTIVEXCTLS;		break;
				}

				bEnable = pView->IsEnableAmbientDownloadControl(nFlag);
				pView->SetAmbientDownloadControl(nFlag,! bEnable);
				break;
			}

		case	ID_CLICK_SOUND:				//クリック音を再生するかどうかの設定
			{
				bool	bDisable;

				bDisable = IsFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS);
				::CoInternetSetFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS,SET_FEATURE_ON_PROCESS,bDisable ? FALSE : TRUE);
			}
			break;

		case	ID_FILE_SAVE:				//上書き保存
			pView->Save();
			break;

		case	ID_FILE_SAVE_AS:			//名前を付けて保存
			pView->SaveAs();
			break;

		case	ID_FILE_CREATE_SHORTCUT:	//デスクトップにリンク作成
			pView->CreateShortcut();
			break;

		case	ID_FILE_PROPERTY:			//プロパティ
			pView->ShowProperty();
			break;

		case	ID_EDIT_FIND:				//検索
			pView->ShowFind();
			break;

		case	ID_EDIT_COPY:				//コピー
			pView->Copy();
			break;

		case	ID_EDIT_CUT:				//切り取り
			pView->Cut();
			break;

		case	ID_EDIT_PASTE:				//貼り付け
			pView->Paste();
			break;

		case	ID_EDIT_SELECT_ALL:			//全てを選択
			pView->SelectAll();
			break;

		case	ID_FILE_PRINT:				//印刷
			pView->PrintOrPreview(true);
			break;

		case	ID_FILE_PRINT_PREVIEW:		//印刷プレビュー
			pView->PrintOrPreview(false);
			break;

		case	ID_FILE_PRINT_SETUP:		//印刷セットアップ
			pView->PrintSetup();
			break;

		default:
			bHandled = FALSE;
			break;
		}

		return	0;
	}

tabbrowser217.gif スクリプト実行のON/OFFはDISPID_AMBIENT_DLCONTROLで行われる。ここでDLCTL_DLIMAGES(画像の表示)などのフラグを設定することでON/OFFできる。
#include "mshtmdid.h"

//■追加
MIDL_INTERFACE("A419B9D4-2940-44c9-B0E0-A0B0FC61046F")
IAmbientControl : public IUnknown
{
public:
	STDMETHOD (put_nAmbient)(long newVal) = 0;
	STDMETHOD (get_nAmbient)(long* pnVal) = 0;
};

//■追加
class CAmbientControl :
	public CComObjectRootEx<CComSingleThreadModel>
	,public	IDispatchImpl<IDispatch>
	,public IOleClientSite
	,public IAmbientControl
{
	long	_nAmbient;

public:

	CAmbientControl()
	{
		_nAmbient = DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS;
	}

    BEGIN_COM_MAP(CAmbientControl)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(IAmbientControl)
        COM_INTERFACE_ENTRY(IOleClientSite)
    END_COM_MAP()


	STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr)
	{
		if(dispIdMember == DISPID_AMBIENT_DLCONTROL)
		{
			//ダウンロードコントロール設定
			V_VT(pVarResult) = VT_I4;
			V_I4(pVarResult) = _nAmbient;
			return	S_OK;
		}

		//if(dispIdMember == DISPID_AMBIENT_USERAGENT)
		//{
		//	//pvar->vt = VT_BSTR;
		//	//pvar->bstrVal = ::SysAllocString(T2OLE(strUserAgent));
		//}

		return	E_NOTIMPL;
	}

	STDMETHOD(put_nAmbient)(long newVal)
	{
		_nAmbient = newVal;
		return	S_OK;
	}

	STDMETHOD(get_nAmbient)(long* pnVal)
	{
		if(pnVal == NULL)
			return	E_POINTER;
		*pnVal = _nAmbient;
		return	S_OK;
	}


	STDMETHOD(SaveObject)(void)
	{
		return	E_NOTIMPL;
	}

	STDMETHOD(GetMoniker)(DWORD dwAssign,DWORD dwWhichMoniker,IMoniker **ppmk)
	{
		return	E_NOTIMPL;
	}

	STDMETHOD(GetContainer)(IOleContainer **ppContainer)
	{
		return	E_NOTIMPL;
	}

	STDMETHOD(ShowObject)(void)
	{
		return	E_NOTIMPL;
	}

	STDMETHOD(OnShowWindow)(BOOL fShow)
	{
		return	E_NOTIMPL;
	}

	STDMETHOD(RequestNewObjectLayout)(void)
	{
		return	E_NOTIMPL;
	}
};

tabbrowser215.gif
ビューウインドウ内にAmbientDownloadのフラグを取得/設定するための関数を追加する。

本来であればIWebBrowser2から直接現在のダウンロードフラグを取得するべきだが、今回は独自インターフェースIAmbientControlを実装することで、前回設定したフラグ値を取得して利用するようにした。
	CComPtr<IAmbientControl>	_pIAmbientControl;		//■追加


	//■追加
	//ダウンロードコントロール設定
	//nFlagsは DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS などを渡す
	bool	SetAmbientDownloadControl(long nFlags)
	{
		if(_pIAmbientControl == NULL)
			return	false;

		//設定
		_pIAmbientControl->put_nAmbient(nFlags);

		//変更の適用
		HRESULT		hr;
		CComPtr<IOleControl>	pIOleControl;

		hr = _pIWebBrowser2->QueryInterface(&pIOleControl);
		if(pIOleControl)
			hr = pIOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);

		return	SUCCEEDED(hr) ? true : false;
	}


	//■追加
	//ダウンロードコントロール取得
	//nFlagsは DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS などが返る
	bool	GetAmbientDownloadControl(long& nFlags)
	{
		nFlags = 0;
		if(_pIAmbientControl == NULL)
			return	false;

		return	SUCCEEDED(_pIAmbientControl->get_nAmbient(&nFlags)) ? true : false;
	}

	//■追加
	//指定したダウンロードコントロールフラグが現在有効化どうか
	//nFlagはDLCTL_DLIMAGESやDLCTL_NO_SCRIPTSなどを1つだけ渡す
	bool	IsEnableAmbientDownloadControl(long nFlag)
	{
		long	nAmbient;

		GetAmbientDownloadControl(nAmbient);

		return	(nAmbient & nFlag) ? true : false;
	}

	//■追加
	//指定したダウンロードコントロールフラグの設定/解除
	//nFlagはDLCTL_DLIMAGESやDLCTL_NO_SCRIPTSなどを1つだけ渡す
	//bEnable=trueならそのフラグを設定、falseなら解除する
	bool	SetAmbientDownloadControl(long nFlag,bool bEnable)
	{
		bool	ret;
		long	nAmbient;

		ret = GetAmbientDownloadControl(nAmbient);
		if(ret == false)
			return	false;

		if(bEnable)
			nAmbient |= nFlag;
		else
			nAmbient &= ~nFlag;

		return	SetAmbientDownloadControl(nAmbient);
	}

tabbrowser216.gif 最後にビューウインドウが生成されたときに、クライアントサイトとして登録されるようにする。
	//Create関数のオーバーライド。内部でIEの取得、接続などを行う
	HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
			DWORD dwStyle = 0, DWORD dwExStyle = 0,
			_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
	{
		HWND	hWnd;

		hWnd = __super::Create(hWndParent,rect,szWindowName,dwStyle,dwExStyle,MenuOrID,lpCreateParam);
		if(hWnd == NULL)
			return	NULL;			//Create失敗

		QueryControl(&_pIWebBrowser2);		//_pIWebBrowser2にこのビューに関連づいているIEをセットする
		if(_pIWebBrowser2 == NULL)
			return	hWnd;			//WebBrowser取得失敗

		Advise(_pIWebBrowser2);		//IEとの接続


		//■追加
		//jacascriptや画像ダウンロードのコントロール設定
		{
			CComPtr<IOleObject>		pIOleObject;
			CComObject<CAmbientControl>*		pCAmbientControl;
			CComPtr<IAxWinAmbientDispatchEx>	pIAxWinAmbientDispatchEx;

			//ダウンロードコントロールの準備
			CComObject<CAmbientControl>::CreateInstance(&pCAmbientControl);
			if(pCAmbientControl)
				pCAmbientControl->QueryInterface(&_pIAmbientControl);

			//IEコントロールへのセット
			_pIWebBrowser2->QueryInterface(&pIOleObject);
			if(pIOleObject && pCAmbientControl)
				pIOleObject->SetClientSite(pCAmbientControl);

			//デフォルトのダウンロードコントロールを設定
			//本来ならゾーン変化をチェックしてゾーンに応じて決定すべき?
			SetAmbientDownloadControl(DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS);
		}

		//Googleツールバーを生成する
		{
			HRESULT	hr;
			GUID	rclsid;
			WCHAR	pszGUID[] = {L"{2318C2B1-4965-11d4-9B18-009027A5CD4F}"};		//GoogleツールバーのGUID

			::CLSIDFromString(pszGUID,&rclsid);

			_pIDeskBand = NULL;
			hr = ::CoCreateInstance(rclsid,NULL,CLSCTX_INPROC_SERVER,IID_IDeskBand,(void**)&_pIDeskBand);
			if(_pIDeskBand)
			{
				CComPtr<IObjectWithSite>	pIObjectWithSite;

				_pIDeskBand->QueryInterface(IID_IObjectWithSite,(void**)&pIObjectWithSite);

				DESKBANDINFO	sDeskBandInfo;

				//別に必要ないが情報をたくさん取得
				::ZeroMemory(&sDeskBandInfo,sizeof(DESKBANDINFO));
				sDeskBandInfo.dwMask = DBIM_MINSIZE | DBIM_MAXSIZE | DBIM_INTEGRAL | DBIM_ACTUAL | DBIM_TITLE | DBIM_MODEFLAGS | DBIM_BKCOLOR;
				hr = _pIDeskBand->GetBandInfo(0,DBIF_VIEWMODE_NORMAL,&sDeskBandInfo);

				//■■本当はきちんと調整しないとだめ!!
				CRect	rect(0,0,2000,sDeskBandInfo.ptMinSize.y);		//横サイズは十分大きいサイズを確保(//■■2000px固定)

				//デスクバンドをホスト用クラスに割り当てる
				{
					CComPtr<IIEToolbar>	pIIEToolbar;

					pIIEToolbar = new CComObject<CIEToolbar>;

					pIIEToolbar->put_hwnd(_hWndRebarIE);
					if(_pIWebBrowser2)
						pIIEToolbar->put_IWebBrowser2(_pIWebBrowser2);
					if(pIObjectWithSite)
						hr = pIObjectWithSite->SetSite(pIIEToolbar);

					if(SUCCEEDED(hr))
						hr = _pIDeskBand->ShowDW(TRUE);
				}

				//位置調整
				{
					HWND	hWnd;

					_pIDeskBand->GetWindow(&hWnd);
					if(::IsWindow(hWnd))
						::MoveWindow(hWnd,0,0,rect.Width(),rect.Height(),TRUE);
				}
			}
		}

		return	hWnd;
	}

tabbrowser218.gif
これでビルド/実行し「画像表示」をOFFにして「更新」したところ、画像が表示されなくなった。


Googleツールバー6が公開されていたのでインストールしたところ、このタブブラウザ上でGoogleツールバーの下部が少し欠けて表示されるようになってしまった。次回はこれを機会にGoogleツールバー表示部分を少し見直す。

プロジェクトファイルをダウンロード


カテゴリー「タブブラウザーを作る」 のエントリー