![]() |
Analysis of marbrowLet's analyze marbrow !! On this sectiion, I analyze codes of marbrow in practice.
|
void main( void )
{
DoInitialize();
DoEventLoop();
DoTerminate();
}
|
Initializing/Terminating process 
This initializes the whole of the program. This initializes Toolbox, menu bar, apple event and embedding and checks the environment.
void DoInitialize( void )
{
InitToolbox();
CheckEnviron();
SetThemeCursor( kThemeWatchCursor );
InitMenubar();
InitAppleEvent();
InitWebShell();
#if DEBUG_WMNG
DumpWmng();
#endif /* DEBUG_WMNG */
SetThemeCursor( kThemeArrowCursor );
}
|
By InitializeMacToolbox() of nsStdLib.shlb, Toolbox is initialized.
static void InitToolbox( void )
{
InitializeMacToolbox();
setbuf(stdout,0);
gScriptCode = IntlScript();
if( !gMouseRgn ){
gMouseRgn = NewRgn();
}
}
|
By NS_InitEmbedding(), embedding is initialized. Because character code setting can be changed by menu, the font sizes except English are also set.
static nsresult InitWebShell( void )
{
// Get the directory which contains the mozilla parts
// In this case it is the app directory but it could
// be anywhere (an existing install of mozilla)
nsresult rv;
ProcessSerialNumber psn;
ProcessInfoRec processInfo;
FSSpec appSpec;
nsCOMPtr<nsILocalFileMac> macDir;
nsCOMPtr<nsILocalFile> appDir
// If this ends up being NULL, default is used
// Get App Directory
if (!::GetCurrentProcess(&psn)) {
processInfo.processInfoLength = sizeof(processInfo);
processInfo.processName = NULL;
processInfo.processAppSpec = &appSpec;
if (!::GetProcessInformation(&psn, &processInfo)) {
// Turn the FSSpec of the app into an FSSpec of the app's directory
::FSMakeFSSpec(appSpec.vRefNum, appSpec.parID, "\p", &appSpec);
// Make an nsILocalFile out of it
rv = NS_NewLocalFileWithFSSpec(&appSpec
PR_TRUE, getter_AddRefs(macDir));
if (NS_SUCCEEDED(rv))
appDir = do_QueryInterface(macDir);
}
}
// Init Embedding
rv = NS_InitEmbedding(appDir, nsnull);
// Make Pref Directory
nsMPFileLocProvider *locationProvider = new nsMPFileLocProvider;
NS_ENSURE_TRUE(locationProvider, NS_ERROR_FAILURE);
nsCOMPtr<nsIFile> rootDir;
rv = NS_GetSpecialDirectory(NS_MAC_PREFS_DIR, getter_AddRefs(rootDir));
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
rv = locationProvider->Initialize(rootDir, "marbrow");
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
// Init Pref
NS_WITH_SERVICE(nsIPref, prefs, kPrefCID, &rv);
if( NS_SUCCEEDED(rv) ){
prefs->ResetPrefs(); // Needed because things read default prefs during startup
prefs->ReadUserPrefs();
// HACK ALERT: Since we don't have prefs UI, reduce the font size here by hand
prefs->SetIntPref("font.size.variable.x-western", 12);
prefs->SetIntPref("font.size.fixed.x-western", 9);
prefs->SetIntPref("font.size.variable.x-central-euro", 12);
prefs->SetIntPref("font.size.fixed.x-central-euro", 9);
prefs->SetIntPref("font.size.variable.x-mac-roman", 12);
prefs->SetIntPref("font.size.fixed.x-mac-roman", 9);
prefs->SetIntPref("font.size.variable.ja", 12);
prefs->SetIntPref("font.size.fixed.ja", 9);
prefs->SetIntPref("font.size.variable.ko", 12);
prefs->SetIntPref("font.size.fixed.ko", 9);
prefs->SetIntPref("font.size.variable.zh", 12);
prefs->SetIntPref("font.size.fixed.zh", 9);
prefs->SetIntPref("font.size.variable.zh-cn", 12);
prefs->SetIntPref("font.size.fixed.zh-cn", 9);
prefs->SetIntPref("font.size.variable.zh-tw", 12);
prefs->SetIntPref("font.size.fixed.zh-tw", 9);
prefs->SavePrefFile();
}else{
NS_ASSERTION(PR_FALSE, "Could not get preferences service");
}
/* Update Bookmark Menu */
MBrow::UpdateBookmarkMenu();
return NS_OK;
}
|
This teminates the whole of the program. This terminates embedding, apple event and Toolbox.
void DoTerminate( void )
{
TermWebShell();
TermAppleEvent();
TermToolbox();
}
|
This terminates Toolbox. Because OpenTSMAwareApplication() has been done in InitializeMacToolbox() of nsStdLib.shlb, TSM should be closed here.
static void TermToolbox( void )
{
if( gMouseRgn ){
DisposeRgn( gMouseRgn );
gMouseRgn = NULL;
}
CloseTSMAwareApplication();
}
|
This terminates embedding. This process is equal to that of PPBrowser.
static void TermWebShell( void )
{
nsresult rv;
// ShutDown preferences
{
NS_WITH_SERVICE(nsIPref, prefs, kPrefCID, &rv);
if( NS_SUCCEEDED(rv) ){
prefs->SavePrefFile();
}
}
UMacUnicode::ReleaseUnit();
// Term Embedding
NS_TermEmbedding();
}
|
Event process 
This is the event loop. The main window is shown intially by DoNew(), and the normal event loop of Macintosh is started. Each gotten event is dispatched to ProcessEvent().
void DoEventLoop( void )
{
EventRecord event;
/* Init New Window */
DoNew( 0xffff, NULL );
gRunning = true;
while( gRunning ){
/* get next event */
SetUpdateCommandStatus( false );
Boolean gotEvent = WaitNextEvent( everyEvent, &event, gSleepTime, gMouseRgn );
if( !gotEvent ){
event.what = nullEvent;
}
/* Process Event */
ProcessEvent( &event );
/* Adjust Menus */
if( !gInBackground && gUpdateCommandStatus ){
AdjustMenus();
}
}
}
|
This does the process specific to mozilla. This calls nsRepeater::DoRepeaters() in each event loop and nsRepeater::DoIdlers() in each null event. Actually, DoEvent() executes the event.
void ProcessEvent( EventRecord *event )
{
if( event->what != nullEvent ){ /* Some Event */
#ifdef DEBUG
if( event->what != keyDown ){
if( SIOUXHandleOneEvent( event ) ){
return;
}
}
#endif /* DEBUG */
/* Modeless Dialog */
if( IsDialogEvent( event ) ){
DialogPtr dlog;
short itemNo;
if( DialogSelect( event, &dlog, &itemNo ) ){
MMlDlog *mmidlog = MMlDlog::FindByDlog( dlog );
if( mmidlog ){
mmidlog->DoEvent( itemNo );
}
}
return;
}
/* handle event */
DoEvent( event );
}else{ /* Null Event */
/* Do App Idle */
DoIdle( event );
/* Do Moz Idle */
Repeater::DoIdlers( *event );
::PR_Sleep(PR_INTERVAL_NO_WAIT);
}
/* Do App Repeat */
DoRepeat( event );
/* Do Moz Repeat */
Repeater::DoRepeaters( *event );
return;
}
|
This is the event dispatcher and the normal process of Macintosh. Most of actual processes are left to sub-functions.
static void DoEvent( EventRecord *event )
{
OSErr err;
WindowPtr window;
short part;
Point aPoint;
switch( event->what ){
case mouseDown:
part = FindWindow( event->where, &window );
switch( part ){
case inMenuBar:
DoMenuCommand( MenuSelect( event->where ) );
break;
case inSysWindow:
SystemClick( event, window );
break;
case inContent:
if( window != FrontWindow() ){
SelectWindow( window );
}else{
DoContentClick( window, event );
}
break;
case inDrag:
if( window != FrontWindow() ){
SelectWindow( window );
}else{
DoDragWindow( window, event );
}
break;
case inGrow:
DoGrowWindow( window, event );
break;
case inZoomIn:
case inZoomOut:
if( TrackBox( window, event->where, part ) ){
DoZoomWindow( window, part );
}
break;
case inCollapseBox:
break;
case inGoAway:
if( TrackGoAway( window, event->where ) ){
DoCloseWindow( window );
}
break;
}
break;
case mouseUp:
DoMouseUp( event );
break;
case keyDown:
case autoKey:
DoKeyDown( event );
break;
case activateEvt:
DoActivate( (WindowPtr)event->message, ( event->modifiers & activeFlag ) != 0 );
break;
case updateEvt:
DoUpdate( (WindowPtr)event->message );
break;
case diskEvt:
if( HiWord( event->message ) != noErr ){
SetPt( &aPoint, kDILeft, kDITop );
err = DIBadMount( aPoint, event->message );
}
break;
case osEvt:
switch( ( event->message >> 24 ) & 0x0FF ){
case mouseMovedMessage:
DoMouseMove( event );
break;
case suspendResumeMessage:
gInBackground = ( event->message & resumeFlag ) == 0;
DoActivate( FrontWindow(), !gInBackground );
DoIdle( event );
break;
}
break;
case kHighLevelEvent:
AEProcessAppleEvent( event );
break;
}
}
|
This is an actual process at the time of dragging window. I show this as an example of the actual event processes.
static void DoDragWindow( WindowPtr window, EventRecord *event )
{
if( IsBrowWindow(window) ){ /* Browser Window */
Point oldPt, newPt;
oldPt = *(Point*)&window->portRect.top;
DragWindow( window, event->where, &qd.screenBits.bounds );
newPt = *(Point*)&window->portRect.top;
WMNG_WIND *wmngWind = FindWmngWindByWind( window );
if( wmngWind ){
wmngWind->mwind->MoveBy( newPt.h - oldPt.h, newPt.v - oldPt.v, true );
}
}
}
|
Thus, in each event process, a proper window object (MWind) is extracted and requested to do the process.
Here, FindWmngWindByWind() is used to extract the proper window object, which is implemented in wmng.cpp (window manager). Window manager defines data structures for each visual parts as classes, and holds visual hierarchy of each window in tree structure.
MWind class has the method for each event processing, that is inherited from MView class.
All other event processings are something like this, therefore omitted.
This is the menu process. After requesting window related menu process to the window object, this actually executes the menu of application level. That is, to open or close main window, to quit the application, and to download the file by netlib and so on.
static Boolean DoMenuCommand( long menuResult )
{
short menuID, menuItem;
WindowPtr window;
Boolean handled = false;
menuID = HiWord( menuResult );
menuItem = LoWord( menuResult );
/* ObeyCommand to MWind */
window = FrontWindow();
WMNG_WIND *wmngWind = FindWmngWindByWind( window );
if( wmngWind ){
handled = wmngWind->mwind->ObeyCommand( menuID, menuItem );
}
/* ObeyCommand to Application */
if( !handled ){
switch( menuID ){
case mApple:
switch( menuItem ){
case iAbout:
DspAbout();
handled = true;
break;
default:
{
Str255 daName;
short daRefNum;
GetMenuItemText( GetMenuHandle(mApple), menuItem, daName );
daRefNum = OpenDeskAcc( daName );
}
handled = true;
break;
}
break;
case mFile:
switch( menuItem ){
case iNew:
DoNew( 0xffff, NULL );
handled = true;
break;
case iClose:
window = FrontWindow();
if( IsBrowWindow(window) ){
DoCloseWindow( window );
}
handled = true;
break;
case iDnload:
{
/* Dialog Select URL */
Str255 strURL = "\p";
if( DspSelectURL( "\pDownLoad File",
"\pEnter URL of DownLooad File", strURL ) ){
char url[256];
CopyPtoCStr( url, strURL );
/* Make FileName */
char *ptr = strrchr( url, '/' );
if( ptr ){
ptr++;
}else{
ptr = url;
}
char name[256];
strcpy( name, ptr );
Str255 strName;
CopyCtoPStr( strName, name );
/* Put File */
StandardFileReply reply;
StandardPutFile( "\pEnter DownLoad FileName & Location"
, strName, &reply );
if( reply.sfGood ){
/* Set Creator, FileType */
OSType creator = '????';
OSType fileType = '????';
/* DnLoad File */
nsresult rv;
rv = DnLoadFile( url, &reply.sfFile, creator, fileType );
printf( "DnLoadFile rv=%d\n", rv );
}
}
}
handled = true;
break;
case iQuit:
DoCloseWindowAll();
gRunning = false;
handled = true;
break;
}
break;
}
}
if( handled ){
SetUpdateCommandStatus( true );
}
HiliteMenu(0);
return handled;
}
|
For file download, URL of downloaded file is gotten by dialog, then executed by DnLoadFile() in dnload.cpp .
Window class (MWind) 
In class definition of MWind, there is a pointer to the window widget as member variable related to mozilla. Window widget is the mozilla way representation for main window.
class MWind : public MView
{
private:
typedef MView Inherited;
/* Constructor, Destructor */
public:
MWind( WMNG_WIND *wmngWind );
virtual ~MWind();
.
.
/* Attribute */
public:
WMNG_WIND *mWmngWind;
static MView* mviewClicked;
MView *mTarget;
MBrow *mTargetBrow;
/* BrowserWindow */
public:
NS_METHOD GetWidget( nsIWidget** aWidget );
MBrow* GetBrowserShell( UInt16 id=CNTLID_ANY ) const;
void GetTitle( Str255 title );
void SetTitle( Str255 title );
protected:
nsCOMPtr<nsIWidget> mWindow;
// MChrome* mBrowserChrome;
};
|
In addition in PPBrowser, window class has pointers to child control instances that he holds, and to chrome instance.
marbrow doesn't have pointers to each child control instances directly. WMNG_WIND *mWmngWind is the pointer to the window manager's window data. And link to each controls can be traced from it.
And in marbrow, because multiple browsers can be placed on one window, chrome instances are created for each browser. Therefore, pointer to chrome is not held by window class but by browser shell class.
Creation, Disposal 
Constructor of MWind class controls all of the creation of main window and creation and initialization of child controls including browser.
MWind::MWind( WMNG_WIND *wmngWind )
: mWmngWind( wmngWind ), mTarget( NULL ), mTargetBrow( NULL )
{
MBrow::GetCharset( &gCharCodeMenuItem );
MBrow::GetAutoDet( &gAutoDetMenuItem );
Create();
}
NS_IMETHODIMP MWind::Create()
{
OSErr err;
Rect rect;
WindowPtr window;
ControlHandle rootControl;
|
In ordinary Macintosh way, creates main window, creates root control and so on.
/* Init Param */
rect = mWmngWind->bounds;
/* Create Window */
err = CreateNewWindow( kDocumentWindowClass,
kWindowStandardDocumentAttributes, &rect, &window );
if( err ){
ExtErr( err, "CreateNewWindow error", "MWind::Create", "none" );
}
DrawEnv de( window );
/* Set WindowKind */
((WindowPeek)window)->windowKind = WKIND_BROW;
/* Root Control */
err = GetRootControl( window, &rootControl );
if( err ){
err = CreateRootControl( window, &rootControl );
if( err ){
ExtErr( err, "CreateRootControl error", "MWind::Create", "none" );
}
}
/* Set Title */
SetWTitle( window, "\pmarbrow" );
/* Set Window Content Color */
RGBColor color;
SetRGBColor( color, 192, 192, 192 );
SetWindowContentColor( window, &color );
|
Window data of window manager(mWmngWind) is set up.
/* Set WmngWind */
mWmngWind->wind = window;
mWmngWind->rootControl = rootControl;
mWmngWind->mwind = this;
|
Instance of base widget is created.
In PPBrowser, chrome is created here. But in marbrow, because chrome is created for each browser, the process is shift to browser class constructor.
/* BrowserWindow : Make Base Widget */
nsresult rv;
mWindow = do_CreateInstance(kWindowCID, &rv);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
Child control array of mWmngWind is iterated and each objects are created. At this point, constructors of each control classes are called.
/* Create Cntls */
MView *initFocus = NULL;
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
switch( cntl->cntl_type ){
case CNTLTYPE_LOCA:
{
MLoca *mloca = new MLoca( mWmngWind, cntl );
if( !mloca ){
ExtErr( MemError(), "new MLoca error", "MWind::Create", "none" );
}
if( !initFocus ) initFocus = mloca;
}
break;
case CNTLTYPE_STAT:
{
MStat *mstat = new MStat( mWmngWind, cntl );
if( !mstat ){
ExtErr( MemError(), "new MStat error", "MWind::Create", "none" );
}
}
break;
case CNTLTYPE_BUTT:
{
MButt *mbutt = new MButt( mWmngWind, cntl );
if( !mbutt ){
ExtErr( MemError(), "new MButt error", "MWind::Create", "none" );
}
}
break;
case CNTLTYPE_BROW:
{
MBrow *mbrow = new MBrow( mWmngWind, cntl );
if( !mbrow ){
ExtErr( MemError(), "new MBrow error", "MWind::Create", "none" );
}
}
break;
}
}
|
Base widget is created.
/* BrowserWindow ( FinishCreate ) : Create Base Widget */
nsRect r(0, 0
mWmngWind->bounds.right - mWmngWind->bounds.left
mWmngWind->bounds.bottom - mWmngWind->bounds.top);
rv = mWindow->Create((nsNativeWidget)mWmngWind->wind, r,
nsnull, nsnull, nsnull, nsnull, nsnull);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
Again child control array of mWmngWind is iterated and FinishCeateSelf() is sent to each object.
/* FinishCreateSelf Cntls */
cntls = mWmngWind->cntls;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
cntl->mview->FinishCreateSelf();
}
|
Finally, FinishCeateSelf() is sent to itself.
/* BrowserWindow FinishCreateSelf */
FinishCreateSelf();
|
Window is shown and initial focus is set up.
/* Show Window */
err = TransitionWindow( window,
kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL );
if( err ){
ExtErr( err, "TransitionWindow error", "MWind::Create", "Main Window" );
}
/* Init Focus */
if( initFocus ) initFocus->SetFocus();
#if DEBUG_CONTROL
{
FSSpec spec;
FSMakeFSSpec( 0, 0, "\pControlHierarchy.txt", &spec );
DumpControlHierarchy( mWmngWind->wind, &spec );
}
#endif /* DEBUG_CONTROL */
return NS_OK;
}
|
Window is enabled and shown.
void MWind::FinishCreateSelf()
{
/* Enable & Show */
EnableSelf( true );
ShowSelf( true );
Inherited::FinishCreateSelf();
}
|
Destructor of MWind class disposes of all child controls and itself.
MWind::~MWind()
{
Destroy();
}
void MWind::Destroy()
{
#if DEBUG_CONTROL
{
FSSpec spec;
FSMakeFSSpec( 0, 0, "\pControlHierarchyEnd.txt", &spec );
DumpControlHierarchy( mWmngWind->wind, &spec );
}
#endif /* DEBUG_CONTROL */
/* Loop Cntls */
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
delete cntl->mview;
}
/* Hide Window */
OSErr err;
err = TransitionWindow( mWmngWind->wind,
kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL );
if( err ){
ExtErr( err, "TransitionWindow error", "MWind::Destroy", "Main Window" );
}
/* Destroy Window */
DisposeWindow( mWmngWind->wind );
}
|
Event 
Because MWind object holds objects of child controls such as browser, button etc, it has the responsibility of informing these control objects of events.
Basis of each event processes in MWind class is generalized like below.
Drawing process of window. DrawSelf() is sent to all control objects intersecting with visRgn.
void MWind::DrawSelf()
{
DrawEnv de( mWmngWind->wind );
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
Rect rect = cntl->bounds;
if( RectInRgn( &rect, mWmngWind->wind->visRgn ) ){
cntl->mview->DrawSelf();
}
}
}
|
Window is shown/hide. Base widget of mozilla is requested the process.
void MWind::ShowSelf( Boolean flag )
{
mWindow->Show( flag );
Inherited::ShowSelf( flag );
}
|
Window is enabled/disabled. Only a flag is set by MView's method.
void MWind::EnableSelf( Boolean flag )
{
Inherited::EnableSelf( flag );
}
|
Window is activated/inactivated. Lower control objects are informed of the status.
void MWind::ActivateSelf( Boolean flag )
{
/* Loop Cntls */
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
cntl->mview->ActivateSelf( flag );
}
Inherited::ActivateSelf( flag );
}
|
Actually window moving is achieved by DragWindow() of Macintosh. Therefore, only new coordinates are assigned in mWmngWind.
void MWind::MoveTo( SInt16 inHoriz, SInt16 inVert, Boolean inRefresh )
{
MoveBy( inHoriz - mWmngWind->bounds.left, inVert - mWmngWind->bounds.top, inRefresh );
}
void MWind::MoveBy( SInt16 inHorizDelta, SInt16 inVertDelta, Boolean inRefresh )
{
OffsetRect( &mWmngWind->bounds, inHorizDelta, inVertDelta );
}
|
After informing base widget of resize, both kind of resize procedure send resize to all child controls by AdjustCntlFrame() common procedure.
void MWind::ResizeFrameTo( SInt16 inWidth, SInt16 inHeight, Boolean inRefresh )
{
ResizeFrameBy( inWidth - ( mWmngWind->bounds.right - mWmngWind->bounds.left ),
inHeight - ( mWmngWind->bounds.bottom - mWmngWind->bounds.top),
inRefresh );
}
void MWind::ResizeFrameBy( SInt16 inWidthDelta, SInt16 inHeightDelta, Boolean inRefresh )
{
DrawEnv de( mWmngWind->wind );
/* Resize Frame */
mWmngWind->bounds.right += inWidthDelta;
mWmngWind->bounds.bottom += inHeightDelta;
if( inRefresh )
InvalRect( &mWmngWind->wind->portRect );
/* Resize Widget */
mWindow->Resize(mWmngWind->bounds.right - mWmngWind->bounds.left,
mWmngWind->bounds.bottom - mWmngWind->bounds.top, PR_TRUE);
/* Loop Cntls */
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
AdjustCntlFrame( cntl, inWidthDelta, inHeightDelta, false );
}
}
|
AdjustCntlFrame() requests move or resize to each controls, taking account of their bind settings.
void MWind::AdjustCntlFrame( WMNG_CNTL *wmngCntl,
SInt16 inSurrWidthDelta, SInt16 inSurrHeightDelta, Boolean inRefresh )
{
SInt16 widthDelta = 0;
SInt16 heightDelta = 0;
SInt16 horizDelta = 0;
SInt16 vertDelta = 0;
if( wmngCntl->bind & BIND_RIGHT ){
if( wmngCntl->bind & BIND_LEFT ){
// Both right and left are bound
// Pane resizes horizontally
widthDelta = inSurrWidthDelta;
} else {
// Right bound, left free
// Pane moves horizontally
horizDelta = inSurrWidthDelta;
}
}
if( wmngCntl->bind & BIND_BOTTOM ){
if( wmngCntl->bind & BIND_TOP ){
// Both bottom and top are bound
// Pane resizes vertically
heightDelta = inSurrHeightDelta;
} else {
// Bottom bound, left free
// Pane moves vertically
vertDelta = inSurrHeightDelta;
}
}
// Perform the actual move and/or resize. Do the move first
// because the resize can cause an immediate redraw.
if ( (horizDelta != 0) || (vertDelta != 0) ) {
wmngCntl->mview->MoveBy( horizDelta, vertDelta, inRefresh );
}
if ( (widthDelta != 0) || (heightDelta != 0) ) {
wmngCntl->mview->ResizeFrameBy( widthDelta, heightDelta, inRefresh );
}
}
|
This searches for clicked control and sends ClickSelf() to it. In marbrow, controls except browser are made of Macintosh Control manager, so they can be searched by FindControlUnderMouse(). Only browser is searched in manual coding.
void MWind::ClickSelf( const EventRecord &inEvent )
{
if( !mActive || !mEnable ) return;
Point where;
ControlHandle cntlH;
SInt16 part;
DrawEnv de( mWmngWind->wind );
/* Get Mouse Location */
where = inEvent.where;
GlobalToLocal( &where );
/* Find Control */
Boolean handled = false;
cntlH = FindControlUnderMouse( where, mWmngWind->wind, &part );
if( cntlH ){
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
if( cntl->cntlH == cntlH && cntl->cntl_type != CNTLTYPE_BROW ){
mMViewClicked = cntl->mview;
cntl->mview->ClickSelf( inEvent );
handled = true;
}
}
}
/* To Brow */
if( !handled ){
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
Rect rect;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
if( cntl->cntl_type == CNTLTYPE_BROW ){
rect = cntl->bounds;
if( PtInRect( where, &rect ) ){
mMViewClicked = cntl->mview;
cntl->mview->ClickSelf( inEvent );
}
}
}
}
}
|
This sends HandleKeyPress() to controls owning focus.
Boolean MWind::HandleKeyPress( const EventRecord &inEvent )
{
Boolean handled = false;
DrawEnv de( mWmngWind->wind );
/* Send Target */
if( mWmngWind->mwind->mTarget ){
handled = mWmngWind->mwind->mTarget->HandleKeyPress( inEvent );
}
return handled;
}
|
These sends DoIdle(), DoRepeat() to all controls.
void MWind::DoIdle( const EventRecord &inEvent )
{
/* Loop Cntls */
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
cntl->mview->DoIdle( inEvent );
}
}
void MWind::DoRepeat( const EventRecord &inEvent )
{
/* Loop Cntls */
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
cntl->mview->DoRepeat( inEvent );
}
}
|
Mouse move process. This sends HandleMouseMove() to control pointed by mouse pointer. When mouse is being pressed, this keeps sending to pressed control.
void MWind::HandleMouseMove( const EventRecord &inEvent )
{
DrawEnv de( mWmngWind->wind );
/* Get Mouse Location */
Point where;
where = inEvent.where;
GlobalToLocal( &where );
WMNG_CNTLS cntls = mWmngWind->cntls;
WMNG_CNTLIT cntlit;
WMNG_CNTL *cntl;
Rect rect;
Boolean found = false;
if( ::Button() && MView::mMViewClicked ){
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
if( cntl->mview == MView::mMViewClicked ){
cntl->mview->HandleMouseMove( inEvent );
found = true;
break;
}
}
}else{
for( cntlit=cntls.begin(); cntlit!=cntls.end(); ++cntlit ){
cntl = *cntlit;
rect = cntl->bounds;
if( PtInRect( where, &rect ) ){
cntl->mview->HandleMouseMove( inEvent );
found = true;
break;
}
}
}
if( !found ){
SetThemeCursor( kThemeArrowCursor );
}
}
|
After requesting menu process to control owning focus, this executes menu process of which window is in charge.
Boolean MWind::ObeyCommand( const short menuID, const short menuItem )
{
Boolean handled = false;
/* ObeyCommand to Target */
if( mTarget ){
handled = mTarget->ObeyCommand( menuID, menuItem );
}
/* ObeyCommand to MWind */
switch( menuID ){
case mBookmarks:
switch( menuItem ){
case iAddCurPage:
{
MBrow *mbrow = mWmngWind->mwind->mTargetBrow;
if( mbrow ){
MBrow::AddBookmark( mbrow );
}
}
handled = true;
break;
case iManamgeBm:
SysBeep( 1 );
handled = true;
break;
default:
{
MBrow *mbrow = mWmngWind->mwind->mTargetBrow;
if( mbrow ){
MBrow::GoToBookmark( mbrow, menuID, menuItem );
}
}
handled = true;
break;
}
break;
case mCharCode:
switch( menuItem ){
case iWE_ISO8859:
case iCE_ISO8859:
case iSE_ISO8859:
case iMACROMAN:
case iJP_ISO2022:
case iJP_SHIFTJIS:
case iJP_EUC:
case iKR_EUC:
case iCH_GB2312:
case iCH_GBK:
case iCH_HZ:
case iCH_BIG5:
case iCH_EUCTW:
MBrow::DoCharset( menuItem );
gCharCodeMenuItem = menuItem;
handled = true;
break;
}
break;
case mAutoDet:
switch( menuItem ){
case iAutoDetOff:
case iAutoDetJp:
case iAutoDetKr:
case iAutoDetCh:
case iAutoDetChSimp:
case iAutoDetChTrad:
case iAutoDetEAsia:
MBrow::DoAutoDet( menuItem );
gAutoDetMenuItem = menuItem;
handled = true;
break;
}
break;
default:
if( menuID < 128 ){
MBrow *mbrow = mWmngWind->mwind->mTargetBrow;
if( mbrow ){
MBrow::GoToBookmark( mbrow, menuID, menuItem );
}
handled = true;
}
break;
}
return handled;
}
|
Browser is requested to process Character set and Auto detect.
Also Browser is requested to process Bookmark addition and Jump to Bookmark.
Accessor 
Accessor used by browser class and chrome class.
This returns base widget of mozilla that corresponds to window.
NS_METHOD MWind::GetWidget( nsIWidget** aWidget )
{
NS_ENSURE_ARG_POINTER(aWidget);
*aWidget = mWindow;
NS_IF_ADDREF(*aWidget);
return NS_OK;
}
|
This is a kind of so called "getter function" in XPCOM, and AddRef()s interface pointer in it and returns it.
If the caller wants to get interface pointer in nsCOMPtr,
nsCOMPtr<nsIWidget> aWidget;
mWmngWind->mwind->GetWidget(getter_AddRefs(aWidget));
NS_ENSURE_TRUE(aWidget, NS_ERROR_FAILURE);
|
Thus processed. Thanks to nsCOMPtr, the interface pointer is automatically Release()d at the end of the scope of aWidget.
In ordinary Macintosh way, this sets up/gets title of window.
void MWind::GetTitle( Str255 title )
{
NS_ASSERTION(mWmngWind, "SetTitle on null mWmngWind");
NS_ASSERTION(mWmngWind->wind, "SetTitle on null WindowPtr");
GetWTitle( mWmngWind->wind, title );
}
void MWind::SetTitle( Str255 title )
{
NS_ASSERTION(mWmngWind, "SetTitle on null mWmngWind");
NS_ASSERTION(mWmngWind->wind, "SetTitle on null WindowPtr");
SetWTitle( mWmngWind->wind, title );
}
|
Browser class (MBrow) 
In class definition of MBrow, as mozilla related member variables, there are a couple of interface pointers to the WebBrowser. And, there is massage sink as a static member, by way of which events are sent to mozilla.
WMNG_WIND *mWmngWind and WMNG_CNTL *mWmngCntl are pointers to the management data of parent WMNG_WIND and of this WMNG_BROW respectively, which are managed by window manager.
Initial URL character string is kept in window manager's WMNG_BROW class, that describes the data of browser.
In PPBrowser, a pointer to chrome object is owned by window class, but in marbrow, this brwser class owns it. The chrome class includes processes for each window and for each browser. Because marbrow supports multiple browser per one window, chrome instance is created in one-to-one correspondednce to browser instance and associated with each browser.
class MBrow : public MView
{
private:
typedef MView Inherited;
// Friends
friend class MChrome;
/* Constructor, Destructor */
public:
MBrow( WMNG_WIND *wmngWind, WMNG_CNTL *wmngCntl );
virtual ~MBrow();
.
.
/* Attribute */
public:
WMNG_WIND *mWmngWind;
WMNG_CNTL *mWmngCntl;
/* BrowserShell */
protected:
static nsMacMessageSink mMessageSink;
protected:
nsCOMPtr<nsIWebBrowser> mWebBrowser;
nsCOMPtr<nsIBaseWindow> mWebBrowserAsBaseWin;
nsCOMPtr<nsIWebNavigation> mWebBrowserAsWebNav;
/* BrowserWindow in PP Brow */
MChrome* mBrowserChrome;
/* Some Browser Status */
protected:
Boolean mLoading;
nsString mTitle;
};
yMBrow.cppz
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/* Static Variable */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
nsMacMessageSink MBrow::mMessageSink;
|
Event process of mozilla exists in widget module. In case of embedding, every kind of event received by framework is sent to mozilla by way of nsMacMessageSink's mMessageSink.DispatchOSEvent().
Creation, Disposal 
Constructor of MBrow class creates the chrome and associates it with himself, creates browser instance.
MBrow::MBrow( WMNG_WIND *wmngWind, WMNG_CNTL *wmngCntl )
: mWmngWind( wmngWind ), mWmngCntl( wmngCntl ),
mBrowserChrome( NULL ),
mLoading( false )
{
Create();
}
NS_IMETHODIMP MBrow::Create()
{
nsresult rv;
/* BrowserWindow : Make Chrome */
mBrowserChrome = new MChrome;
NS_ENSURE_TRUE(mBrowserChrome, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(mBrowserChrome);
mBrowserChrome->BrowserWindow() = mWmngWind->mwind;
/* Create WebBrowser */ /* BrowserShell */
mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(mWebBrowser));
NS_ENSURE_TRUE(baseWin, NS_ERROR_FAILURE);
mWebBrowserAsBaseWin = baseWin;
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mWebBrowser));
NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
mWebBrowserAsWebNav = webNav;
/* Set WmngWind */
mWmngCntl->cntlH = NULL;
mWmngCntl->mview = this;
return NS_OK;
}
|
In marbrow, a chrome instance is created and associated with, in one-to-one basis to each browser instances.
Browser is a instance of nsWebBrowser class. Its source code exists in embedding module. nsWebBrowser is instanciated by do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv); and returns its typical interface, nsIWebBrower. And this is housed in mWebBrowser member.
In case that you manipulate nsWebBrowser, all you have to keep is this nsIWebBrower mWebBrowser and that's enough, and you can get whatever interfaces you want by QI()ing via nsIWebBrowser whenever other interfaces are necessary. But in this procedure, nsIBaseWindow, nsIWebNavigation are gotten and kept in member variables in this timing, 'cause afterwards they are referenced very often.
Mozilla specific process in this procedure is to initialize geometry of nsWebBrowser(position, size, etc). By InitWindow() and Create() of nsIBaseWindow mWebBrowserAsBaseWin, that is the interface associated with the geometry, initialization is done anyway. Then, by AdjustFrame() common method, the position and size are arranged precisely.
And, by SetTopLevelWindow(), this initialize and set up chrome.
void MBrow::FinishCreateSelf()
{
DrawEnv de( mWmngWind->wind );
nsCOMPtr<nsIWidget> aWidget;
mWmngWind->mwind->GetWidget(getter_AddRefs(aWidget));
if( !aWidget ) NS_ERROR( "GetWidget failure" );
/* Init BaseWindow */
Rect rect;
GetBestCntlRect( mWmngCntl->bounds, rect );
nsRect r(rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top);
mWebBrowserAsBaseWin->InitWindow(aWidget->GetNativeData(NS_NATIVE_WIDGET),
nsnull, r.x, r.y, r.width, r.height);
mWebBrowserAsBaseWin->Create();
AdjustFrame( rect );
/* Tell BrowserShell about Chrome */
SetTopLevelWindow(mBrowserChrome);
/* Tell Chrome about BrowserShell */
mBrowserChrome->BrowserShell() = this;
/* Kill Scrollbars */
WMNG_BROW *wmng_brow = dynamic_cast<WMNG_BROW*>(mWmngCntl);
if( wmng_brow->killScrollbars ){
KillContentScrollbars();
}
/* Enable & Show */
EnableSelf( true );
ShowSelf( true );
/* Set Focus */
SetFocus();
/* Load URL */
if( wmng_brow->startURL[0] != 0 ){
LoadURL( wmng_brow->startURL, MAX_URLSTRING );
}
}
|
After enabling and showing itself, this load initial URL finally.
Called by MBrow::FinishCreateSelf(). Last stage of initializing browser. By calling nsIWebBrowser::SetContainerWindow(), nsWebBrowser recognizes MChrome object as a chrome.
And, as the code comment says, if you want to initialize nsIDocShell related matters, it can be done here also.
NS_IMETHODIMP MBrow::SetTopLevelWindow(nsIWebBrowserChrome * aTopLevelWindow)
{
mWebBrowser->SetContainerWindow(aTopLevelWindow);
/*
In case we needed to do something with the underlying docshell...
nsCOMPtr<nsIDocShell> aDocShell;
mWebBrowser->GetDocShell(getter_AddRefs(aDocShell));
NS_ENSURE_TRUE(aDocShell, NS_ERROR_FAILURE);
*/
nsresult rv;
/* Set URIContentListener to WebBrowser */
if( aTopLevelWindow ){
nsCOMPtr<nsIURIContentListener> browserAsURIContentListene
r(do_GetInterface(aTopLevelWindow));
NS_ENSURE_TRUE(browserAsURIContentListener, NS_ERROR_INVALID_ARG);
rv = mWebBrowser->SetParentURIContentListener( browserAsURIContentListener );
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
}else{
rv = mWebBrowser->SetParentURIContentListener( nsnull );
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
}
return NS_OK;
}
|
Chrome of marbrow implements nsIURIContentListener interface, in addition to the interfaces PPBrowser implements. By nsIWebBrowser::SetParentURIContentListener(), nsWebBrowser recognizes our chrome's nsIURIContentListener.
Destructor of MBrow class stops net process, cut off association between browser shell and chrome and dispose of chrome.
MBrow::~MBrow()
{
Destroy();
SetTopLevelWindow( nsnull );
/* Destroy Chrome */
if( mBrowserChrome ){
mBrowserChrome->BrowserShell() = nsnull;
mBrowserChrome->BrowserWindow() = nsnull;
NS_RELEASE(mBrowserChrome);
}
}
void MBrow::Destroy()
{
/* Fource Stop */
Stop();
}
|
Webshell 
Method mainly called by chrome. Getter(to get) and setter(to set up) for browser(nsIWebBrowser) used by chrome class.
NS_METHOD MBrow::GetWebBrowser(nsIWebBrowser** aBrowser)
{
NS_ENSURE_ARG_POINTER(aBrowser);
*aBrowser = mWebBrowser;
NS_IF_ADDREF(*aBrowser);
return NS_OK;
}
NS_METHOD MBrow::SetWebBrowser(nsIWebBrowser* aBrowser)
{
NS_ENSURE_ARG(aBrowser);
DrawEnv de( mWmngWind->wind );
nsCOMPtr<nsIWidget> aWidget;
mWmngWind->mwind->GetWidget(getter_AddRefs(aWidget));
NS_ENSURE_TRUE(aWidget, NS_ERROR_FAILURE);
mWebBrowser = aBrowser;
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(mWebBrowser));
NS_ENSURE_TRUE(baseWin, NS_ERROR_FAILURE);
mWebBrowserAsBaseWin = baseWin;
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mWebBrowser));
NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
mWebBrowserAsWebNav = webNav;
/* Init BaseWindow */
Rect rect;
GetBestCntlRect( mWmngCntl->bounds, rect );
nsRect r(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
mWebBrowserAsBaseWin->InitWindow(aWidget->GetNativeData(NS_NATIVE_WIDGET),
nsnull, r.x, r.y, r.width, r.height);
mWebBrowserAsBaseWin->Create();
AdjustFrame( rect );
return NS_OK;
}
|
In marbrow, because of multiple browser on one window, title information from chrome is kept by each browser and title bar of the main window shows last informed one.
void MBrow::GetTitle( nsString &outTitle )
{
outTitle = mTitle;
}
void MBrow::SetTitle( const nsString &inTitle )
{
mTitle = inTitle;
Str255 aStr;
UMacUnicode::StringToStr255( mTitle, aStr );
mWmngWind->mwind->SetTitle( aStr );
}
|
Event 
Event process of MBrow object processes basically by dispatching event to mozilla through nsMacMessageSink.
void MBrow::DrawSelf()
{
DrawEnv de( mWmngWind->wind );
/* Draw Self */
EventRecord osEvent;
osEvent.what = updateEvt;
mMessageSink.DispatchOSEvent(osEvent, mWmngWind->wind);
}
void MBrow::ShowSelf( Boolean flag )
{
mWebBrowserAsBaseWin->SetVisibility( flag );
Inherited::ShowSelf( flag );
}
void MBrow::EnableSelf( Boolean flag )
{
Inherited::EnableSelf(flag );
}
void MBrow::ActivateSelf( Boolean flag )
{
Inherited::ActivateSelf(flag );
}
|
This processes move and resize of browser. After all, this sets up it by nsIBaseWindow::SetPositionAndSize().
void MBrow::ResizeFrameTo( SInt16 inWidth, SInt16 inHeight, Boolean inRefresh )
{
Rect rect;
SetRectWH( mWmngCntl->bounds, inWidth, inHeight );
GetBestCntlRect( mWmngCntl->bounds, rect );
AdjustFrame( rect );
}
void MBrow::ResizeFrameBy( SInt16 inWidthDelta, SInt16 inHeightDelta, Boolean inRefresh )
{
Rect rect;
IncRectWH( mWmngCntl->bounds, inWidthDelta, inHeightDelta );
GetBestCntlRect( mWmngCntl->bounds, rect );
AdjustFrame( rect );
}
void MBrow::MoveBy( SInt16 inHorizDelta, SInt16 inVertDelta, Boolean inRefresh )
{
Rect rect;
OffsetRect( &mWmngCntl->bounds, inHorizDelta, inVertDelta );
GetBestCntlRect( mWmngCntl->bounds, rect );
AdjustFrame( rect );
}
void MBrow::AdjustFrame( const Rect &inRect )
{
DrawEnv de( mWmngWind->wind );
nsRect r(inRect.left, inRect.top, inRect.right - inRect.left, inRect.bottom - inRect.top);
mWebBrowserAsBaseWin->SetPositionAndSize(r.x, r.y, r.width, r.height, PR_TRUE);
}
|
This uses nsMacMessageSink and sends event by DispatchOSEvent().
void MBrow::ClickSelf( const EventRecord &inEvent )
{
if( !mActive || !mEnable ) return;
DrawEnv de( mWmngWind->wind );
if( mWmngWind->mwind->mTarget != this ){
SetFocus();
}
mMessageSink.DispatchOSEvent( (EventRecord&)inEvent, mWmngWind->wind );
}
|
Others go the same way, and omitted.
This does clipboard process such as copy, paste etc. Process is equal to what is of PPBrowser.
Boolean MBrow::ObeyCommand( const short menuID, const short menuItem )
{
Boolean handled = false;
nsresult rv;
nsCOMPtr<nsIClipboardCommands> clipCmd;
/* ObeyCommand to Me */
switch( menuID ){
case mEdit:
switch( menuItem ){
case iCut:
rv = GetClipboardHandler( getter_AddRefs(clipCmd) );
if( NS_SUCCEEDED(rv) ){
clipCmd->CutSelection();
}
handled = true;
break;
case iCopy:
rv = GetClipboardHandler( getter_AddRefs(clipCmd) );
if( NS_SUCCEEDED(rv) ){
clipCmd->CopySelection();
}
handled = true;
break;
case iPaste:
rv = GetClipboardHandler( getter_AddRefs(clipCmd) );
if( NS_SUCCEEDED(rv) ){
clipCmd->PasteSelection();
}
handled = true;
break;
case iClear:
break;
case iSelectAll:
rv = GetClipboardHandler( getter_AddRefs(clipCmd) );
if( NS_SUCCEEDED(rv) ){
clipCmd->SelectAll();
}
handled = true;
break;
}
}
return handled;
}
|
Operation 
By <nsIWebNavigation::LoadURI(), this loads URL.
void MBrow::LoadURL( const char *text, SInt32 len )
{
if( len < 0 ) len = strlen( text );
nsAutoString string; string.AssignWithConversion(text, len);
LoadURL(string);
}
void MBrow::LoadURL( const nsString& text )
{
nsresult rv = mWebBrowserAsWebNav->LoadURI( text.GetUnicode(),
nsIWebNavigation::LOAD_FLAGS_NONE );
#ifdef DEBUG
if( NS_FAILED(rv) ){
char strText[MAX_URLSTRING];
PRInt32 len = MAX_URLSTRING;
UMacUnicode::StringToStr( text, strText, &len );
printf("mWebBrowserAsWebNav->LoadURI failed : '%s'\n",strText);
}
#endif /* DEBUG */
}
|
This creates plain window and does SetViewMode() to DocShell of its browser object.
int MBrow::ViewSource( const nsString& url )
{
/* Create New Browser */
WMNG_WIND *wmngWind = DoNewPlain( 1000, -1, -1, -1, -1,
nsIWebBrowserChrome::CHROME_DEFAULT );
NS_ENSURE_TRUE(wmngWind, NS_ERROR_FAILURE);
WMNG_CNTL *cntl = FindWmngCntlByID( wmngWind, CNTLTYPE_BROW, 1000 );
NS_ENSURE_TRUE(cntl, NS_ERROR_FAILURE);
MBrow *mcntl = dynamic_cast<MBrow*>(cntl->mview);
NS_ENSURE_TRUE(mcntl, NS_ERROR_FAILURE);
/* Get WebBrowser */
nsCOMPtr<nsIWebBrowser> webBrowser;
mcntl->GetWebBrowser(getter_AddRefs(webBrowser));
NS_ENSURE_TRUE(webBrowser, NS_ERROR_FAILURE);
/* Get DocShell */
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(webBrowser);
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
/* Set ViewMode */
docShell->SetViewMode( nsIDocShell::viewSource );
/* Load URL */
mcntl->LoadURL( url );
return NS_OK;
}
|
This traces interface as nsIDocShell -> nsIContentViewer -> nsIContentViewerFile and calls Print().
int MBrow::DoPrint()
{
/* Get DocShell */
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mWebBrowser);
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
/* Get Viewer */
nsCOMPtr<nsIContentViewer> viewer;
docShell->GetContentViewer(getter_AddRefs(viewer));
if( viewer ){
/* Get ViewerFile */
nsCOMPtr<nsIContentViewerFile> viewerFile = do_QueryInterface(viewer);
if( viewerFile ){
viewerFile->Print(PR_FALSE,0);
}
}
return 0;
}
|
This seaches for location bar and status bar associated with itself and requests these to set up character string.
void MBrow::SetLocaCntlText( const nsString& locaText )
{
MLoca* mcntl = FindLocaCntl();
if( mcntl ){
mcntl->SetText( locaText );
mcntl->SetFocus();
}
}
void MBrow::SetStatCntlText( const char* statText, SInt32 len )
{
MStat* mcntl = FindStatCntl();
if( mcntl ){
mcntl->SetText( statText, len );
}
}
void MBrow::SetStatCntlText( const PRUnichar* statText )
{
MStat* mcntl = FindStatCntl();
if( mcntl ){
mcntl->SetText( statText );
}
}
void MBrow::SetStatCntlText( const nsString& statText )
{
MStat* mcntl = FindStatCntl();
if( mcntl ){
mcntl->SetText( statText );
}
}
|
Navigation 
This reflects condition of net process in each control.
In PPBrowser, these are in window class, but because these are status of each browser essentially, should be in browser class.
In marbrow, progress bar is not supported and progress change is empty.
NS_METHOD MBrow::OnNetStart( nsIWebProgress *progress, nsIRequest *request,
PRInt32 progressStateFlags, PRUint32 status )
{
/* Set Loading */
SetLoading( true );
/* Disp StatCntl */
nsAutoString str;
str.AssignWithConversion("Transferring ...");
SetStatCntlText( str );
/* Enable Stop Button */
{
WMNG_CNTL* cntl;
MButt* mcntl;
for( cntl=nil; ; ){
cntl = FindSourceCntlWithFuncAll( cntl, mWmngWind, "stop", mWmngCntl->id );
if( !cntl ) break;
mcntl = dynamic_cast<MButt*>(cntl->mview);
if( mcntl ){
mcntl->EnableSelf( true );
}
}
}
return NS_OK;
}
NS_METHOD MBrow::OnNetStop( nsIWebProgress *progress, nsIRequest *request,
PRInt32 progressStateFlags, PRUint32 status )
{
/* Reset Loading */
SetLoading( false );
/* Disp StatCntl */
nsAutoString str;
str.AssignWithConversion("Transfer Done.");
SetStatCntlText( str );
WMNG_CNTL* cntl;
MButt* mcntl;
/* Activate/Deactivate Back Button */
for( cntl=nil; ; ){
cntl = FindSourceCntlWithFuncAll( cntl, mWmngWind, "back", mWmngCntl->id );
if( !cntl ) break;
mcntl = dynamic_cast<MButt*>(cntl->mview);
if( mcntl ){
mcntl->EnableSelf( CanGoBack() );
}
}
/* Activate/Deactivate Forward Button */
for( cntl=nil; ; ){
cntl = FindSourceCntlWithFuncAll( cntl, mWmngWind, "forward", mWmngCntl->id );
if( !cntl ) break;
mcntl = dynamic_cast<MButt*>(cntl->mview);
if( mcntl ){
mcntl->EnableSelf( CanGoForward() );
}
}
/* Dectivate Stop Button */
for( cntl=nil; ; ){
cntl = FindSourceCntlWithFuncAll( cntl, mWmngWind, "stop", mWmngCntl->id );
if( !cntl ) break;
mcntl = dynamic_cast<MButt*>(cntl->mview);
if( mcntl ){
mcntl->EnableSelf( false );
}
}
return NS_OK;
}
NS_METHOD MBrow::OnProgressChange( nsIWebProgress *progress, nsIRequest *request,
PRInt32 curSelfProgress, PRInt32 maxSelfProgress,
PRInt32 curTotalProgress, PRInt32 maxTotalProgress )
{
return NS_OK;
}
|
This requests all the actual processes to nsIWebNavigation interface.
Boolean MBrow::CanGoBack()
{
PRBool canDo;
nsresult rv;
rv = mWebBrowserAsWebNav->GetCanGoBack(&canDo);
return (NS_SUCCEEDED(rv) && canDo);
}
Boolean MBrow::CanGoForward()
{
PRBool canDo;
nsresult rv;
rv = mWebBrowserAsWebNav->GetCanGoForward(&canDo);
return (NS_SUCCEEDED(rv) && canDo);
}
void MBrow::Back()
{
if (CanGoBack())
mWebBrowserAsWebNav->GoBack();
else
::SysBeep(5);
}
void MBrow::Forward()
{
if (CanGoForward())
mWebBrowserAsWebNav->GoForward();
else
::SysBeep(5);
}
void MBrow::Stop()
{
mWebBrowserAsWebNav->Stop();
}
void MBrow::Refresh( PRInt32 reloadFlags )
{
/* -- Reload Flags -- */
/* enum { LOAD_FLAGS_NONE = 0U }; */
/* enum { LOAD_FLAGS_MASK = 65535U }; */
/* enum { LOAD_FLAGS_IS_REFRESH = 16U }; */
/* enum { LOAD_FLAGS_IS_LINK = 32U }; */
/* enum { LOAD_FLAGS_BYPASS_HISTORY = 64U }; */
/* enum { LOAD_FLAGS_REPLACE_HISTORY = 128U }; */
/* enum { LOAD_FLAGS_BYPASS_CACHE = 256U }; */
/* enum { LOAD_FLAGS_BYPASS_PROXY = 512U }; */
mWebBrowserAsWebNav->Reload( reloadFlags );
}
void MBrow::GetCurrentURL( char *text, SInt32 len )
{
text[0] = 0;
nsresult rv;
nsCOMPtr<nsIURI> uri;
rv = mWebBrowserAsWebNav->GetCurrentURI( getter_AddRefs(uri) );
if( NS_SUCCEEDED(rv) ){
if( uri ){
char *buf = nsnull;
uri->GetSpec( &buf );
if( buf ){
if( strlen( buf ) < len ){
strcpy( text, buf );
}else{
strncpy( text, buf, len-1 );
text[len-1] = 0;
}
Recycle(buf);
}
}else{
text[0] = 0;
}
}
}
|
These are omitted here. Please see the source code for detail.
Chrome class (MChrome) 
Chrome class of marbrow (MChrome) is nearly equal to the one of PPBrowser(CWebBrowserChrome), but there are 2 large differences.
First - Creation of chrome instance
Chrome class of PPBrowser is created for each window object by the constructor of window class. But chrome class of marbrow is created for each browser object by the constructor of browser class.
Chrome class includes processes for both each window object and each browser object. Because marbrow supports multiple browser on one window, this construction is essential.
Second - nsIURIContentListener interface
In addition to interfaces that PPBrowser has in chrome, marbrow has addtionally nsIURIContentListener interface.
This nsIURIContentListener interface makes OnStartURIOpen() method in the said interface called on starting URL open. This method makes it possible to intercept process according to scheme, target name and URL.
When scheme is mailto: or news:, marbrow intercepts process and requests default mail client set up in InternetConfig to process.
Difference between chrome class of PPBrowser and of marbrow is only that marbrow has nsIURIContentListener interface additionally. Except this, the two are quite equal.
class MChrome : public nsIWebBrowserChrome,
public nsIWebProgressListener,
public nsIBaseWindow,
public nsIPrompt,
public nsIURIContentListener,
public nsIInterfaceRequestor
{
// Friends
friend class MBrow;
// Constructor, Destructor
protected:
MChrome();
virtual ~MChrome();
// COM Interfaces
public:
// nsISupports
NS_DECL_ISUPPORTS
// nsIWebBrowserChrome
NS_DECL_NSIWEBBROWSERCHROME
// nsIWebProgressListener
NS_DECL_NSIWEBPROGRESSLISTENER
// nsIBaseWindow
NS_DECL_NSIBASEWINDOW
// nsIPrompt
NS_DECL_NSIPROMPT
// nsIURIContentListener
NS_DECL_NSIURICONTENTLISTENER
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
// Accessors
protected:
MWind*& BrowserWindow();
MBrow*& BrowserShell();
// Attributes
protected:
MWind* mBrowserWindow;
MBrow* mBrowserShell;
static vector<MChrome*> mgBrowserList;
};
yMChrome.cppz
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/* Static Variable */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
vector<MChrome*> MChrome::mgBrowserList;
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/* nsISupports */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
NS_IMPL_ADDREF(MChrome)
NS_IMPL_RELEASE(MChrome)
NS_INTERFACE_MAP_BEGIN(MChrome)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
NS_INTERFACE_MAP_ENTRY(nsIURIContentListener)
NS_INTERFACE_MAP_ENTRY(nsIPrompt)
NS_INTERFACE_MAP_END
|
nsIURIContentListener interface 
Below I show only nsIURIContentListener interface that marbrow has additionally.
Other interfaces are omitted, for they are equal to those of PPBrowser except syntactic difference, results from differences of class name or of the framework.
When scheme is mailto: or news:, this starts default mail client user sets up in InternetConfig, requests him to load URL, and makes process of mozilla aborted.
NS_IMETHODIMP MChrome::OnStartURIOpen(nsIURI* aURI,
const char* aWindowTarget, PRBool* aAbortOpen)
{
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aAbortOpen);
nsresult rv;
char *bufSpec = nsnull;
char *bufScheme = nsnull;
char *bufTarget;
nsAutoString strSpec;
nsAutoString strScheme;
nsAutoString strTarget;
rv = aURI->GetSpec(&bufSpec);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
rv = aURI->GetScheme(&bufScheme);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
bufTarget = (char*)aWindowTarget;
strSpec.AssignWithConversion(bufSpec);
strScheme.AssignWithConversion(bufScheme);
strTarget.AssignWithConversion(bufTarget);
#ifdef DEBUG
printf("OnStartURIOpen : scheme='%s' target='%s' spec='%s'\n",
bufScheme, bufTarget, bufSpec);
#endif /* DEBUG */
if( strScheme.EqualsIgnoreCase("http") ){ /* http: */
if( strTarget.EqualsIgnoreCase("_blank") ){ /* New Window */
/* Leave process to nsIWebBrowserChrome::FindNamedBrowserItem() */
/* which fails to set nsIDocShellTreeItem *aBrowserItem , */
/* then nsIWebBrowserChrome::GetNewBrowser() */
/* which makes Plain Browser Window , */
/* so I do nothing here . */
;
}
}else
if( strScheme.EqualsIgnoreCase("javascript") ){ /* javascript: */
/* Through javascript: */
;
}else
if( strScheme.EqualsIgnoreCase("mailto") /* mailto: */
|| strScheme.EqualsIgnoreCase("news") ){ /* news: */
/* Launch Default Browser */
OSStatus err = uinetc::LaunchURL( bufSpec );
#ifdef DEBUG
if( err ){
printf("uinetc::LaunchURL fail %d: '%s'\n",err,bufSpec);
}
#endif /* DEBUG */
*aAbortOpen = PR_TRUE;
}
if( bufSpec ) Recycle( bufSpec );
if( bufScheme ) Recycle( bufScheme );
return NS_OK;
}
|
Here I do no special, but if this method is implemented, according to the conditions, for example ...
you are able to do something special, whatever you want.
For other methods, default processes are enough. So, basically, processes are thrown to the implementation of the default chrome's corresponding interfaces, that is held by nsWebBrowser (nsWBURIContentListener).
NS_IMETHODIMP MChrome::GetProtocolHandler(nsIURI* aURI,
nsIProtocolHandler** aProtocolHandler)
{
/* Leave nsWebBrowser (nsWBURIContentListener) */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP MChrome::DoContent(const char* aContentType,
nsURILoadCommand aCommand, const char* aWindowTarget,
nsIChannel* aOpenedChannel, nsIStreamListener** aContentHandler,
PRBool* aAbortProcess)
{
/* Leave nsWebBrowser (nsWBURIContentListener) */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP MChrome::IsPreferred(const char* aContentType,
nsURILoadCommand aCommand, const char* aWindowTarget, char ** aDesiredContentType,
PRBool* aCanHandle)
{
/* Leave nsWebBrowser (nsWBURIContentListener) */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP MChrome::CanHandleContent(const char* aContentType,
nsURILoadCommand aCommand, const char* aWindowTarget, char ** aDesiredContentType,
PRBool* aCanHandleContent)
{
/* Leave nsWebBrowser (nsWBURIContentListener) */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP MChrome::GetLoadCookie(nsISupports ** aLoadCookie)
{
/* Leave nsWebBrowser (nsWBURIContentListener) */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP MChrome::SetLoadCookie(nsISupports * aLoadCookie)
{
/* Leave nsWebBrowser (nsWBURIContentListener) */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP MChrome::GetParentContentListener(nsIURIContentListener**
aParentListener)
{
NS_ENSURE_ARG_POINTER(aParentListener);
NS_ASSERTION(PR_FALSE, "Not Yet Implemented");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP MChrome::SetParentContentListener(nsIURIContentListener*
aParentListener)
{
NS_ASSERTION(PR_FALSE, "Not Yet Implemented");
return NS_ERROR_NOT_IMPLEMENTED;
}
|
File download by netlib 
Here I download file of specified URL by using netlib directly. This is an example of low level usage of mozilla module.
I download the file on URL specified by argument, using netlib, and save it as a file which owes FSSpec, creator, file type, specified by argument.
nsresult DnLoadFile( const char* url, FSSpec *spec, OSType creator, OSType fileType )
{
nsresult rv;
|
From C character string of URL received by argument, nsIURI object is created, that is the generic mozilla representation of the URL.
/* New Uri */
nsCOMPtr<nsIURI> uri;
printf( "Calling NS_NewURI for %s...\n", url );
rv = NS_NewURI( getter_AddRefs( uri ), url );
if ( NS_SUCCEEDED( rv ) ) {
printf( "...NS_NewURI completed OK\n" );
} else {
printf( "%s %d: NS_NewURI failed, rv=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)rv );
return rv;
}
|
By passing this nsIURI object, channel to actual downloader is opened.
/* New Channel */
nsCOMPtr<nsIChannel> channel;
printf( "Calling NS_OpenURI...\n" );
rv = NS_OpenURI( getter_AddRefs( channel ), uri, 0 );
if ( NS_SUCCEEDED( rv ) ) {
printf( "...NS_OpenURI completed OK\n" );
} else {
printf( "%s %d: NS_OpenURI failed, rv=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)rv );
return rv;
}
|
Listener object (DnloadListener) is created. This object does execute the reception of data, according to the progress of netlib.
/* New Listener */
DnloadListener *listener = new DnloadListener( url,
spec, creator, fileType );
NS_ENSURE_TRUE( listener, NS_ERROR_FAILURE);
NS_IF_ADDREF( listener );
|
To netlib channel, this passes listener object and requests to start asynchronous reading.
/* Read Channel Async */
printf( "Doing AsyncRead...\n" );
rv = channel->AsyncRead( listener, 0 );
printf( "...AsyncRead completed rv=0x%08X\n", rv );
/* Cleanup */
NS_RELEASE( listener );
return NS_OK;
}
|
Class definition of DnloadListener.
This inherits from nsIStreamObserver and nsIStreamListener interfaces and has methods that is
In member variables, this has character string of URL to download, FSSpec, creator and file type of saved file, pointer to progress condition dialog, various kinds of progress condition management values, pointer to dummy widget and so on.
class DnloadListener : public nsIStreamListener {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
/* Constructor, Destructor */
public:
DnloadListener( const char* aUrl,
FSSpec *spec, OSType creator, OSType fileType );
virtual ~DnloadListener();
/* Attribute */
protected:
nsCString mURLString;
PRInt32 mTotalLength;
PRInt32 mBytesRead;
nsCOMPtr<nsIWidget> mDummyWidget;
FSSpec mSpec;
OSType mCreator;
OSType mFileType;
short mRefNum;
MProgDlog *mDlog;
};
|
Main process of this part is creation of dummy widget.
Asynchronous download condition is informed through event sink of mozilla. Event sink is processed by mozilla widget.
This download can start even if browser window is not shown (that is, mozilla widget doesn't exist). So, to keep event sink's wheel running, dummy widget is necessary and created.
DnloadListener::DnloadListener( const char* aUrl,
FSSpec *spec, OSType creator, OSType fileType )
: mTotalLength( 0 ), mBytesRead( 0 ),
mURLString( aUrl ),
mSpec( *spec ), mCreator( creator ),
mFileType( fileType ), mRefNum( 0 ), mDlog( nil )
{
printf( "DnloadListener::DnloadListener -> in\n");
NS_INIT_REFCNT();
/* New Dummy Widget */
nsresult rv;
mDummyWidget = do_CreateInstance(kWindowCID, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "New DummyWidget failed");
/* Create Dummy Widget */
nsRect r(0, 0, 0, 0);
rv = mDummyWidget->Create((nsNativeWidget)nil, r,
nsnull, nsnull, nsnull, nsnull, nsnull);
NS_ASSERTION(NS_SUCCEEDED(rv), "Create DummyWidget failed");
printf( "DnloadListener::DnloadListener -> out\n");
}
|
Destructor disposes of dummy widget.
DnloadListener::~DnloadListener()
{
printf( "DnloadListener::~DnloadListener -> in\n");
/* Destroy Dummy Widget */
nsresult rv;
rv = mDummyWidget->Destroy();
NS_ASSERTION(NS_SUCCEEDED(rv), "Destroy DummyWidget failed");
printf( "DnloadListener::~DnloadListener -> out\n");
}
|
For the display of pogress condition, total size of the file is gotten. Progress condition dialog is created. Save file is created and opened.
NS_IMETHODIMP DnloadListener::OnStartRequest(nsIChannel *aChannel, nsISupports* aContext)
{
printf("DnloadListener::OnStartRequest() -> in\n");
/* Get Total Length */
nsresult rv;
PRInt32 aContentLength;
rv = aChannel->GetContentLength( &aContentLength );
if ( NS_SUCCEEDED( rv ) ) {
printf( "nsIChannel::GetContentLength completed OK\n" );
mTotalLength = aContentLength;
} else {
printf( "%s %d: nsIChannel::GetContentLength failed, rv=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)rv );
}
printf( "TotalLength = %ld\n", mTotalLength );
/* New Progress Dialog */
mDlog = new MProgDlog( dProgress, mTotalLength );
/* Create File */
OSErr err;
err = FSpCreate( &mSpec, mCreator, mFileType, smSystemScript );
if( err == dupFNErr ){
err = FSpDelete( &mSpec );
if( err ){
printf( "FSpDelete failed, err=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)err );
return NS_ERROR_FAILURE;
}
err = FSpCreate( &mSpec, mCreator, mFileType, smSystemScript );
if( err ){
printf( "FSpCreate failed, err=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)err );
return NS_ERROR_FAILURE;
}
}else
if( err ){
printf( "FSpCreate failed, err=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)err );
return NS_ERROR_FAILURE;
}
/* Open File */
err = FSpOpenDF( &mSpec, fsWrPerm, &mRefNum );
if( err ){
printf( "FSpOpenDF failed, err=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)err );
return NS_ERROR_FAILURE;
}
printf( "DnloadListener::OnStartRequest() -> out\n");
return NS_OK;
}
|
File is closed and dialog is dispoed of.
NS_IMETHODIMP DnloadListener::OnStopRequest(nsIChannel *aChannel,
nsISupports *aContext,
nsresult aStatus, const PRUnichar* aStatusArg)
{
printf("DnloadListener::OnStopRequest() -> in\n");
/* Check Read Length */
if( mBytesRead != mTotalLength ){
printf( "mBytesRead != mTotalLength : %ld %ld\n",
mBytesRead, mTotalLength );
}
/* Close File */
if( mRefNum ){
OSErr err;
err = FSClose( mRefNum );
if( err ){
printf( "FSClose failed, err=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)err );
}
mRefNum = 0;
}
/* Delete Progress Dialog */
if( mDlog ){
delete mDlog;
mDlog = nil;
}
printf( "------------------------\n" );
printf( "mURLString = '%s'\n", mURLString.GetBuffer() );
printf( "mTotalLength = %ld\n", mTotalLength );
printf( "mBytesRead = %ld\n", mBytesRead ); printf( "------------------------\n" );
printf( "DnloadListener::OnStopRequest() -> out\n");
return NS_OK;
}
|
This reads data already arrived from the channel's stream and writes them on file. And, dialog is updated.
NS_IMETHODIMP DnloadListener::OnDataAvailable(nsIChannel *aChannel,
nsISupports *aContext,
nsIInputStream *aIStream,
PRUint32 aOffset, PRUint32 aLength)
{
printf( "DnloadListener::OnDataAvailable() -> in\n");
nsresult rv = NS_OK;
char buffer[ SIZE_BUFFER ];
unsigned long bytesRemaining = aLength;
while ( bytesRemaining ) {
unsigned int bytesRead;
/* Read to Buffer */
rv = aIStream->Read( buffer,
PR_MIN( sizeof( buffer ), bytesRemaining ),
&bytesRead );
if ( NS_SUCCEEDED( rv ) ) {
/* Write to File */
if( mRefNum ){
OSErr err;
long wrCount = bytesRead;
err = FSWrite( mRefNum, &wrCount, buffer );
if( err ){
printf( "FSWrite failed, err=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)err );
break;
}
if( wrCount != bytesRead ){
printf( "FSWrite failed, wrCount=0x%08X bytesRead=0x%08X\n"
, (char*)__FILE__, (int)__LINE__, wrCount, bytesRead );
break;
}
}
/* Update Param */
printf( "bytesRead = %d\n", bytesRead );
mBytesRead += bytesRead;
bytesRemaining -= bytesRead;
/* Update Progress Dialog */
if( mDlog ){
if( mDlog->mCancel ){
aChannel->Cancel( NS_ERROR_ABORT );
return NS_ERROR_ABORT;
}
mDlog->SetValue( mBytesRead );
}
} else {
printf( "%s %d: Read error, rv=0x%08X\n",
(char*)__FILE__, (int)__LINE__, (int)rv );
break;
}
}
printf( "DnloadListener::OnDataAvailable() -> out\n");
return NS_OK;
}
|
| c_o_n_t_a_c_t | Copyright (C) 2000-2002 Symphony, Inc. All Rights Reserved. |
Japanese |