컴퓨터 공학/C++

[C++] NativeMessaging으로 크롬 확장 앱과 C/C++ 앱 통신하기

혼새미로 2019. 11. 27. 19:33
반응형

크롬 브라우저에서 크롬 확장 앱을 사용하면 로컬에 있는 C/C++ 기반의 앱과 통신을 할 수 있습니다.

[준비물]
* 크롬 브라우저
* Visual Studio (버전 무관)

chrome_extension_sample.7z
0.01MB

첨부 파일로 올린 'chrome_extension_sample.7z'을 내려받아 압축을 해제합니다.

그림과 같이 메뉴 - 도구 더보기 - 확장 프로그램을 클릭합니다.

우측 상단에 개발자 모드를 on으로 설정합니다.

좌측 상단에 '압축해제된 확장 프로그램을 로드합니다.'를 클릭합니다. 그리고 위에서 내려받은 압축파일에 있는 app 폴더를 선택해줍니다.

그럼 다음과 같이 'Chrome 앱'에 확장 프로그램이 추가된 것을 확인할 수 있습니다.

다시 크롬 브라우저의 새창을 열어서 url 입력창에 chrome://apps/ 을 입력하여 확장 앱 목록으로 이동합니다.

그러면 위와 같이 'Native Messaging Example'이라는 이름의 앱이 보이는데, 아직 클릭하지 마시기 바랍니다.

다시 위에서 내려받은 압축파일에 있는 host 폴더에 보면 install_host.bat 파일이 있는데 이를 더블클릭하여 레지스트리에 호스트 프로세스의 위치를 등록하여 줍니다.

다음으로, 크롬 브라우저에서 Native Messaging Example 앱을 클릭하여 줍니다.

그러면 위와 같이 창에 connect 버튼만 달랑 있는데 클릭해줍니다.

클릭하면 위와 같이 텍스트를 입력할 수 있는 컴포넌트가 생기가 아래에 Send 버튼이 나타납니다.
입력 칸에 임의의 문자열을 입력한 후 Send 버튼을 클릭해줍니다.

클릭하면 위와 같이 Sent message에 확장 앱에서 보낸 메시지, 그리고 Received message에 C/C++로부터 받은 메시지가 출력되는 것을 확인할 수 있습니다.

확실히 하기 위해 host 폴더에 보면 다음과 같이 input.txt 파일이 새로 생긴 것을 확인할 수 있습니다. 이는 확장 앱으로부터 전달받은 메시지를 파일로 저장한 것입니다.

열어보면 위와 같이 브라우저에서 본 메시지와 동일한 것을 확인할 수 있습니다.

확장 앱은 host 폴더에 있는 nativeMessaging.exe 파일을 실행해서 이 프로세스와 통신을 하는데, 이 실행파일은 제가 사전에 빌드한 파일입니다. 

이에 대한 소스코드는 host/src에 있으며, 다음과 같습니다.

#include <iostream>
#include <string>
#include <memory>
#include <fstream>
using namespace std;

/* INFO: 크롬 확장 앱으로부터 데이터 크기를 쉽게 입력받기 위한 공용체 */
union U32_U8 {
	uint32_t u32;
	uint8_t u8[4];
} ;

/* INFO: 크롬 확장 앱으로부터 전달받은 데이터를 파일로 기록 */
void write_recieved_data(unique_ptr<char[]>& data) {
	const string filename{ "./intput.txt" };

	/* INFO: 크롬 확장으로부터 받은 데이터 파일 출력 */
	string msg = data.get() + '\0';
	ofstream wf(filename, fstream::out | fstream::app);
	if (!wf.is_open()) {
		return;
	}

	wf << msg << endl;

	wf.close();
}

void main() {
	constexpr size_t INPUT_DATA_LENGTH = 4;
	size_t inputSize{ 0 };
	U32_U8 lenBuf;
	lenBuf.u32 = 0;
	/* INFO: 데이터 크기 입력받음 */
	inputSize = fread(lenBuf.u8, 1, 4, stdin);
	/* INFO: 지정한 데이터 길이가 아니면 오류이다. */
	if (inputSize != INPUT_DATA_LENGTH) {
		return;
	}
	
	int iLen = (int)lenBuf.u32;
	/* INFO: 크롬 확장 앱으로부터 전달받은 데이터 크기가 0 이하면 오류이다. */
	if (iLen <= 0) {
		return;
	}

	unique_ptr<char[]> receivedData = make_unique<char[]>(8 * iLen);
	/* INFO: 입력한 크기만큼의 데이터를 입력받음 */
	inputSize = fread(receivedData.get(), 1, iLen, stdin);

	write_recieved_data(receivedData);

	/* INFO: 전송할 데이터 크기 전달 */
	fwrite(lenBuf.u8, 1, 4, stdout);
	/* INFO: 실제 데이터 전달 */
	fwrite(receivedData.get(), 1, iLen, stdout);
	/* INFO: 버퍼 비워주기 */
	fflush(stdout);
}

필요에 따라 소스 코드를 수정해서 사용하시면 됩니다.

반응형