Gecko Embedding Basics

  • 리비전 슬러그: Gecko_Embedding_Basics
  • 리비전 제목: Gecko Embedding Basics
  • 리비전 아이디: 164320
  • 제작일시:
  • 만든이: Neot
  • 현재 리비전인가요? 아니오
  • 댓글 /* 인터페이스 */

리비전 내용

정보의 원천, 놀이, 개인간 교류 수단으로써 웹의 중요성이 끝없이 증가하면서, HTML 포맷으로 저장된 데이터에 접근하고 보는 능력은 다양한 소프트웨어 애플리케이션을 폭넓게 대체하기 위해 점점 더 중요해지고 있다. 단순한 HTML 페이지 뷰어건 완벽한 기능의 웹 브라우저이건, HTML 기반 문서를 해석하고 그려내는 것은 수많은 상황에서 매우 중요한 기능이 됐다. 애플리케이션 개발자는 개발 시간을 최소화하면서도 애자일하고 안정성이 높은 제품을 만들기 위해, HTML을 출력하는 결정적인 기능을 어떻게 구현할지에 고민하게 되었다. Gecko, 즉 넷스케이프와 모질라 브라우저의 핵심에 있는 렌더링 엔진을 임베딩하는 것은 이런 문제에 대한 훌륭한 해결책이다.

왜 Gecko인가?

Gecko를 임베딩하는 것은 현명한 선택이다. Gecko는 빠르고, 안정적이며 표준을 매우 잘 지키고 있다. Mozilla와 Netscape의 지원 아래서 매우 널리 배포되었으며 많은 사람들이 꾸준히 지켜보고 있다.

Gecko는 오픈 소스이다. 다른 임베딩 브라우저 솔루션과는 달리, Gecko의 모든 소스 코드는 자유롭게 사용할 수 있으며 마음껏 수정할 수 있다. 필요한 만큼 뜯어 고칠 수 있다. 또한 현재의 라이센스에 따르면, Gecko를 독점적인 상용 제품에 컴포넌트로 사용할 수도 있다.

Gecko는 Mozilla 프로젝트와 연관되어 있으므로, Mozilla 프로젝트에서 임베딩 작업에 도움이 되는 많은 리소스를 쉽게 얻을 수 있다. Mozilla 웹 사이트에는 임베딩 프로젝트 영역이 있다. 또한 mozilla.dev.emobedding 뉴스그룹이 있으며, 많은 관련 뉴스그룹과 함께 임베딩 개발자들 간에 정보를 교환하는 것을 주 목적으로 하고 있다. 전체 코드기반 상호 참조가 가능하며, Bugzilla 버그 데이터베이스를 통해 버그 제출, 버그 진행 상황 참조, 버그 수정 참여 등을 간단히 할 수 있다.

Gecko는 바닥부터 크로스플랫폼으로 설계되었다. mozill.org에서는 직접 Wintel, MacOS 9.0과 OS X, 리눅스를 지원하고 있으며, 수많은 다른 플랫폼도 써드파티에서 지원하고 있다.

마지막으로, Gecko를 라이센스하는 것은 로열티가 필요 없으며, 심지어 독점 저작권을 갖는 상용 제품에도 로열티없이 적용할 수 있다. "매우" 일반적으로는, 모질라가 제공하는 원본 소스코드에 대해서는 어떤 수정도 커뮤니티에 반환되어야 한다.(Gecko를 임베드하는 코드까지 반환해야하는 것은 아니다.) 즉 애플리케이션의 사용자라면 사용중인 Gecko 엔진에 해당하는 소스 코드를 언제든지 얻을 수 있어야 하며(대부분 mozilla.org 웹사이트 링크를 통해서), 애플리케이션은 명확한 방법으로 Gecko를 사용하고 있음을 공지해야 한다. (예를 들면, 제품 박스 위의 로고나 About: 페이지 등) 가능한 라이센스 방법에 대한 정확한 설명은 라이센스에 대해 유일한 법적 근거인 Mozilla & Nescape Public Licneses에서 볼 수 있다.

임베딩에 필요한 것

Gecko를 임베드하기로 결정했다면, 세가지 과정을 밟아야 한다. 첫째로 코드를 얻는다. 다음으로 Gecko 코드베이스를 다루는데 사용되는 몇가지 지정 기술을 이해해야 한다. 마지막으로 추가하려는 부가적인 기능을 결정해야 한다. 이 절은 이러한 과정을 안내할 것이다.

코드 얻기

이 글을 쓰는 시점에서 Gecko를 임베드하기 위한 파일을 얻는 가장 좋은 방법은 전체 Mozill 소스 트리를 다운로드해서 빌드하는 것이다. 사실 상당히 간단한 과정이다. 전체 설명과 적절한 링크는 Download Mozilla Source Code에서 찾을 수 있다. 두번째 방법(컴포넌트에 의한 컴포넌트)은 현재 개발 중이며, 아직 베타 상태에 있다. 이 프로젝트에 대한 정보는 REQUIRES 기반 빌드 메카니즘에서 찾을 수 있다. 그 외에, Gecko 런타임 환경(GRE, Gecko Runtime Environment)가 개발중에 있다. GRE는 단일 코어 라이브러리를 사용하는 모질라 컴포넌트 위에서 여러가지 애플리케이션을 지원하기 위한 것이다. (컴포넌트에 의한 컴포넌트를 사용하려고 생각한다면, 우선 버전과 바이너리 호환성에 대한 이슈를 잘 살펴봐야 한다. XPCOM 컴포넌트 재사용을 살펴보면 도움이 될 것이다.)

우선 몇가지 도구(기본으로 컴파일러, 펄 배포판, 몇몇 범용 유틸리티)를 가져와야 한다. 그런 다음 컴퓨터 환경을 설정하고, 소스를 다운로드 한다. 전체 트리를 다운로드하려 한다면, 두가지 방법이 있다. FTP에서 전체 소스 트리를 tar로 압축한 파일을 가져올 수 있다. (이것이 가장 간단한 방법이며, 확실히 컴파일이 가능한 한 방법이다. 다만 최근에 수정된 코드는 포함하지 않았을 수도 있다.) 다른 방법은 CVS에서 가장 최신의 코드를 가져오거나 변경분에 대한 업데이트를 수행하는 것이다. 소스를 가져와서 환경 설정을 적절히 끝마친 다음에는 제공된 makfile 중 적절한 것을 실행하면 된다. 각 플랫폼마다 컴파일 과정에 대한 상세한 설명이 있다.

빌드가 끝나면 mozilla/embedding/config 디렉토리로 간다. 거기서 예제 manifest 파일을 찾을 수 있을 것이다. (파일들은 모두 이름이 "basebrowser"로 시작한다. manifest 파일은 각 플래폼마다 임베딩을 위한 개별 설정이다. 기본으로 들어있는 것은 단지 예제일 뿐이며, 당신의 목적에는 딱 들어맞지 않을 수도 있다. 하지만 예제로 시작해서 조금씩 수정해 나가면 좋을 것이다. 각 플랫폼마다 모델로 삼을 만한 예제 임베딩 프로젝트들도 있다. Roll_your_own_browser_-_An_embedding_HowTo를 참고하라.

코드 작성 환경 이해하기

모질라는 처음부터 여러 플랫폼과 프로그래밍 언어에 대한 설계와 개발을 지원하는 것으로 시작됐다. 결국 여러가지 자체 프로그래밍 기술이 개발되었으며, 모두 다 객체 은폐라는 이상적인 개념을 바탕으로 두고 있다. Gecko 임베딩에는 XPCOM, XPIDL, XPConnect, 특별 문자열 클래스, XUL 등의 기술에 대한 실제적인 지식을 필요로 한다. 다음은 각 기술에 대한 간략한 소개이다. 더 자세한 정보는 mozilla.org 사이트에서 찾을 수 있다.

XPCOM

모질라 기술 중 가장 중요한 것은 XPCOM, 즉 크로스플랫폼 컴포넌트 오브젝트 모델(Cross-Platform Component Object Model)이다. XPCOM은 객체나 다른 데이터의 생성, 소유, 제거를 모질라 전체에 걸쳐 관리하는 프레임워크를 제공한다. MSCOM을 사용한 적이 있다면, 기본적으로 유사한 개념임을 느낄 것이다. 하지만 매우 큰 차이가 있다. XPCOM은 크로스플랫폼이며 단일 스레드에서 대부분 동작하도록 설계되어 있다. 또한 XPCOM와 MSCOM은 현재로써는 아직 호환되지 않는다.

인터페이스

XPCOM의 핵심은 인터페이스라는 개념이다. 인터페이스는 특정 기증과 연관된 메소드, 속성, 관련 상수의 집합을 기술한 것일 뿐이다. 실제 기능을 구현하는 클래스와는 전혀 별개이다. 인터페이스는 계약의 역할을 한다. 특정 인터페이스를 지원하는 객체는 인터페이스에 기술된 서비스를 수행한다는 약속의 의미이다. 인터페이스를 최대한 중립적으로 유지할 수 있도록 IDL(Interface Definition Language)라는 별도의 언어를 사용해서 기술한다. 인터페이스 파일은 일반적으로 .idl이라는 확장자를 갖는다. 인터페이스의 기능을 지정할 뿐만 아니라 인터페이스의 IID도 지정한다. IID는 인터페이스를 지정할 때 사용하는 세계에서 유일한 번호이다.

Gecko 내에서 이루어지는 통신의 대부분은 추상 구조체를 거친다. (규약에 따라 추상 구조체의 이름은 nsISomething의 형식을 따른다.)

//이거야
void ProcessSample(nsISample* aSample) {
	aSample->Poke("Hello"); 
//이건 아니야
void ProcessSample(nsSampleImpl* aSample) {
	aSample->Poke("hello"); 
@status FROZEN

XPCOM의 추상화 수준으로 인해 시스템이 매우 큰 유연성을 갖추게 됐다. 구현은 필요에 따라 얼마든지 변경할 수 있다. 하지만 최소한 인터페이스 자체는 고정된 채로 유지해야 한다. 모질라의 초기 설계와 개발 기간 동안에는 인터페이스는 다소 유동적인 것이었지만, 프로젝트가 성숙되면서 점점 더 많은 인터페이스가 FROZEN으로 표시됐다. FROZEN으로 표시된 인터페이스는 향후 변경되지 않음을 보장한다는 의미이다.

임베딩 관련된 대부분의 주요 인터페이스가 FROZEN으로 표시되긴 했지만, 인터페이스를 사용하기 전에 확인해보는 것이 좋다. 인터페이스의 상태는 .idl 파일의 주석에 나열된다. 얼려진 인터페이스(frozen interface)는 @status FROZEN라는 표시가 달린다. 모질라 상호 참조 도구를 사용해서 얼려진 인터페이스를 검색할 수도 있다. 얼려지지 않은 상태의 인터페이스는 언제든지 변경될 가능성이 있다. 얼리는 과정에 대한 자세한 정보는 임베딩 프로젝트 페이지를 참고하라.

인터페이스가 얼려지고 나면 해당 인터페이스는 Gecko 임베딩 API 참조에 추가된다.

nsISupports

한 객체가 하나 이상의 인터페이스를 지원할 수 있다. 실제로는 모든 객체는 최소한 두 개의 인터페이스를 지원해야 한다. 하나는 실제 객체의 역할이 되는 무언가이고, 다른 하나는 범용적인 목적으로 사용되는 nsISupports이다. 다르게 말하자면 nsISupports는 모든 XPCOM 인터페이스의 조상이다. 모든 인터페이스는 nsISupports로부터 상속되며, 대부분은 직접 상속받는다. nsISupports는 두가지 주요 기능을 갖는다. 런타임 타입 발견과 객체 생명주기 관리이다. MSCOM의 IUnknown과 동일한 역할을 한다.

모든 객체가 다중 인터페이스를 지원하기 때문에, 한 인터페이스에 대한 포인터를 가진 상태에서 해당 객체가 당장 필요한 기능을 제공하는 다른 인터페이스를 지원하는지 알아낼 수 있다. 첫번째 nsISupports 메소드인 QueryInterface()는 다음과 같은 질문을 수행한다. "나는 이 객체가 A 타입임(인터페이스 A를 지원함)을 알고 있다. 그런데 타입 B이기도 한가?(인터페이스 B도 지원하는가?)"

만일 그렇다면 QueryInterface()는 새로 요청된 인터페이스로 연결된 포인터를 반환한다.

void ProcessSample(nsISample* aSample) {
	nsIExample *example;
	nsresult rv;
	rv = aSample->QueryInterface(NS_GET_IID(nsIExample),(void **)&example); 
	if (NS_SUCCEEDED(rv)) {
		example->DoSomeOperation();
		NS_RELEASE(example); // Release호출을 위해 매크로를 사용 
	} 
} 

XPCOM은 간접적인 방법(컴포넌트 관리자)을 사용해서 객체의 인스턴스를 생성하기 때문에, 같은 객체에 대한 다중 포인터(각각 다양한 인터페이스로 연결됨)가 존재할 수 있으며, 포인터가 가리키는 모든 객체를 호출자가 정확하게 추적하기 어려워질 수 있다. 객체가 필요하지 않은 상황에서도 남아있게 되서 메모리 누수가 발생하거나, 필요한 객체가 삭제되는 바람에 댕글링 포인터가 나타날 수도 있다. nsISupports의 다른 두 메소드 AddRef()Release()는 이런 이슈를 다루기 위해 설계된 것이다. 포인터가 변수에 입력될 때마다AddRef()가 호출되어 내부 카운터가 증가한다. 포인터가 풀려날 때마다 Release()가 호출되어 내부 카운터가 감소한다. 카운터가 0이 되면, 객체에 대한 포인터가 없으며 객체를 안전하게 삭제할 수 있다. 객체의 수명에 대한 제어는 객체 내부에 있는 것이다. 이와 같은 과정을 자동화할 수 있도록 돕는 유틸리티인 XPCOM "스마트" 포인터nsCOMPtr에 대한 정보를 참고하라.

객체 생성

XPCOM에서는 객체의 인스턴스 생성조차도 간접적인 절차를 거친다. 인터페이스가 GUID(Globally Unique ID)인 IID를 갖는 것처럼, XPCOM 클래스도 자신만의 GUID인 CID를 갖는다. 또는 문자 기반 ID인 Contract ID로 참조하기도 한다. 두가지 ID 중 하나를 객체를 생성하는 영속적인 XPCOM 컴포넌트인 "컴포넌트 관리자"의 메소드에 전달한다. 새로운 클래스 라이브러리(XPCOM에서는 모듈이라고 부른다)를 시스템에 처음 배치할 때, 라이브러리는 자기 자신을 컴포넌트 관리자에 등록하며, 컴포넌트 관리자는 클래스(ID로 참조)와 클래스가 포함된 라이브러리를 매핑하는 레지스트리를 관리한다.

싱글턴 객체가 제공하는 몇가지 영속적인 서비스는 컴포넌트 관리자와 함께 서비스 관리자가 생성하고 제어한다. 컴포넌트 관리자 자체도 영속적인 서비스의 예시 중 하나이다.

요약

XPCOM에 포함된 기능은 추상 인터페이스로 기술되며, 시스템 요소 간의 대부분의 통신은 인터페이스를 거쳐서 이루어진다. 반면, 인터페이스를 구현하는 하부 객체들은 교차색인 레지스트리에 기반한 컴포넌트 관리자에 의해 간접적으로 생성된다.

모든 인터페이스가 공유하는 기능 한가지는 런타임에서 하부 객체에게 어떤 다른 인터페이스를 구현하고 있는지 질의하는 기능이다. 인터페이스는 고정되어 변하지 않는다는 가정이 있는 것이지만, 현재 모질라 코드베이스에서는 FROZEN으로 선언된 인터페이스들만이 크게 변경되지 않을 것임을 보장한다. 객체 생명주기 관리는 객체 내에 들어있는 자신에게로 향하는 포인터의 개수를 추적하는 내부 카운터를 통해 이루어진다. 객체를 사용하는 클라이언트가 해야 할 일은 카운터를 올리거나 내리는 것 뿐이다. 내부 카운터가 0에 도달하면 객체는 자기자신을 삭제한다.

nsCOMPtr

하지만 AddRef()Release()를 적절한 때에 호출하는 것을 가끔 잊어버릴 수도 있다. 이런 과정을 더 쉽고 확실히 화기 위해 XPCOM은 내장 "스마트" 포인터인 nsCOMPtr을 제공한다. 이 포인터는 AddRef()Release() 호출을 처리한다. 대신 nsCOMPtr을 사용하면 코드를 더 명확하고 효율적으로 만들 수 있다. 스마트 포인터에 대한 추가 정보는 "The Complete nsCOMPtr User's Manual"을 참고하라.

모질라는 수많은 내장 매크로(규약에 따라 코드 내에서 모두 대문자로 작성됨)나 nsCOMPtr과 같은 유틸리티를 제공해서 XPCOM으로 코딩하는 과정을 더 쉽게 만들어 준다. 이들 중 대부분은 다음 파일에서 찾을 수 있다.

<tt>nsCom.h</tt>, <tt>nsDebug.h</tt>, <tt>nsError.h</tt>, <tt>nsIServiceManager.h</tt>, <tt>nsISupportsUtils.h</tt>

모질라는 메모리 사용량 추적 기능 같은 개발 도구까지 제공한다. 이런 도구에 대한 정보는 http://www.mozilla.org/performance/ 에서 찾을 수 있다.

참고자료

XPCOM에 대한 참고자료는 일반적으로 XPCOM에서 찾을 수 있다. XPCOM 컴포넌트 작성에 대한 개략적인 내용은 오릴리 서적인 Creating Applications with Mozilla의 8장에서 참고할 수 있다. 전체 내용이 XPCOM 관련된 책인 Creating XPCOM Components도 있다. Don Box가 저술한 Essential COM에서는 COM 시스템의 기반 로직에 대해 더욱 상세히 설명하고 있다. 비록 MSCOM에 대해 초점을 맞춘 책이긴 하지만, 객체 모델 등을 사용할 때 필요한 핵심 원리를 이해하하기에 매우 훌륭한 배경지식을 제공한다.

XPIDL

인터페이스는 XPIDL(Cross Platform Interface Definition Language)로 작성된 추상 클래스이다. 여전히 인터페이스에서 제공할 기능은 몇몇 정규 프로그래밍 언어로 작성하는 것이 유용하다. XPIDL 컴파일러가 이런 역할을 한다. 인터페이스를 .idl 파일에 정의하면 XPIDL 컴파일러가 정의된 인터페이스를 처리한다.

컴파일러는 여러가지 출력이 가능하지만, 일반적으로는 두가지 출력을 사용한다. 인터페이스의 C++ 구현을 위해 사용하며 주석달린 템플릿을 포함하는 C++ .h 파일이 그 중 하나이다. 다른 하나는 XPConnect가 사용할 타입 라이브러리 정보를 포함하는 XPT 파일이다. XPConnect는 JavaScript에서 인터페이스를 사용할 수 있도록 한다. XPIDL의 문법(간단한 C 스타일 언어)에 대한 자료와 컴파일러 사용법이 참고하라.

XPConnect와 XPT 파일

XPConnectJavaScript로 작성된 코드에 접근하거나, C++로 작성된 XPCOM 컴포넌트를 다룰 수 있도록 하는 XPCOM 모듈이다. XPConnect를 사용하면, XPCOM 인터페이스를 제공하거나 사용하는 양쪽 컴포넌트가 상대방이 어떤 언어로 작성됐는지 신경쓸 필요가 없다.

인터페이스를 XPIDL 컴파일러에 적용하면, XPT 또는 타입 라이브러리 파일을 생성한다. XPConnect는 XPT 파일로부터 얻은 정보를 사용해서 C++ 객체와 JavaScript 객체 간의 통신을 XPCOM 인터페이스를 통해서 투명하게 구현한다. 그러므로 C++로만 개발하더라도 XPCOM 인터페이스를 생성해서 코드에 포함시키는 것이 매우 중요하다. 브라우저의 특정 부분만 JS로 구현된 것이 아니라, 향후에도 누군가 JS 기반 코드를 사용해서 당신이 작성한 컴포넌트와 상호작용하도록 할 수도 있다.

현재 모질라에서 XPConnect는 C++와 JS 간의 상호작용을 가능하게 한다. 다른 언어(Python 등)에서 접근할 수 있도록 하는 모듈은 별도로 개발 중이다.

String 클래스

웹 브라우징은 일반적으로 많은 양의 문자열 처리를 필요로 한다. 모질라는 문자열을 처리하고 효율적으로 빠르게 출력하기 위한 C++ 클래스 라이브러리를 개발해왔다. 모질라는 객체 간 통신을 간단하게 하고 에러를 줄이기 위해 인터페이스, 즉 추상 클래스를 사용한다. 같은 이유로 String 클래스 계층도 nsAString, nsASingleFragmentString, nsAFlatString 등의 몇가지 추상 클래스를 앞세운다. (이 클래스들은 2바이트 문자열을 참조한다. nsACString로 시작하는 1바이트 문자열을 참조하는 계층이 동일한 구조로 별도로 존재한다.) nsAString은 문자로 구성된 문자열이라는 것만 보장한다. nsASingleFragmentString는 문자들이 한 버퍼에 저장되어 있음을 보장한다. nsAFlatString는 문자들이 하나의 null로 끝나는 버퍼에 들어있음을 보장한다. 하부에는 구상 클래스가 있지만, 되도록이면 가능한한 가장 추상적인 타입을 사용하는 것이 좋다. 예를 들어 문자열 접합(concatenation)은 포인터를 사용해서 가상으로 이루어질 수 있으며, 그 결과는 다른 문자열처럼 사용될 수 있는 nsAString이다. 덕분에 메모리 할당과 복사를 하지 않아도 된다. 더 자세한 정보는 "Guide to the Mozilla string classes"를 참고하라.

XUL/XBL

이 마지막 모질라 기술은 애플리케이션의 UI를 어떻게 만들 것이냐에 따라 선택해서 사용할 수 있다. XUL은 모질라의 매우 유연한 XML UI 언어이다. 매우 다양한 플랫폼 독립적인 위젯을 제공하며 위젯들을 사용해서 UI를 작성할 수 있다. 넷스케이프와 모질라는 모두 XUL을 인터페이스로 사용하지만, 모든 임베딩 애플리케이션 개발자들이 XUL을 사용하는 것은 아니다. XBL(eXtensible Binding Language)은 XUL의 XML 요소에 동작을 추가하는 데 사용할 수 있다. XUL에 대한 더 자세한 정보는 XUL Programmer's Reference에서, XBLXBL:XBL_1.0_Reference에서 찾을 수 있다. XULPlanet에도 XUL에 관련된 좋은 정보가 많다.

Choosing Additional Functionalities

As of this writing (8/19/02), Gecko is a partially modularized rendering engine. Some functionalities beyond basic browsing are always embedded with Gecko, and, as a result of certain architectural decisions, always will be; some are at present always embedded with Gecko, but may, at some point in the future, be separable; and some are now available purely as options. The following table describes the present status of these additional functionalities:

Functions Status Now Status in Future
FTP support Optional
HTTPS support Optional
International character support Optional
XUL support Required Probably optional
Network support Required Maybe optional
JavaScript support Required Maybe optional
CSS support Required Always required
DOM support Required Probably always
XML support Required Probably always

At this time embedding Mozilla's editor along with the rendering engine Gecko is an uncertain proposion, although the situation continues to improve. For more information on the status of the embeddable editor, see http://www.mozilla.org/editor/Editor_Embedding_Guide.html.

What Gecko Provides

The following is a description of some of the interfaces most commonly used in embedding Gecko. It is by no means an exhaustive list of the available interfaces. The interfaces in this section are on classes provided by Mozilla. There is also a set of interfaces for which Gecko expects the embedder to provide the implementation. A sample of those are covered in the next section.

Initialization and Teardown

There are two C++ only functions which serve to initalize and terminate Gecko. The initialization function (NS_InitEmbedding) must be called before attempting to use Gecko. It ensures XPCOM is started, creates the component registry if necessary, and starts global services. The shutdown function (NS_TermEmbedding) terminates the Gecko embedding layer, ensuring that global services are unloaded, files are closed and XPCOM is shut down.

nsIWebBrowser

Use of this interface during initialization allows embedders to associate a new nsWebBrowser instance (an object representing the "client-area" of a typical browser window) with the embedder's chrome and to register any listeners. The interface may also be used at runtime to obtain the content DOM window and from that the rest of the DOM.

The XULPlanet nsWebBrowser reference also has a lot of useful information on this class.

nsIWebBrowserSetup

This interface is used to set basic properties (like whether image loading will be allowed) before the browser window is open.

nsIWebNavigation

The nsIWebNavigation interface is used to load URIs into the web browser instance and provide access to session history capabilities - such as back and forward. As of June 6, 2006, this interface is not yet frozen.

nsIWebBrowserPersist

The nsIWebBrowserPersist interface allows a URI to be saved to file. As of June 6, 2006, this interface is not yet frozen.

nsIBaseWindow

The nsIBaseWindow interface describes a generic window and basic operations (size, position, window title retrieval, etc.) that can be performed on it. As of June 6, 2006, this interface is not yet frozen.

nsISHistory

The nsISHistory interface provides access to session history information and allows that information to be purged.

nsIWebBrowserFind

The nsIWebBrowserFind interface controls the setup and execution of text searches in the browser window.

What You Provide

The following is a description of some of the more common embedder-provided interfaces used in embedding Gecko. It is by no means an exhaustive list of the available interfaces.

nsIWebBrowserChrome

The nsIWebBrowserChrome interface corresponds to the top-level, outermost window containing an embedded Gecko web browser. You associate it with the WebBrowser through the nsIWebBrowser interface. It provides control over window setup and whether or not the window is modal. It must be implemented.

nsIEmbeddingSiteWindow

The nsIEmbeddingSiteWindow interface provides Gecko with the means to call up to the host to resize the window, hide or show it and set/get its title. It must be implemented.

nsIWebProgressListener

The nsIWebProgressListener interface provides information on the progress of loading documents. It is added to the WebBrowser through the nsIWebBrowser interface. It must be implemented. As of this writing (8/19/02), it is not frozen.

nsISHistoryListener

The nsISHistoryListener interface is implemented by embedders who wish to receive notifications about activities in session history. A history listener is notified when pages are added, removed and loaded from session history. It is associated with Gecko through the nsIWebBrowser interface. Implementation is optional.

nsIContextMenuListener

The nsIContextMenuListener interface is implemented by embedders who wish to receive notifications for context menu events, i.e. generated by a user right-mouse clicking on a link. It should be implemented on the web browser chrome object associated with the window for which notifications are required. When a context menu event occurs, the browser will call this interface if present. Implementation is optional.

nsIPromptService

The nsIPromptServices interface allows the embedder to override Mozilla's standard prompts: alerts, dialog boxes, and check boxes and so forth. The class that implements these embedder specific prompts must be registered with the Component Manager using the same CID and contract ID that the Mozilla standard prompt service normally uses. Implementation is optional. As of this writing (8/19/02), this interface is not frozen.

Common Embedding Tasks

The following is a series of code snippets (taken from MFCEmbed, the Windows based embedding Gecko sample) which demonstrate very briefly implementation associated with common embedding tasks.To see all the files associated with this sample, go to http://lxr.mozilla.org/seamonkey/source/embedding/tests/mfcembed/. There are also Linux- and Mac OS-based examples.

Gecko setup

The Gecko embedding layer must be initialized before you can use Gecko. This ensures XPCOM is started, creates the component registry if necessary, and starts global services. There is an equivalent shutdown procedure.

Note that the embedding layer is started up by passing it two parameters. The first indicates where the executable is stored on the file system (nsnull indicates the working directory). The second indicates the file location object "provider" that specifies to Gecko where to find profiles, the component registry preferences, and so on.

nsresult rv;
rv = NS_InitEmbedding(nsnull, provider);
if(NS_FAILED(rv))
{
ASSERT(FALSE);
return FALSE;
} 

Creating a browser instance

The embedder-provided BrowserView object calls its method CreateBrowser(). Each browser object (a webbrowser) represents a single browser window. Notice the utility directive do_CreateInstance() and the use of macros.

//Create an instance of the Mozilla embeddable browser
 
HRESULT CBrowserView::CreateBrowser() 
{
// Create a web shell  
nsresult rv;
mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv);
if(NS_FAILED(rv))
return rv; 

Once the nsWebBrowser object is created the application uses do_QueryInterface() to load a pointer to the nsIWebNavigation interface into the mWebNav member variable. This will be used later for web page navigation.

rv = NS_OK;
mWebNav = do_QueryInterface(mWebBrowser, &rv);
if(NS_FAILED(rv))
return rv; 

Next the embedder-provided CBrowserImpl object is created. Gecko requires that some interfaces be implemented by the embedder so that Gecko can communicate with the embedding application. See the What You Provide Section. In the sample, CBrowserImpl is the object that implements those required interfaces. It will be passed into the SetContainerWindow() call below.

mpBrowserImpl = new CBrowserImpl();
if(mpBrowserImpl == nsnull)
return NS_ERROR_OUT_OF_MEMORY; 

The mWebBrowser interface pointer is then passed to the CBrowserImpl object via its Init() method. A second pointer to the platform specific BrowserFrameGlue interface is also passed in and saved. The BrowserFrameGlue pointer allows CBrowserImpl to call methods to update status bars, progress bars, and so forth.

mpBrowserImpl->Init(mpBrowserFrameGlue, mWebBrowser);
mpBrowserImpl->AddRef(); 

Next the embedder-supplied chrome object is associated with the webbrowser. Note the use of an nsCOMPtr.

mWebBrowser->SetContainerWindow
	(NS_STATIC_CAST(nsIWebBrowserChrome*, mpBrowserImpl)); 
nsCOMPtr<nsIWebBrowserSetup>setup(do_QueryInterface(mWebBrowser));  
if (setup) 
	setup->SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER,PR_TRUE); 

Then, the real webbrowser window is created.

rv = NS_OK;
mBaseWindow = do_QueryInterface(mWebBrowser, &rv);
if(NS_FAILED(rv))
return rv; 

Binding a window

Basic location information is passed in.

RECT rcLocation;
GetClientRect(&rcLocation);
if(IsRectEmpty(&rcLocation)) 
{
	rcLocation.bottom++;
	rcLocation.top++;
}
rv = mBaseWindow->InitWindow(nsNativeWidget(m_hWnd), 
		nsnull,0, 0, rcLocation.right - rcLocation.left, 
		rcLocation.bottom - rcLocation.top);
rv = mBaseWindow->Create(); 

Note the m_hWnd passed into the call above to InitWindow(). (CBrowserView inherits the m_hWnd from CWnd). This m_hWnd will be used as the parent window by the embeddable browser.

Adding a listener

The BrowserImpl object is added as an nsIWebProgressListener. It will now receive progress messages. These callbacks will be used to update the status/progress bars.

nsWeakPtr weakling
	(dont_AddRef(NS_GetWeakReference(NS_STATIC_CAST(nsIWebProgressListener*, 
			mpBrowserImpl))));
void mWebBrowser->AddWebBrowserListener(weakling, NS_GET_IID(nsIWebProgressListener)); 

Finally the webbrowser window is shown.

mBaseWindow->SetVisibility(PR_TRUE);

Using session history to navigate

The pointer to nsIWebNavigation saved above is used to move back through session history.

void CBrowserView::OnNavBack() 
{
if(mWebNav)
	mWebNav->GoBack();
} 

Appendix: Data Flow Inside Gecko

While it isn't strictly necessary for embedders to understand how Gecko does what it does, a brief overview of the main structures involved as Gecko puts bits on a display may be helpful.

Image:EmbeddingBasicsa.gif

HTML data comes into Gecko either from the network or a local source. The first thing that happens is that it is parsed, using Gecko's own HTML parser. Then the Content Model arranges this parsed data into a large tree. The tree is also known as the "Document" and its structure is based on the W3C Document Object Model. Any use of DOM APIs manipulates the data in the Content Model.

Next the data is put into frames using CSS and the Frame Constructor. A frame in this sense (which is not the same thing as an HTML frame) is basically an abstract box within which a DOM element will be displayed. This process produces a Frame Tree, which, like the Content Model, is a tree of data, but this time focused not on the logical relationship among the elements but on the underlying calculations needed to display the data. In the beginning a frame has no size. Using CSS rules specifying how the elements of the DOM should look when they are displayed, including information like font type or image size, the eventual size of each frame is calculated. Because the same data may need to be displayed in different ways -- to a monitor and to a printer, for example -- a particular Content Model may have more than one Frame Tree associated with it. In such a case, each individual Frame Tree would belong to a different "presentation" mode.

Calculations continue as new information flows into the system using a process called reflow. As information in the Frame Tree changes, the section of the Frame Tree involved is marked "dirty" by the Frame Constructor. Reflow repeatedly steps through the tree, processing every "dirty" item it encounters until all the items it encounters are "clean". Every item in the Frame Tree has a pointer back to its corresponding item in the Content Model. A change in the Content Model, say through using the DOM APIs to change an element from hidden to visible, produces an equivalent change in the Frame Tree. It's important to note that all of these operations are purely data manipulations. Painting to the display itself is not yet involved at this point.

The next stage is the View Manager. With a few small exceptions that have to do with prompting the Frame Constructor to load graphics, the View Manager is the first place in the process that accesses the native OS. Delaying OS access until this point both helps Gecko to run more quickly and makes cross-platform issues easier to deal with. The View Manger is the place where Gecko figures out where on the display the data will need to be drawn. It then tells the system that that area is "invalid" and needs to be repainted. The actual painting is managed by the gfx submodule, while other low-level system operations are run through the widget submodule, which handles things like platform specific event (mouse clicks and so forth) processing loops and accessing system defaults (colors, fonts, etc.) Both gfx and widget are system specific.

If you want to take a look at the code underlying these structures, the code for the Content Model can be found in <tt>/mozilla/content</tt>, for the Frame Constructor, CSS, and Reflow in <tt>/mozilla/layout</tt>, for the View Manager in <tt>/mozilla/view</tt>, and for the DOM APIs in <tt>/mozilla/dom</tt>.

Original Document Information

리비전 소스

<p>정보의 원천, 놀이, 개인간 교류 수단으로써 웹의 중요성이 끝없이 증가하면서, HTML 포맷으로 저장된 데이터에 접근하고 보는 능력은 다양한 소프트웨어 애플리케이션을 폭넓게 대체하기 위해 점점 더 중요해지고 있다. 단순한 HTML 페이지 뷰어건 완벽한 기능의 웹 브라우저이건, HTML 기반 문서를 해석하고 그려내는 것은 수많은 상황에서 매우 중요한 기능이 됐다. 애플리케이션 개발자는 개발 시간을 최소화하면서도 애자일하고 안정성이 높은 제품을 만들기 위해, HTML을 출력하는 결정적인 기능을 어떻게 구현할지에 고민하게 되었다. Gecko, 즉 넷스케이프와 모질라 브라우저의 핵심에 있는 렌더링 엔진을 임베딩하는 것은 이런 문제에 대한 훌륭한 해결책이다.
</p>
<h2 name=".EC.99.9C_Gecko.EC.9D.B8.EA.B0.80.3F"> 왜 Gecko인가? </h2>
<p>Gecko를 임베딩하는 것은 현명한 선택이다. Gecko는 빠르고, 안정적이며 표준을 매우 잘 지키고 있다. Mozilla와 Netscape의 지원 아래서 매우 널리 배포되었으며 많은 사람들이 꾸준히 지켜보고 있다.
</p><p>Gecko는 오픈 소스이다. 다른 임베딩 브라우저 솔루션과는 달리, Gecko의 모든 소스 코드는 자유롭게 사용할 수 있으며 마음껏 수정할 수 있다. 필요한 만큼 뜯어 고칠 수 있다. 또한 현재의 라이센스에 따르면, Gecko를 독점적인 상용 제품에 컴포넌트로 사용할 수도 있다.
</p><p>Gecko는 Mozilla 프로젝트와 연관되어 있으므로, Mozilla 프로젝트에서 임베딩 작업에 도움이 되는 많은 리소스를 쉽게 얻을 수 있다. Mozilla <a class="external" href="http://www.mozilla.org">웹 사이트</a>에는 <a class="external" href="http://mozilla.org/projects/embedding/">임베딩 프로젝트 영역</a>이 있다. 또한 mozilla.dev.emobedding 뉴스그룹이 있으며, 많은 관련 뉴스그룹과 함께 임베딩 개발자들 간에 정보를 교환하는 것을 주 목적으로 하고 있다. 전체 <a class="external" href="http://lxr.mozilla.org/seamonkey">코드기반 상호 참조</a>가 가능하며, <a class="external" href="http://bugzilla.mozilla.org/">Bugzilla 버그 데이터베이스</a>를 통해 버그 제출, 버그 진행 상황 참조, 버그 수정 참여 등을 간단히 할 수 있다.
</p><p>Gecko는 바닥부터 크로스플랫폼으로 설계되었다. mozill.org에서는 직접 Wintel, MacOS 9.0과 OS X, 리눅스를 지원하고 있으며, 수많은 다른 플랫폼도 써드파티에서 지원하고 있다.
</p><p>마지막으로, Gecko를 라이센스하는 것은 로열티가 필요 없으며, 심지어 독점 저작권을 갖는 상용 제품에도 로열티없이 적용할 수 있다. "매우" 일반적으로는, 모질라가 제공하는 원본 소스코드에 대해서는 어떤 수정도 커뮤니티에 반환되어야 한다.(Gecko를 임베드하는 코드까지 반환해야하는 것은 아니다.) 즉 애플리케이션의 사용자라면 사용중인 Gecko 엔진에 해당하는 소스 코드를 언제든지 얻을 수 있어야 하며(대부분 mozilla.org 웹사이트 링크를 통해서), 애플리케이션은 명확한 방법으로 Gecko를 사용하고 있음을 공지해야 한다. (예를 들면, 제품 박스 위의 로고나 About: 페이지 등) 가능한 라이센스 방법에 대한 정확한 설명은 라이센스에 대해 유일한 법적 근거인 <a class="external" href="http://www.mozill.org/MPL/">Mozilla &amp; Nescape Public Licneses</a>에서 볼 수 있다.
</p>
<h2 name=".EC.9E.84.EB.B2.A0.EB.94.A9.EC.97.90_.ED.95.84.EC.9A.94.ED.95.9C_.EA.B2.83"> 임베딩에 필요한 것 </h2>
<p>Gecko를 임베드하기로 결정했다면, 세가지 과정을 밟아야 한다. 첫째로 코드를 얻는다. 다음으로 Gecko 코드베이스를 다루는데 사용되는 몇가지 지정 기술을 이해해야 한다. 마지막으로 추가하려는 부가적인 기능을 결정해야 한다. 이 절은 이러한 과정을 안내할 것이다.
</p>
<h3 name=".EC.BD.94.EB.93.9C_.EC.96.BB.EA.B8.B0"> 코드 얻기 </h3>
<p>이 글을 쓰는 시점에서 Gecko를 임베드하기 위한 파일을 얻는 가장 좋은 방법은 전체 Mozill 소스 트리를 다운로드해서 빌드하는 것이다. 사실 상당히 간단한 과정이다. 전체 설명과 적절한 링크는 <a href="ko/Download_Mozilla_Source_Code">Download Mozilla Source Code</a>에서 찾을 수 있다. 두번째 방법(컴포넌트에 의한 컴포넌트)은 현재 개발 중이며, 아직 베타 상태에 있다. 이 프로젝트에 대한 정보는 <a class="external" href="http://www.mozilla.org/projects/embedding/bootstrap.html">REQUIRES 기반 빌드 메카니즘</a>에서 찾을 수 있다. 그 외에, Gecko 런타임 환경(<a href="ko/GRE">GRE</a>, Gecko Runtime Environment)가 개발중에 있다. <a href="ko/GRE">GRE</a>는 단일 코어 라이브러리를 사용하는 모질라 컴포넌트 위에서 여러가지 애플리케이션을 지원하기 위한 것이다. (컴포넌트에 의한 컴포넌트를 사용하려고 생각한다면, 우선 버전과 바이너리 호환성에 대한 이슈를 잘 살펴봐야 한다. <a class="external" href="http://mozilla.org/projects/xpcom/glue/Component_Reuse.html">XPCOM 컴포넌트 재사용</a>을 살펴보면 도움이 될 것이다.)
</p><p>우선 몇가지 도구(기본으로 컴파일러, 펄 배포판, 몇몇 범용 유틸리티)를 가져와야 한다. 그런 다음 컴퓨터 환경을 설정하고, 소스를 다운로드 한다. 전체 트리를 다운로드하려 한다면, 두가지 방법이 있다. FTP에서 전체 소스 트리를 tar로 압축한 파일을 가져올 수 있다. (이것이 가장 간단한 방법이며, 확실히 컴파일이 가능한 한 방법이다. 다만 최근에 수정된 코드는 포함하지 않았을 수도 있다.) 다른 방법은 CVS에서 가장 최신의 코드를 가져오거나 변경분에 대한 업데이트를 수행하는 것이다. 소스를 가져와서 환경 설정을 적절히 끝마친 다음에는 제공된 makfile 중 적절한 것을 실행하면 된다. 각 플랫폼마다 컴파일 과정에 대한 상세한 설명이 있다.
</p><p>빌드가 끝나면 mozilla/embedding/config 디렉토리로 간다. 거기서 예제 manifest 파일을 찾을 수 있을 것이다. (파일들은 모두 이름이 "basebrowser"로 시작한다. manifest 파일은 각 플래폼마다 임베딩을 위한 개별 설정이다. 기본으로 들어있는 것은 단지 예제일 뿐이며, 당신의 목적에는 딱 들어맞지 않을 수도 있다. 하지만 예제로 시작해서 조금씩 수정해 나가면 좋을 것이다. 각 플랫폼마다 모델로 삼을 만한 예제 임베딩 프로젝트들도 있다. <a href="ko/Roll_your_own_browser_-_An_embedding_HowTo">Roll_your_own_browser_-_An_embedding_HowTo</a>를 참고하라.
</p>
<h3 name=".EC.BD.94.EB.93.9C_.EC.9E.91.EC.84.B1_.ED.99.98.EA.B2.BD_.EC.9D.B4.ED.95.B4.ED.95.98.EA.B8.B0"> 코드 작성 환경 이해하기 </h3>
<p>모질라는 처음부터 여러 플랫폼과 프로그래밍 언어에 대한 설계와 개발을 지원하는 것으로 시작됐다. 결국 여러가지 자체 프로그래밍 기술이 개발되었으며, 모두 다 객체 은폐라는 이상적인 개념을 바탕으로 두고 있다. Gecko 임베딩에는 XPCOM, XPIDL, XPConnect, 특별 문자열 클래스, XUL 등의 기술에 대한 실제적인 지식을 필요로 한다. 다음은 각 기술에 대한 간략한 소개이다. 더 자세한 정보는 mozilla.org 사이트에서 찾을 수 있다.
</p>
<h4 name="XPCOM"> XPCOM </h4>
<p>모질라 기술 중 가장 중요한 것은 <a href="ko/XPCOM">XPCOM</a>, 즉 크로스플랫폼 컴포넌트 오브젝트 모델(Cross-Platform Component Object Model)이다. XPCOM은 객체나 다른 데이터의 생성, 소유, 제거를 모질라 전체에 걸쳐 관리하는 프레임워크를 제공한다. MSCOM을 사용한 적이 있다면, 기본적으로 유사한 개념임을 느낄 것이다. 하지만 매우 큰 차이가 있다. XPCOM은 크로스플랫폼이며 단일 스레드에서 대부분 동작하도록 설계되어 있다. 또한 XPCOM와 MSCOM은 현재로써는 아직 호환되지 않는다.
</p>
<h5 name=".EC.9D.B8.ED.84.B0.ED.8E.98.EC.9D.B4.EC.8A.A4"> 인터페이스 </h5>
<p>XPCOM의 핵심은 인터페이스라는 개념이다. 인터페이스는 특정 기증과 연관된 메소드, 속성, 관련 상수의 집합을 기술한 것일 뿐이다. 실제 기능을 구현하는 클래스와는 전혀 별개이다. 인터페이스는 계약의 역할을 한다. 특정 인터페이스를 지원하는 객체는 인터페이스에 기술된 서비스를 수행한다는 약속의 의미이다. 인터페이스를 최대한 중립적으로 유지할 수 있도록 IDL(Interface Definition Language)라는 별도의 언어를 사용해서 기술한다. 인터페이스 파일은 일반적으로 .idl이라는 확장자를 갖는다. 인터페이스의 기능을 지정할 뿐만 아니라 인터페이스의 IID도 지정한다. IID는 인터페이스를 지정할 때 사용하는 세계에서 유일한 번호이다.
</p><p>Gecko 내에서 이루어지는 통신의 대부분은 추상 구조체를 거친다. (규약에 따라 추상 구조체의 이름은 <code>nsISomething</code>의 형식을 따른다.)
</p>
<pre>//이거야
void ProcessSample(nsISample* aSample) {
	aSample-&gt;Poke("Hello"); 
//이건 아니야
void ProcessSample(nsSampleImpl* aSample) {
	aSample-&gt;Poke("hello"); 
</pre>
<h5 name=".40status_FROZEN"> @status FROZEN </h5>
<p>XPCOM의 추상화 수준으로 인해 시스템이 매우 큰 유연성을 갖추게 됐다.
구현은 필요에 따라 얼마든지 변경할 수 있다. 하지만 최소한 인터페이스 자체는
고정된 채로 유지해야 한다. 모질라의 초기 설계와 개발 기간 동안에는 인터페이스는
다소 유동적인 것이었지만, 프로젝트가 성숙되면서 점점 더 많은 인터페이스가
FROZEN으로 표시됐다. FROZEN으로 표시된 인터페이스는 향후 변경되지 않음을
보장한다는 의미이다.
</p><p>임베딩 관련된 대부분의 주요 인터페이스가 FROZEN으로 표시되긴 했지만,
인터페이스를 사용하기 전에 확인해보는 것이 좋다. 인터페이스의 상태는
.idl 파일의 주석에 나열된다. 얼려진 인터페이스(frozen interface)는
<code>@status FROZEN</code>라는 표시가 달린다.
모질라 상호 참조 도구를 사용해서 <a class="external" href="http://lxr.mozilla.org/seamonkey/search?string=%40status+FROZEN">얼려진 인터페이스를 검색</a>할 수도 있다.
얼려지지 않은 상태의 인터페이스는 언제든지 변경될 가능성이 있다.
얼리는 과정에 대한 자세한 정보는 <a class="external" href="http://mozilla.org/embedding/">임베딩 프로젝트 페이지</a>를 참고하라.
</p><p>인터페이스가 얼려지고 나면 해당 인터페이스는
<a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi.html">Gecko 임베딩 API 참조</a>에 추가된다.
</p>
<h5 name="nsISupports"> nsISupports </h5>
<p>한 객체가 하나 이상의 인터페이스를 지원할 수 있다. 실제로는 모든 객체는 최소한 두 개의 인터페이스를 지원해야 한다. 하나는 실제 객체의 역할이 되는 무언가이고, 다른 하나는 범용적인 목적으로 사용되는 <code>nsISupports</code>이다. 다르게 말하자면 <code>nsISupports</code>는 모든 XPCOM 인터페이스의 조상이다. 모든 인터페이스는 <code>nsISupports</code>로부터 상속되며, 대부분은 직접 상속받는다. <code>nsISupports</code>는 두가지 주요 기능을 갖는다. 런타임 타입 발견과 객체 생명주기 관리이다. MSCOM의 IUnknown과 동일한 역할을 한다.
</p><p>모든 객체가 다중 인터페이스를 지원하기 때문에, 한 인터페이스에 대한 포인터를 가진 상태에서 해당 객체가 당장 필요한 기능을 제공하는 다른 인터페이스를 지원하는지 알아낼 수 있다. 첫번째 <code>nsISupports</code> 메소드인 <code>QueryInterface()</code>는 다음과 같은 질문을 수행한다. "나는 이 객체가 A 타입임(인터페이스 A를 지원함)을 알고 있다. 그런데 타입 B이기도 한가?(인터페이스 B도 지원하는가?)"
</p><p>만일 그렇다면 <code>QueryInterface()</code>는 새로 요청된 인터페이스로 연결된 포인터를 반환한다.
</p>
<pre>void ProcessSample(nsISample* aSample) {
	nsIExample *example;
	nsresult rv;
	rv = aSample-&gt;QueryInterface(NS_GET_IID(nsIExample),(void **)&amp;example); 
	if (NS_SUCCEEDED(rv)) {
		example-&gt;DoSomeOperation();
		NS_RELEASE(example); // Release호출을 위해 매크로를 사용 
	} 
} 
</pre>
<p>XPCOM은 간접적인 방법(컴포넌트 관리자)을 사용해서 객체의 인스턴스를 생성하기 때문에, 같은 객체에 대한 다중 포인터(각각 다양한 인터페이스로 연결됨)가 존재할 수 있으며, 포인터가 가리키는 모든 객체를 호출자가 정확하게 추적하기 어려워질 수 있다. 객체가 필요하지 않은 상황에서도 남아있게 되서 메모리 누수가 발생하거나, 필요한 객체가 삭제되는 바람에 댕글링 포인터가 나타날 수도 있다. <code>nsISupports</code>의 다른 두 메소드 <code>AddRef()</code>와 <code>Release()</code>는 이런 이슈를 다루기 위해 설계된 것이다. 포인터가 변수에 입력될 때마다<code>AddRef()</code>가 호출되어 내부 카운터가 증가한다. 포인터가 풀려날 때마다 <code>Release()</code>가 호출되어 내부 카운터가 감소한다. 카운터가 0이 되면, 객체에 대한 포인터가 없으며 객체를 안전하게 삭제할 수 있다. 객체의 수명에 대한 제어는 객체 내부에 있는 것이다. 이와 같은 과정을 자동화할 수 있도록 돕는 유틸리티인 XPCOM "스마트" 포인터<a href="#nsCOMPtr">nsCOMPtr</a>에 대한 정보를 참고하라.
</p>
<h5 name=".EA.B0.9D.EC.B2.B4_.EC.83.9D.EC.84.B1"> 객체 생성 </h5>
<p>XPCOM에서는 객체의 인스턴스 생성조차도 간접적인 절차를 거친다.
인터페이스가 GUID(Globally Unique ID)인 IID를 갖는 것처럼, XPCOM 클래스도 자신만의 GUID인 CID를 갖는다. 또는 문자 기반 ID인 Contract ID로 참조하기도 한다. 두가지 ID 중 하나를 객체를 생성하는 영속적인 XPCOM 컴포넌트인 "컴포넌트 관리자"의 메소드에 전달한다. 새로운 클래스 라이브러리(XPCOM에서는 모듈이라고 부른다)를 시스템에 처음 배치할 때, 라이브러리는 자기 자신을 컴포넌트 관리자에 등록하며, 컴포넌트 관리자는 클래스(ID로 참조)와 클래스가 포함된 라이브러리를 매핑하는 레지스트리를 관리한다.
</p><p>싱글턴 객체가 제공하는 몇가지 영속적인 서비스는 컴포넌트 관리자와 함께 서비스 관리자가 생성하고 제어한다. 컴포넌트 관리자 자체도 영속적인 서비스의 예시 중 하나이다.
</p>
<h5 name=".EC.9A.94.EC.95.BD"> 요약 </h5>
<p>XPCOM에 포함된 기능은 추상 인터페이스로 기술되며, 시스템 요소 간의 대부분의 통신은
인터페이스를 거쳐서 이루어진다. 반면, 인터페이스를 구현하는 하부 객체들은
교차색인 레지스트리에 기반한 컴포넌트 관리자에 의해 간접적으로 생성된다.
</p><p>모든 인터페이스가 공유하는 기능 한가지는 런타임에서 하부 객체에게 어떤 다른 인터페이스를
구현하고 있는지 질의하는 기능이다. 인터페이스는 고정되어 변하지 않는다는 가정이 있는
것이지만, 현재 모질라 코드베이스에서는 <code>FROZEN</code>으로 선언된
인터페이스들만이 크게 변경되지 않을 것임을 보장한다. 객체 생명주기 관리는
객체 내에 들어있는 자신에게로 향하는 포인터의 개수를 추적하는 내부 카운터를 통해 이루어진다.
객체를 사용하는 클라이언트가 해야 할 일은 카운터를 올리거나 내리는 것 뿐이다.
내부 카운터가 0에 도달하면 객체는 자기자신을 삭제한다.
</p>
<h5 name="nsCOMPtr"> nsCOMPtr </h5>
<p>하지만 <code>AddRef()</code>와 <code>Release()</code>를 적절한 때에 호출하는 것을
가끔 잊어버릴 수도 있다. 이런 과정을 더 쉽고 확실히 화기 위해 XPCOM은 내장 "스마트"
포인터인 <code>nsCOMPtr</code>을 제공한다. 이 포인터는 <code>AddRef()</code>와 <code>Release()</code> 호출을 처리한다. 대신 <code>nsCOMPtr</code>을 사용하면 코드를 더 명확하고 효율적으로 만들 수 있다. 스마트 포인터에 대한 추가 정보는 "<a class="external" href="http://www.mozilla.org/projects/xpcom/nsCOMPtr.html">The Complete nsCOMPtr User's Manual</a>"을 참고하라.
</p><p>모질라는 수많은 내장 매크로(규약에 따라 코드 내에서 모두 대문자로 작성됨)나 <code>nsCOMPtr</code>과 같은 유틸리티를 제공해서 XPCOM으로 코딩하는 과정을 더 쉽게 만들어 준다.
이들 중 대부분은 다음 파일에서 찾을 수 있다.
</p><p><tt>nsCom.h</tt>, <tt>nsDebug.h</tt>, <tt>nsError.h</tt>, <tt>nsIServiceManager.h</tt>, <tt>nsISupportsUtils.h</tt>
</p><p>모질라는 메모리 사용량 추적 기능 같은 개발 도구까지 제공한다. 이런 도구에 대한 정보는 http://www.mozilla.org/performance/ 에서 찾을 수 있다.
</p>
<h5 name=".EC.B0.B8.EA.B3.A0.EC.9E.90.EB.A3.8C"> 참고자료 </h5>
<p>XPCOM에 대한 참고자료는 일반적으로 <a href="ko/XPCOM">XPCOM</a>에서 찾을 수 있다.
XPCOM 컴포넌트 작성에 대한 개략적인 내용은 오릴리 서적인 <i><a class="external" href="http://books.mozdev.org/chapters/ch08.html">Creating Applications with Mozilla</a></i>의
8장에서 참고할 수 있다. 전체 내용이 XPCOM 관련된 책인 <i><a href="ko/Creating_XPCOM_Components">Creating XPCOM Components</a></i>도 있다. Don Box가 저술한 <i>Essential COM</i>에서는 COM 시스템의 기반 로직에 대해
더욱 상세히 설명하고 있다. 비록 MSCOM에 대해 초점을 맞춘 책이긴 하지만, 객체 모델 등을
사용할 때 필요한 핵심 원리를 이해하하기에 매우 훌륭한 배경지식을 제공한다.
</p>
<h4 name="XPIDL"> XPIDL </h4>
<p>인터페이스는 XPIDL(Cross Platform Interface Definition Language)로
작성된 추상 클래스이다. 여전히 인터페이스에서 제공할 기능은 몇몇 정규 프로그래밍 언어로
작성하는 것이 유용하다. XPIDL 컴파일러가 이런 역할을 한다. 인터페이스를 .idl 파일에
정의하면 XPIDL 컴파일러가 정의된 인터페이스를 처리한다.
</p><p>컴파일러는 여러가지 출력이 가능하지만, 일반적으로는 두가지 출력을 사용한다.
인터페이스의 C++ 구현을 위해 사용하며 주석달린 템플릿을 포함하는 C++ .h 파일이 그 중
하나이다. 다른 하나는 XPConnect가 사용할 타입 라이브러리 정보를 포함하는 XPT 파일이다.
XPConnect는 JavaScript에서 인터페이스를 사용할 수 있도록 한다. <a href="ko/XPIDL">XPIDL</a>의
문법(간단한 C 스타일 언어)에 대한 자료와 <a href="ko/XPIDL/xpidl">컴파일러</a> 사용법이 참고하라.
</p>
<h4 name="XPConnect.EC.99.80_XPT_.ED.8C.8C.EC.9D.BC"> <a href="ko/XPConnect">XPConnect</a>와 XPT 파일 </h4>
<p><a href="ko/XPConnect">XPConnect</a>는 <a href="ko/JavaScript">JavaScript</a>로 작성된 코드에 접근하거나, C++로 작성된
XPCOM 컴포넌트를 다룰 수 있도록 하는 <a href="ko/XPCOM">XPCOM</a> 모듈이다. XPConnect를 사용하면,
XPCOM 인터페이스를 제공하거나 사용하는 양쪽 컴포넌트가 상대방이 어떤 언어로 작성됐는지
신경쓸 필요가 없다.
</p><p>인터페이스를 XPIDL 컴파일러에 적용하면, XPT 또는 타입 라이브러리 파일을 생성한다.
XPConnect는 XPT 파일로부터 얻은 정보를 사용해서 C++ 객체와 JavaScript 객체 간의
통신을 XPCOM 인터페이스를 통해서 투명하게 구현한다. 그러므로 C++로만 개발하더라도
XPCOM 인터페이스를 생성해서 코드에 포함시키는 것이 매우 중요하다. 브라우저의
특정 부분만 JS로 구현된 것이 아니라, 향후에도 누군가 JS 기반 코드를 사용해서 당신이
작성한 컴포넌트와 상호작용하도록 할 수도 있다.
</p><p>현재 모질라에서 XPConnect는 C++와 JS 간의 상호작용을 가능하게 한다.
다른 언어(Python 등)에서 접근할 수 있도록 하는 모듈은 별도로 개발 중이다.
</p>
<h4 name="String_.ED.81.B4.EB.9E.98.EC.8A.A4"> String 클래스 </h4>
<p>웹 브라우징은 일반적으로 많은 양의 문자열 처리를 필요로 한다. 모질라는 문자열을 처리하고
효율적으로 빠르게 출력하기 위한 C++ 클래스 라이브러리를 개발해왔다. 모질라는 객체 간 통신을 간단하게 하고 에러를 줄이기 위해 인터페이스, 즉 추상 클래스를 사용한다.
같은 이유로 String 클래스
계층도 <code>nsAString</code>, <code>nsASingleFragmentString</code>, <code>nsAFlatString</code> 등의 몇가지 추상 클래스를 앞세운다.
(이 클래스들은 2바이트 문자열을 참조한다. <code>nsACString</code>로 시작하는
1바이트 문자열을 참조하는 계층이 동일한 구조로 별도로 존재한다.) 
<code>nsAString</code>은 문자로 구성된 문자열이라는 것만 보장한다.
<code>nsASingleFragmentString</code>는 문자들이 한 버퍼에 저장되어 있음을 보장한다.
<code>nsAFlatString</code>는 문자들이 하나의 null로 끝나는 버퍼에 들어있음을 보장한다.
하부에는 구상 클래스가 있지만, 되도록이면 가능한한 가장 추상적인 타입을 사용하는 것이 좋다.
예를 들어 문자열 접합(concatenation)은 포인터를 사용해서 가상으로 이루어질 수 있으며, 그 결과는 다른 문자열처럼 사용될 수 있는 nsAString이다. 덕분에 메모리 할당과 복사를 하지 않아도 된다. 더 자세한 정보는 "<a href="ko/XPCOM/Strings">Guide to the Mozilla string classes</a>"를 참고하라.
</p>
<h4 name="XUL.2FXBL"> XUL/XBL </h4>
<p>이 마지막 모질라 기술은 애플리케이션의 UI를 어떻게 만들 것이냐에 따라 선택해서 사용할 수 있다.
<a href="ko/XUL">XUL</a>은 모질라의 매우 유연한 XML UI 언어이다. 매우 다양한 플랫폼 독립적인 위젯을 제공하며 위젯들을 사용해서 UI를 작성할 수 있다. 넷스케이프와 모질라는 모두 XUL을 인터페이스로
사용하지만, 모든 임베딩 애플리케이션 개발자들이 XUL을 사용하는 것은 아니다.
XBL(eXtensible Binding Language)은 XUL의 XML 요소에 동작을 추가하는 데 사용할 수 있다.
XUL에 대한 더 자세한 정보는 <a class="external" href="http://www.mozilla.org/xpfe/xulref/">XUL Programmer's Reference</a>에서, <a href="ko/XBL">XBL</a>은 <a href="ko/XBL/XBL_1.0_Reference">XBL:XBL_1.0_Reference</a>에서 찾을 수 있다. <a class="external" href="http://www.xulplanet.com/">XULPlanet</a>에도 XUL에 관련된 좋은 정보가 많다.
</p>
<h3 name="Choosing_Additional_Functionalities"> Choosing Additional Functionalities </h3>
<p>As of this writing (8/19/02), Gecko is a partially modularized rendering engine. Some functionalities beyond basic browsing are always embedded with Gecko, and, as a result of certain architectural decisions, always will be; some are at present always embedded with Gecko, but may, at some point in the future, be separable; and some are now available purely as options. The following table describes the present status of these additional functionalities:
</p>
<table>
<tbody><tr>
<th> Functions
</th><th> Status Now
</th><th> Status in Future
</th></tr>
<tr>
<td> FTP support
</td><td> Optional
</td><td>
</td></tr>
<tr>
<td> HTTPS support
</td><td> Optional
</td><td>
</td></tr>
<tr>
<td> International character support
</td><td> Optional
</td><td>
</td></tr>
<tr>
<td> XUL support
</td><td> Required
</td><td> Probably optional
</td></tr>
<tr>
<td> Network support
</td><td> Required
</td><td> Maybe optional
</td></tr>
<tr>
<td> JavaScript support
</td><td> Required
</td><td> Maybe optional
</td></tr>
<tr>
<td> CSS support
</td><td> Required
</td><td> Always required
</td></tr>
<tr>
<td> DOM support
</td><td> Required
</td><td> Probably always
</td></tr>
<tr>
<td> XML support
</td><td> Required
</td><td> Probably always
</td></tr></tbody></table>
<p>At this time embedding Mozilla's editor along with the rendering engine Gecko is an uncertain proposion, although the situation continues to improve. For more information on the status of the embeddable editor, see http://www.mozilla.org/editor/Editor_Embedding_Guide.html.
</p>
<h2 name="What_Gecko_Provides"> What Gecko Provides </h2>
<p>The following is a description of some of the interfaces most commonly used in embedding Gecko. It is by no means an exhaustive list of the available interfaces. The interfaces in this section are on classes provided by Mozilla. There is also a set of interfaces for which Gecko expects the embedder to provide the implementation. A sample of those are covered in the next section.
</p>
<h3 name="Initialization_and_Teardown"> Initialization and Teardown </h3>
<p>There are two C++ only functions which serve to initalize and terminate Gecko. The initialization function (<a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi2.html#1099700">NS_InitEmbedding</a>) must be called before attempting to use Gecko. It ensures XPCOM is started, creates the component registry if necessary, and starts global services. The shutdown function (<a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi2.html#1101115">NS_TermEmbedding</a>) terminates the Gecko embedding layer, ensuring that global services are unloaded, files are closed and XPCOM is shut down.
</p>
<h3 name="nsIWebBrowser"> <a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi4.html">nsIWebBrowser</a> </h3>
<p>Use of this interface during initialization allows embedders to associate a new <code>nsWebBrowser</code> instance (an object representing the "client-area" of a typical browser window) with the embedder's chrome and to register any listeners. The interface may also be used at runtime to obtain the content DOM window and from that the rest of the DOM.
</p><p>The <a class="external" href="http://xulplanet.com/references/xpcomref/ifaces/nsIWebBrowser.html">XULPlanet <code>nsWebBrowser</code> reference</a> also has a lot of useful information on this class.
</p>
<h3 name="nsIWebBrowserSetup"> <a class="external" href="http://www.mozilla.org/projects/embedding/embedapiref/embedapi10.html">nsIWebBrowserSetup</a> </h3>
<p>This interface is used to set basic properties (like whether image loading will be allowed) before the browser window is open.
</p>
<h3 name="nsIWebNavigation"> <a class="external" href="http://www.xulplanet.com/references/xpcomref/ifaces/nsIWebNavigation.html">nsIWebNavigation</a> </h3>
<p>The <code>nsIWebNavigation</code> interface is used to load URIs into the web browser instance and provide access to session history capabilities - such as back and forward. As of June 6, 2006, this interface is not yet frozen.
</p>
<h3 name="nsIWebBrowserPersist"> <a class="external" href="http://www.xulplanet.com/references/xpcomref/ifaces/nsIWebBrowserPersist.html">nsIWebBrowserPersist</a> </h3>
<p>The <code>nsIWebBrowserPersist</code> interface allows a URI to be saved to file. As of June 6, 2006, this interface is not yet frozen.
</p>
<h3 name="nsIBaseWindow"> <a class="external" href="http://www.xulplanet.com/references/xpcomref/ifaces/nsIBaseWindow.html">nsIBaseWindow</a> </h3>
<p>The <code>nsIBaseWindow</code> interface describes a generic window and basic operations (size, position, window title retrieval, etc.) that can be performed on it. As of June 6, 2006, this interface is not yet frozen.
</p>
<h3 name="nsISHistory"> <a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi58.html">nsISHistory</a> </h3>
<p>The <code>nsISHistory</code> interface provides access to session history information and allows that information to be purged.
</p>
<h3 name="nsIWebBrowserFind"> <a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi14.html">nsIWebBrowserFind</a> </h3>
<p>The <code>nsIWebBrowserFind</code> interface controls the setup and execution of text searches in the browser window.
</p>
<h2 name="What_You_Provide"> What You Provide </h2>
<p>The following is a description of some of the more common embedder-provided interfaces used in embedding Gecko. It is by no means an exhaustive list of the available interfaces.
</p>
<h3 name="nsIWebBrowserChrome"> <a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi6.html">nsIWebBrowserChrome</a> </h3>
<p>The <code>nsIWebBrowserChrome</code> interface corresponds to the top-level, outermost window containing an embedded Gecko web browser. You associate it with the WebBrowser through the <code>nsIWebBrowser</code> interface. It provides control over window setup and whether or not the window is modal. It must be implemented.
</p>
<h3 name="nsIEmbeddingSiteWindow"> <a class="external" href="http://www.mozilla.org/projects/embedding/embedapiref/embedapi12.html">nsIEmbeddingSiteWindow</a> </h3>
<p>The <code>nsIEmbeddingSiteWindow</code> interface provides Gecko with the means to call up to the host to resize the window, hide or show it and set/get its title. It must be implemented.
</p>
<h3 name="nsIWebProgressListener"> <a href="ko/NsIWebProgressListener">nsIWebProgressListener</a> </h3>
<p>The <code>nsIWebProgressListener</code> interface provides information on the progress of loading documents. It is added to the WebBrowser through the <code>nsIWebBrowser</code> interface. It must be implemented. As of this writing (8/19/02), it is not frozen.
</p>
<h3 name="nsISHistoryListener"> <a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi59.html">nsISHistoryListener</a> </h3>
<p>The <code>nsISHistoryListener</code> interface is implemented by embedders who wish to receive notifications about activities in session history. A history listener is notified when pages are added, removed and loaded from session history. It is associated with Gecko through the <code>nsIWebBrowser</code> interface. Implementation is optional.
</p>
<h3 name="nsIContextMenuListener"> <a class="external" href="http://mozilla.org/projects/embedding/embedapiref/embedapi5.html">nsIContextMenuListener</a> </h3>
<p>The <code>nsIContextMenuListener</code> interface is implemented by embedders who wish to receive notifications for context menu events, i.e. generated by a user right-mouse clicking on a link. It should be implemented on the web browser chrome object associated with the window for which notifications are required. When a context menu event occurs, the browser will call this interface if present. Implementation is optional.
</p>
<h3 name="nsIPromptService"> <a href="ko/NsIPromptService">nsIPromptService</a> </h3>
<p>The <code>nsIPromptServices</code> interface allows the embedder to override Mozilla's standard prompts: alerts, dialog boxes, and check boxes and so forth. The class that implements these embedder specific prompts must be registered with the Component Manager using the same CID and contract ID that the Mozilla standard prompt service normally uses. Implementation is optional. As of this writing (8/19/02), this interface is not frozen.
</p>
<h2 name="Common_Embedding_Tasks"> Common Embedding Tasks </h2>
<p>The following is a series of code snippets (taken from MFCEmbed, the Windows based embedding Gecko sample) which demonstrate very briefly implementation associated with common embedding tasks.To see all the files associated with this sample, go to http://lxr.mozilla.org/seamonkey/source/embedding/tests/mfcembed/. There are also Linux- and Mac OS-based examples.
</p>
<h3 name="Gecko_setup"> Gecko setup </h3>
<p>The Gecko embedding layer must be initialized before you can use Gecko. This ensures XPCOM is started, creates the component registry if necessary, and starts global services. There is an equivalent shutdown procedure.
</p><p>Note that the embedding layer is started up by passing it two parameters. The first indicates where the executable is stored on the file system (<code>nsnull</code> indicates the working directory). The second indicates the file location object "provider" that specifies to Gecko where to find profiles, the component registry preferences, and so on.
</p>
<pre>nsresult rv;
rv = NS_InitEmbedding(nsnull, provider);
if(NS_FAILED(rv))
{
ASSERT(FALSE);
return FALSE;
} 
</pre>
<h3 name="Creating_a_browser_instance"> Creating a browser instance </h3>
<p>The embedder-provided BrowserView object calls its method <code>CreateBrowser()</code>. Each browser object (a webbrowser) represents a single browser window. Notice the utility directive <code>do_CreateInstance()</code> and the use of macros.
</p>
<pre>//Create an instance of the Mozilla embeddable browser
 
HRESULT CBrowserView::CreateBrowser() 
{
// Create a web shell  
nsresult rv;
mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &amp;rv);
if(NS_FAILED(rv))
return rv; 
</pre>
<p>Once the <code>nsWebBrowser</code> object is created the application uses <code>do_QueryInterface()</code> to load a pointer to the <a class="external" href="http://www.xulplanet.com/references/xpcomref/ifaces/nsIWebNavigation.html">nsIWebNavigation</a> interface into the <code>mWebNav</code> member variable. This will be used later for web page navigation.
</p>
<pre>rv = NS_OK;
mWebNav = do_QueryInterface(mWebBrowser, &amp;rv);
if(NS_FAILED(rv))
return rv; 
</pre>
<p>Next the embedder-provided <code>CBrowserImpl</code> object is created. Gecko requires that some interfaces be implemented by the embedder so that Gecko can communicate with the embedding application. See the <a href="#What_You_Provide">What You Provide Section</a>. In the sample, <code>CBrowserImpl</code> is the object that implements those required interfaces. It will be passed into the <code>SetContainerWindow()</code> call below.
</p>
<pre>mpBrowserImpl = new CBrowserImpl();
if(mpBrowserImpl == nsnull)
return NS_ERROR_OUT_OF_MEMORY; 
</pre>
<p>The <code>mWebBrowser</code> interface pointer is then passed to the <code>CBrowserImpl</code> object via its <code>Init()</code> method. A second pointer to the platform specific <code>BrowserFrameGlue</code> interface is also passed in and saved. The <code>BrowserFrameGlue</code> pointer allows <code>CBrowserImpl</code> to call methods to update status bars, progress bars, and so forth.
</p>
<pre>mpBrowserImpl-&gt;Init(mpBrowserFrameGlue, mWebBrowser);
mpBrowserImpl-&gt;AddRef(); 
</pre>
<p>Next the embedder-supplied chrome object is associated with the webbrowser. Note the use of an <code>nsCOMPtr</code>.
</p>
<pre>mWebBrowser-&gt;SetContainerWindow
	(NS_STATIC_CAST(nsIWebBrowserChrome*, mpBrowserImpl)); 
nsCOMPtr&lt;nsIWebBrowserSetup&gt;setup(do_QueryInterface(mWebBrowser));  
if (setup) 
	setup-&gt;SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER,PR_TRUE); 
</pre>
<p>Then, the real webbrowser window is created.
</p>
<pre>rv = NS_OK;
mBaseWindow = do_QueryInterface(mWebBrowser, &amp;rv);
if(NS_FAILED(rv))
return rv; 
</pre>
<h3 name="Binding_a_window"> Binding a window </h3>
<p>Basic location information is passed in.
</p>
<pre>RECT rcLocation;
GetClientRect(&amp;rcLocation);
if(IsRectEmpty(&amp;rcLocation)) 
{
	rcLocation.bottom++;
	rcLocation.top++;
}
rv = mBaseWindow-&gt;InitWindow(nsNativeWidget(m_hWnd), 
		nsnull,0, 0, rcLocation.right - rcLocation.left, 
		rcLocation.bottom - rcLocation.top);
rv = mBaseWindow-&gt;Create(); 
</pre>
<p>Note the <code>m_hWnd</code> passed into the call above to <code>InitWindow()</code>. (<code>CBrowserView</code> inherits the <code>m_hWnd</code> from <code>CWnd</code>). This <code>m_hWnd</code> will be used as the parent window by the embeddable browser.
</p>
<h3 name="Adding_a_listener"> Adding a listener </h3>
<p>The <code>BrowserImpl</code> object is added as an <a href="ko/NsIWebProgressListener">nsIWebProgressListener</a>. It will now receive progress messages. These callbacks will be used to update the status/progress bars.
</p>
<pre>nsWeakPtr weakling
	(dont_AddRef(NS_GetWeakReference(NS_STATIC_CAST(nsIWebProgressListener*, 
			mpBrowserImpl))));
void mWebBrowser-&gt;AddWebBrowserListener(weakling, NS_GET_IID(nsIWebProgressListener)); 
</pre>
<p>Finally the webbrowser window is shown.
</p>
<pre>mBaseWindow-&gt;SetVisibility(PR_TRUE);
</pre>
<h3 name="Using_session_history_to_navigate"> Using session history to navigate </h3>
<p>The pointer to <a class="external" href="http://www.xulplanet.com/references/xpcomref/ifaces/nsIWebNavigation.html">nsIWebNavigation</a> saved above is used to move back through session history.
</p>
<pre>void CBrowserView::OnNavBack() 
{
if(mWebNav)
	mWebNav-&gt;GoBack();
} 
</pre>
<h2 name="Appendix:_Data_Flow_Inside_Gecko"> Appendix: Data Flow Inside Gecko </h2>
<p>While it isn't strictly necessary for embedders to understand how Gecko does what it does, a brief overview of the main structures involved as Gecko puts bits on a display may be helpful.
</p><p><img alt="Image:EmbeddingBasicsa.gif" src="File:ko/Media_Gallery/EmbeddingBasicsa.gif">
</p><p>HTML data comes into Gecko either from the network or a local source. The first thing that happens is that it is parsed, using Gecko's own HTML parser. Then the Content Model arranges this parsed data into a large tree. The tree is also known as the "Document" and its structure is based on the W3C Document Object Model. Any use of DOM APIs manipulates the data in the Content Model.
</p><p>Next the data is put into frames using CSS and the Frame Constructor. A frame in this sense (which is not the same thing as an HTML frame) is basically an abstract box within which a DOM element will be displayed. This process produces a Frame Tree, which, like the Content Model, is a tree of data, but this time focused not on the logical relationship among the elements but on the underlying calculations needed to display the data. In the beginning a frame has no size. Using CSS rules specifying how the elements of the DOM should look when they are displayed, including information like font type or image size, the eventual size of each frame is calculated. Because the same data may need to be displayed in different ways -- to a monitor and to a printer, for example -- a particular Content Model may have more than one Frame Tree associated with it. In such a case, each individual Frame Tree would belong to a different "presentation" mode.
</p><p>Calculations continue as new information flows into the system using a process called <b>reflow</b>. As information in the Frame Tree changes, the section of the Frame Tree involved is marked "dirty" by the Frame Constructor. Reflow repeatedly steps through the tree, processing every "dirty" item it encounters until all the items it encounters are "clean". Every item in the Frame Tree has a pointer back to its corresponding item in the Content Model. A change in the Content Model, say through using the DOM APIs to change an element from hidden to visible, produces an equivalent change in the Frame Tree. It's important to note that all of these operations are purely data manipulations. Painting to the display itself is not yet involved at this point.
</p><p>The next stage is the View Manager. With a few small exceptions that have to do with prompting the Frame Constructor to load graphics, the View Manager is the first place in the process that accesses the native OS. Delaying OS access until this point both helps Gecko to run more quickly and makes cross-platform issues easier to deal with. The View Manger is the place where Gecko figures out where on the display the data will need to be drawn. It then tells the system that that area is "invalid" and needs to be repainted. The actual painting is managed by the gfx submodule, while other low-level system operations are run through the widget submodule, which handles things like platform specific event (mouse clicks and so forth) processing loops and accessing system defaults (colors, fonts, etc.) Both gfx and widget are system specific.
</p><p>If you want to take a look at the code underlying these structures, the code for the Content Model can be found in <tt>/mozilla/content</tt>, for the Frame Constructor, CSS, and Reflow in <tt>/mozilla/layout</tt>, for the View Manager in <tt>/mozilla/view</tt>, and for the DOM APIs in <tt>/mozilla/dom</tt>. 
</p>
<div class="originaldocinfo">
<h2 name="Original_Document_Information"> Original Document Information </h2>
<ul><li> Author(s): <a class="external" href="mailto:jeev@netscape.com">Ellen Evans</a>
</li><li> Last Updated Date: August 19, 2002
</li><li> Copyright Information: Copyright (C) <a class="external" href="mailto:jeev@netscape.com">Ellen Evans</a>
</li></ul>
</div>
Revert to this revision