root/trunk/llmozlib2/llembeddedbrowserwindow.cpp

Revision 16, 42.9 kB (checked in by callum.linden, 1 year ago)

Some misc fixes: Fixed up VC8 solution/project files, added VC8 release and debug versions of GLUI library, fixed testGL dependency, fixed uninitialized HWND in llembeddedbrowserwindow.cpp.
Reviewed by telephone

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is Linden Lab Inc. (http://lindenlab.com) code.
15  *
16  * The Initial Developer of the Original Code is:
17  *   Callum Prentice (callum@ubrowser.com)
18  *
19  * Portions created by the Initial Developer are Copyright (C) 2006
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  *  Callum Prentice (callum@ubrowser.com)
24  *
25  * Alternatively, the contents of this file may be used under the terms of
26  * either the GNU General Public License Version 2 or later (the "GPL"), or
27  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28  * in which case the provisions of the GPL or the LGPL are applicable instead
29  * of those above. If you wish to allow use of your version of this file only
30  * under the terms of either the GPL or the LGPL, and not to allow others to
31  * use your version of this file under the terms of the MPL, indicate your
32  * decision by deleting the provisions above and replace them with the notice
33  * and other provisions required by the GPL or the LGPL. If you do not delete
34  * the provisions above, a recipient may use your version of this file under
35  * the terms of any one of the MPL, the GPL or the LGPL.
36  *
37  * ***** END LICENSE BLOCK ***** */
38
39 // seems to be required by LibXUL/Mozilla code to avoid crashes in their debug code, but only on Windows.
40 // undef'd at end of this
41 #ifdef _DEBUG
42         #ifdef WIN32
43                 #define DEBUG 1
44         #endif
45 #endif
46
47 // needed for the code in LLEmbeddedBrowserWindow::NotifyInvalidated() which will
48 // one day be moved to platform agnostic code when I find out how...
49 #ifdef WIN32
50 #include "windows.h"
51 #endif
52
53 #include "llembeddedbrowser.h"
54 #include "llembeddedbrowserwindow.h"
55
56 // Mozilla code has non-virtual destructors
57 #ifdef WIN32
58 #pragma warning( disable : 4291 ) // (no matching operator delete found; memory will not be freed if initialization throws an exception)
59 #pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual"
60 #endif
61
62 #include "nsCWebBrowser.h"
63 #include "nsGUIEvent.h"
64 #include "nsICaret.h"
65 #include "nsIContent.h"
66 #include "nsIDOMDocument.h"
67 #include "nsIDOMElement.h"
68 #include "nsIDOMWindow.h"
69 #include "nsIDOMEvent.h"
70 #include "nsIDocShell.h"
71 #include "nsIDocShellTreeItem.h"
72 #include "nsIDocument.h"
73 #include "nsIFrame.h"
74 #include "nsIHttpChannel.h"
75 #include "nsIInterfaceRequestorUtils.h"
76 #include "nsIScrollableView.h"
77 #include "nsISelection.h"
78 #include "nsISelectionController.h"
79 #include "nsIWebBrowserChrome.h"
80 #include "nsIWebBrowserChromeFocus.h"
81 #include "nsIWebBrowserFocus.h"
82 #include "nsIWebProgress.h"
83 #include "nsIWebProgressListener.h"
84 #include "nsPresContext.h"
85 #include "nsProfileDirServiceProvider.h"
86 #include "nsXPCOMGlue.h"
87 #include "nsXULAppAPI.h"
88
89 #include "llembeddedbrowserwindow.h"
90
91 #include <iostream>
92
93 #ifdef WIN32
94 #pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
95 #endif
96
97 ////////////////////////////////////////////////////////////////////////////////
98 //
99 LLEmbeddedBrowserWindow::LLEmbeddedBrowserWindow() :
100         mParent( 0 ),
101         mWebBrowser( nsnull ),
102         mBaseWindow( nsnull ),
103         mWindowId( 0 ),
104         mPercentComplete( 0 ),
105         mBrowserWidth( 0 ),
106         mBrowserHeight( 0 ),
107         mBrowserDepth( 4 ),
108         mPageBuffer( 0 ),
109         mEnabled( true ),
110         mCurrentUri( "" ),
111         mStatusText( "" ),
112         mClickHref( "" ),
113         mClickTarget( "" ),
114         mNoFollowScheme( "secondlife://" ),
115         mBkgRed( 0xff ),
116         mBkgGreen( 0xff ),
117         mBkgBlue( 0xff ),
118         mCaretRed( 0x0 ),
119         mCaretGreen( 0x0 ),
120         mCaretBlue( 0x0 ),
121         m404RedirectUrl( "" ),
122         mFlipBitmap( false )
123 {
124 }
125
126 ////////////////////////////////////////////////////////////////////////////////
127 //
128 LLEmbeddedBrowserWindow::~LLEmbeddedBrowserWindow()
129 {
130         if ( mWebNav )
131         {
132                 mWebNav->Stop ( nsIWebNavigation::STOP_ALL );
133                 mWebNav = nsnull;
134         };
135
136         if ( mBaseWindow )
137         {
138                 mBaseWindow->Destroy();
139                 mBaseWindow = nsnull;
140         };
141
142         if ( mPageBuffer )
143         {
144                 delete[] mPageBuffer;
145                 mPageBuffer = 0;
146         };
147 }
148
149 ////////////////////////////////////////////////////////////////////////////////
150 //
151 nsresult LLEmbeddedBrowserWindow::createBrowser( void* nativeWindowHandleIn, PRInt32 widthIn, PRInt32 heightIn, nsIWebBrowser **aBrowser )
152 {
153         NS_ENSURE_ARG_POINTER(aBrowser);
154         *aBrowser = nsnull;
155
156         nsresult rv;
157         mWebBrowser = do_CreateInstance( NS_WEBBROWSER_CONTRACTID, &rv );
158         if ( ! mWebBrowser )
159         {
160                 return NS_ERROR_FAILURE;
161         }
162
163     (void)mWebBrowser->SetContainerWindow( NS_STATIC_CAST( nsIWebBrowserChrome*, this ) );
164
165     nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface( mWebBrowser );
166     dsti->SetItemType( nsIDocShellTreeItem::typeContentWrapper );
167
168     mBaseWindow = do_QueryInterface( mWebBrowser );
169
170     mBaseWindow->InitWindow( nativeWindowHandleIn, nsnull,  0, 0, mBrowserWidth, mBrowserHeight );
171     mBaseWindow->Create();
172
173     nsCOMPtr< nsIWebProgressListener > listener( NS_STATIC_CAST( nsIWebProgressListener*, this ) );
174     nsCOMPtr< nsIWeakReference > thisListener( do_GetWeakReference( listener ) );
175     mWebBrowser->AddWebBrowserListener( thisListener, NS_GET_IID( nsIWebProgressListener ) );
176
177 #if LL_DARWIN
178         // Without this, the mac doesn't get upates for animating gifs, mouseovers, etc.
179         mBaseWindow->SetVisibility( PR_TRUE );
180 #else
181         mBaseWindow->SetVisibility( PR_FALSE );
182 #endif
183
184         nsresult result;
185         mWebNav = do_QueryInterface( mWebBrowser, &result );
186         if ( NS_FAILED( result ) || ! mWebNav )
187         {
188                 return NS_ERROR_FAILURE;
189         };
190
191         setSize( widthIn, heightIn );
192
193     if ( mWebBrowser )
194     {
195                 *aBrowser = mWebBrowser;
196                 NS_ADDREF( *aBrowser );
197
198                 return NS_OK;
199     };
200
201     return NS_ERROR_FAILURE;
202 }
203
204 ////////////////////////////////////////////////////////////////////////////////
205 //
206 NS_IMPL_ADDREF( LLEmbeddedBrowserWindow )
207 NS_IMPL_RELEASE( LLEmbeddedBrowserWindow )
208
209 ////////////////////////////////////////////////////////////////////////////////
210 //
211 NS_INTERFACE_MAP_BEGIN( LLEmbeddedBrowserWindow )
212         NS_INTERFACE_MAP_ENTRY_AMBIGUOUS( nsISupports, nsIWebBrowserChrome )
213         NS_INTERFACE_MAP_ENTRY( nsIInterfaceRequestor )
214         NS_INTERFACE_MAP_ENTRY( nsIWebBrowserChrome )
215         NS_INTERFACE_MAP_ENTRY( nsIWebProgressListener )
216         NS_INTERFACE_MAP_ENTRY( nsIURIContentListener )
217         NS_INTERFACE_MAP_ENTRY( nsISupportsWeakReference )
218         NS_INTERFACE_MAP_ENTRY( nsIToolkitObserver )
219 NS_INTERFACE_MAP_END
220
221 ////////////////////////////////////////////////////////////////////////////////
222 //
223 NS_IMETHODIMP LLEmbeddedBrowserWindow::GetInterface( const nsIID &aIID, void** aInstancePtr )
224 {
225         if ( aIID.Equals( NS_GET_IID( nsIDOMWindow ) ) )
226         {
227                 if ( mWebBrowser )
228                 {
229                         return mWebBrowser->GetContentDOMWindow( ( nsIDOMWindow** )aInstancePtr );
230                 };
231
232                 return NS_ERROR_NOT_INITIALIZED;
233         };
234
235         return QueryInterface( aIID, aInstancePtr );
236 }
237
238 ////////////////////////////////////////////////////////////////////////////////
239 // called when something changes the status text - emits event to consumer
240 NS_IMETHODIMP LLEmbeddedBrowserWindow::SetStatus( PRUint32 aType, const PRUnichar* aStatus )
241 {
242         mStatusText = std::string( NS_ConvertUTF16toUTF8( aStatus ).get() );
243
244         LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), mStatusText );
245         mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onStatusTextChange, event );
246
247         return NS_OK;
248 }
249
250 ////////////////////////////////////////////////////////////////////////////////
251 //
252 NS_IMETHODIMP LLEmbeddedBrowserWindow::GetWebBrowser( nsIWebBrowser** aWebBrowser )
253 {
254         NS_ENSURE_ARG_POINTER( aWebBrowser );
255
256         *aWebBrowser = mWebBrowser;
257
258         NS_IF_ADDREF( *aWebBrowser );
259
260         return NS_OK;
261 }
262
263 ////////////////////////////////////////////////////////////////////////////////
264 //
265 NS_IMETHODIMP LLEmbeddedBrowserWindow::SetWebBrowser( nsIWebBrowser* aWebBrowser )
266 {
267         NS_ENSURE_ARG_POINTER( aWebBrowser );
268
269         mWebBrowser = aWebBrowser;
270
271         return NS_OK;
272 }
273
274 ////////////////////////////////////////////////////////////////////////////////
275 //
276 NS_IMETHODIMP LLEmbeddedBrowserWindow::GetChromeFlags( PRUint32* aChromeMask )
277 {
278         return NS_ERROR_NOT_IMPLEMENTED;
279 }
280
281 ////////////////////////////////////////////////////////////////////////////////
282 //
283 NS_IMETHODIMP LLEmbeddedBrowserWindow::SetChromeFlags( PRUint32 aChromeMask )
284 {
285         return NS_ERROR_NOT_IMPLEMENTED;
286 }
287
288 ////////////////////////////////////////////////////////////////////////////////
289 //
290 NS_IMETHODIMP LLEmbeddedBrowserWindow::DestroyBrowserWindow()
291 {
292         return NS_OK;
293 }
294
295 ////////////////////////////////////////////////////////////////////////////////
296 //
297 NS_IMETHODIMP LLEmbeddedBrowserWindow::SizeBrowserTo( PRInt32 aCX, PRInt32 aCY )
298 {
299         return NS_OK;
300 }
301
302 ////////////////////////////////////////////////////////////////////////////////
303 //
304 NS_IMETHODIMP LLEmbeddedBrowserWindow::ShowAsModal()
305 {
306         return NS_ERROR_NOT_IMPLEMENTED;
307 }
308
309 ////////////////////////////////////////////////////////////////////////////////
310 //
311 //
312 NS_IMETHODIMP LLEmbeddedBrowserWindow::IsWindowModal( PRBool* retval )
313 {
314         *retval = PR_FALSE;
315
316         return NS_OK;
317 }
318
319 ////////////////////////////////////////////////////////////////////////////////
320 //
321 NS_IMETHODIMP LLEmbeddedBrowserWindow::ExitModalEventLoop( nsresult aStatus )
322 {
323         return NS_OK;
324 }
325
326 ////////////////////////////////////////////////////////////////////////////////
327 // called when the page loading progress changes - emits event to consumer
328 NS_IMETHODIMP LLEmbeddedBrowserWindow::OnProgressChange( nsIWebProgress* progress, nsIRequest* request,
329                                                                                                         PRInt32 curSelfProgress, PRInt32 maxSelfProgress,
330                                                                                                                 PRInt32 curTotalProgress, PRInt32 maxTotalProgress )
331 {
332         mPercentComplete = static_cast< PRInt16 >
333                 ( static_cast< float >( curTotalProgress * 100.0f ) / static_cast< float >( maxTotalProgress ) );
334
335         if ( mPercentComplete < 0 )
336                 mPercentComplete = 0;
337
338         if ( mPercentComplete > 100 )
339                 mPercentComplete = 100;
340
341         LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), mPercentComplete );
342         mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onUpdateProgress, event );
343
344         return NS_OK;
345 }
346
347 ////////////////////////////////////////////////////////////////////////////////
348 // called when the browser state changes - as described below - emits event to consumer
349 NS_IMETHODIMP LLEmbeddedBrowserWindow::OnStateChange( nsIWebProgress* progress, nsIRequest* request,
350                                                                                                         PRUint32 progressStateFlags, nsresult status )
351 {
352         if ( ( progressStateFlags & STATE_START ) && ( progressStateFlags & STATE_IS_DOCUMENT ) && ( status == NS_OK ) )
353         {
354                 // TODO: move this to a better place.
355                 enableToolkitObserver( false );
356                 enableToolkitObserver( true );
357
358                 // page load is starting so remove listener that catches "click" events
359                 nsCOMPtr< nsIDOMWindow > window;
360                 nsresult result = progress->GetDOMWindow( getter_AddRefs( window ) );
361                 if ( result == NS_OK )
362                 {
363                         nsCOMPtr< nsIDOMEventTarget > target = do_QueryInterface( window );
364                         if ( target )
365                                 target->RemoveEventListener(NS_ConvertUTF8toUTF16( "click" ), this, PR_TRUE );
366                 };
367
368                 // set the listener to we can catch nsURIContentListener events
369                 if ( mWebBrowser )
370                 {
371                         mWebBrowser->SetParentURIContentListener( NS_STATIC_CAST( nsIURIContentListener*, this ) );
372                 };
373
374                 // emit event that navigation is beginning
375                 mStatusText = std::string( "Browser loaded" );
376                 LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), mStatusText );
377                 mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onNavigateBegin, event );
378
379                 // about to move to a different page so have to stop grabbing a page
380                 // but done one final grab in case the app doesn't ever call grabWindow again
381                 grabWindow( 0, 0, mBrowserWidth, mBrowserHeight );
382         };
383
384         if ( ( progressStateFlags & STATE_STOP ) && ( progressStateFlags & STATE_IS_WINDOW ) && ( status == NS_OK ) )
385         {
386                 // page load is complete so add listener that catches "click" events
387                 nsCOMPtr< nsIDOMWindow > window;
388                 nsresult result = progress->GetDOMWindow( getter_AddRefs( window ) );
389                 if ( result == NS_OK )
390                 {
391                         nsCOMPtr< nsIDOMEventTarget > target = do_QueryInterface( window );
392                         if ( target )
393                                 target->AddEventListener(NS_ConvertUTF8toUTF16( "click" ), this, PR_TRUE );
394                 };
395
396                 // pick up raw HTML response status code
397                 PRUint32 responseStatus = 0;
398                 if ( request )
399                 {
400                         nsCOMPtr< nsIHttpChannel > httpChannel = do_QueryInterface( request );
401                         if ( httpChannel )
402                         {
403                                 httpChannel->GetResponseStatus( &responseStatus );
404                         };
405                 };
406
407                 // emit event that navigation is finished
408                 mStatusText = std::string( "Done" );
409                 LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), mStatusText, (int)responseStatus );
410                 mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onNavigateComplete, event );
411
412                 // also set the flag here since back/forward navigation doesn't call progress change
413                 grabWindow( 0, 0, mBrowserWidth, mBrowserHeight );
414         };
415
416         if ( progressStateFlags & STATE_REDIRECTING )
417         {
418                 mStatusText = std::string( "Redirecting..." );
419         };
420
421         if ( progressStateFlags & STATE_TRANSFERRING )
422         {
423                 mStatusText = std::string( "Transferring..." );
424         };
425
426         if ( progressStateFlags & STATE_NEGOTIATING )
427         {
428                 mStatusText = std::string( "Negotiating..." );
429         };
430
431         LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), mStatusText );
432         mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onStatusTextChange, event );
433
434         return NS_OK;
435 }
436
437 ////////////////////////////////////////////////////////////////////////////////
438 // call when the location changes - e.g. when a site redirects - emits event to consumer
439 // TODO: ought to check that this change is on the top frame and
440 // indicate this to the consumer of this class
441 NS_IMETHODIMP LLEmbeddedBrowserWindow::OnLocationChange( nsIWebProgress* webProgress,
442                                                                                                                 nsIRequest* request,
443                                                                                                                         nsIURI* location )
444 {
445         if ( request )
446         {
447                 nsCOMPtr< nsIHttpChannel > http_channel = do_QueryInterface( request );
448                 if ( http_channel )
449                 {
450                         PRUint32 response_status = 0;
451                         http_channel->GetResponseStatus( &response_status );
452
453                         if ( response_status == 404 )
454                         {
455                                 if ( ! m404RedirectUrl.empty() )
456                                 {
457                                         if ( mWebNav )
458                                         {
459                                                 mWebNav->LoadURI( reinterpret_cast< const PRUnichar* >
460                                                         ( NS_ConvertUTF8toUTF16( m404RedirectUrl.c_str() ).get() ),
461                                                                 nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY,
462                                                                         nsnull, nsnull, nsnull );
463                                         };
464                                 };
465                         };
466                 };
467         };
468
469         nsCAutoString newURI;
470         location->GetSpec( newURI );
471
472         mCurrentUri = newURI.get();
473
474         LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri() );
475         mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onLocationChange, event );
476
477         return NS_OK;
478 }
479
480 ////////////////////////////////////////////////////////////////////////////////
481 // change the background color that gets used between pages (usually white)
482 void LLEmbeddedBrowserWindow::setBackgroundColor( const PRUint8 redIn, const PRUint8 greenIn, const PRUint8 blueIn )
483 {
484         mBkgRed = redIn;
485         mBkgGreen = greenIn;
486         mBkgBlue = blueIn;
487 }
488
489 ////////////////////////////////////////////////////////////////////////////////
490 // change the caret color (we have different backgrounds to edit fields - black caret on black background == bad)
491 void LLEmbeddedBrowserWindow::setCaretColor( const PRUint8 redIn, const PRUint8 greenIn, const PRUint8 blueIn )
492 {
493         mCaretRed = redIn;
494         mCaretGreen = greenIn;
495         mCaretBlue = blueIn;
496 }
497
498 ////////////////////////////////////////////////////////////////////////////////
499 //
500 void LLEmbeddedBrowserWindow::setEnabled( PRBool enabledIn )
501 {
502         mEnabled = enabledIn;
503 }
504
505 ////////////////////////////////////////////////////////////////////////////////
506 // allow consumers of this class to observe events - add themselves as an observer
507 bool LLEmbeddedBrowserWindow::addObserver( LLEmbeddedBrowserWindowObserver* observerIn )
508 {
509         return mEventEmitter.addObserver( observerIn );
510 }
511
512 ////////////////////////////////////////////////////////////////////////////////
513 // allow consumers of this class to observe events - remove themselves as an observer
514 bool LLEmbeddedBrowserWindow::remObserver( LLEmbeddedBrowserWindowObserver* observerIn )
515 {
516         return mEventEmitter.remObserver( observerIn );
517 }
518
519 ////////////////////////////////////////////////////////////////////////////////
520 // used by observers of this class to get the current URI
521 const std::string& LLEmbeddedBrowserWindow::getCurrentUri()
522 {
523         return mCurrentUri;
524 }
525
526 ////////////////////////////////////////////////////////////////////////////////
527 // utility method that is used by observers to retrieve data after an event
528 const PRInt16 LLEmbeddedBrowserWindow::getPercentComplete()
529 {
530         return mPercentComplete;
531 }
532
533 ////////////////////////////////////////////////////////////////////////////////
534 // utility method that is used by observers to retrieve data after an event
535 const std::string& LLEmbeddedBrowserWindow::getStatusMsg()
536 {
537         return mStatusText;
538 }
539
540 ////////////////////////////////////////////////////////////////////////////////
541 // utility method that is used by observers to retrieve data after an event
542 const std::string& LLEmbeddedBrowserWindow::getClickLinkHref()
543 {
544         return mClickHref;
545 }
546
547 ////////////////////////////////////////////////////////////////////////////////
548 // utility method that is used by observers to retrieve data after an event
549 const std::string& LLEmbeddedBrowserWindow::getClickLinkTarget()
550 {
551         return mClickTarget;
552 }
553
554 ////////////////////////////////////////////////////////////////////////////////
555 // called when the status text is changed - emits event to consumer
556 NS_IMETHODIMP LLEmbeddedBrowserWindow::OnStatusChange( nsIWebProgress* aWebProgress,
557                                                                                                                 nsIRequest* aRequest,
558                                                                                                                         nsresult aStatus,
559                                                                                                                                 const PRUnichar* aMessage )
560 {
561         mStatusText = std::string( NS_ConvertUTF16toUTF8( aMessage ).get() );
562
563         LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), mStatusText );
564         mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onStatusTextChange, event );
565
566         return NS_OK;
567 }
568
569 ////////////////////////////////////////////////////////////////////////////////
570 // implement this if you want to do something when the security state changtes
571 NS_IMETHODIMP LLEmbeddedBrowserWindow::OnSecurityChange( nsIWebProgress* aWebProgress,
572                                                                                                         nsIRequest* aRequest,
573                                                                                                                 PRUint32 state )
574 {
575         return NS_OK;
576 }
577
578 ////////////////////////////////////////////////////////////////////////////////
579 // render a page into memory and grab the window
580 // TODO: 0,0, browser width, browser height is always passed in right now
581 //       need to make this work with arbitrary rects (i.e. the dirty rect)
582 unsigned char* LLEmbeddedBrowserWindow::grabWindow( int xIn, int yIn, int widthIn, int heightIn )
583 {
584         // sanity check
585         if ( ! mWebBrowser )
586                 return 0;
587
588         // only grab the window if it's enabled
589         if ( ! mEnabled )
590                 return false;
591
592         // get the docshell
593         nsCOMPtr< nsIDocShell > docShell = do_GetInterface( mWebBrowser );
594         if ( ! docShell )
595                 return PR_FALSE;
596
597
598         // get pres context
599         nsCOMPtr< nsPresContext > presContext;
600         nsresult result = docShell->GetPresContext( getter_AddRefs( presContext ) );
601         if ( NS_FAILED( result ) || ( ! presContext ) )
602                 return PR_FALSE;
603
604         // get view manager
605         nsIViewManager* viewManager = presContext->GetViewManager();
606         if ( ! viewManager )
607                 return PR_FALSE;
608
609         // get the view
610         nsIScrollableView* scrollableView = NULL;
611         viewManager->GetRootScrollableView( &scrollableView );
612         nsIView* view = NULL;
613         if ( scrollableView )
614                 scrollableView->GetScrolledView( view );
615         else
616                 viewManager->GetRootView( view );
617
618         // get the rectangle we want to render in twips (this looks odd but takees care of scrolling too)
619         nsRect rect = view->GetBounds() - view->GetPosition() - view->GetPosition();
620         if ( rect.IsEmpty() )
621                 return 0;
622
623         float p2t = presContext->PixelsToTwips();
624         rect.width = NSIntPixelsToTwips( widthIn, p2t );
625         rect.height = NSIntPixelsToTwips( heightIn, p2t );
626
627         // render the page
628         nsCOMPtr< nsIRenderingContext > context;
629         result = viewManager->RenderOffscreen( view, rect, PR_FALSE, PR_FALSE, NS_RGB( mBkgRed, mBkgGreen, mBkgBlue  ), getter_AddRefs( context ) );
630         if ( NS_FAILED( result ) )
631                 return 0;
632
633         // retrieve the surface we rendered to
634         nsIDrawingSurface* surface = nsnull;
635         context->GetDrawingSurface( &surface );
636         if ( ! surface )
637                 return 0;
638
639         // lock the surface and retrieve a pointer to the rendered data and current row span
640         PRUint8* data;
641         PRInt32 rowLen;
642         // sometime rowspan ! width in pixels * bytes per pixel so save row span value and use in application
643         result = surface->Lock( xIn, yIn, widthIn, heightIn, reinterpret_cast< void** >( &data ), &mBrowserRowSpan, &rowLen, NS_LOCK_SURFACE_READ_ONLY );
644         if ( NS_FAILED ( result ) )
645                 return 0;
646
647         // save row span - it *can* change during the life of the app
648         mBrowserDepth = rowLen / mBrowserWidth;
649
650         // create memory buffer here so it can be deleted and recreated elsewhere
651         if ( ! mPageBuffer )
652                 mPageBuffer = new unsigned char[ mBrowserRowSpan * mBrowserHeight ];
653
654         // save the pixels and optionally invert them
655         // (it's useful the SL client to get bitmaps that are inverted compared
656         // to the way that Mozilla renders them - allow to optionally flip
657         if ( mFlipBitmap )
658         {
659                 for( int y = mBrowserHeight - 1; y > -1; --y )
660                 {
661                         memcpy( mPageBuffer + y * mBrowserRowSpan,
662                                                 data + ( mBrowserHeight - y - 1 ) * mBrowserRowSpan,
663                                                         mBrowserRowSpan );
664                 };
665         }
666         else
667         {
668                 memcpy( mPageBuffer, data, mBrowserRowSpan * mBrowserHeight );
669         };
670
671         // release and destroy the surface we rendered to
672         surface->Unlock();
673         context->DestroyDrawingSurface( surface );
674
675         renderCaret();
676
677         return mPageBuffer;
678 }
679
680 ////////////////////////////////////////////////////////////////////////////////
681 // all this just to render a caret!
682 PRBool LLEmbeddedBrowserWindow::renderCaret()
683 {
684         nsCOMPtr< nsIWebBrowserFocus > focus = do_QueryInterface( mWebBrowser );
685
686         nsCOMPtr< nsIDOMElement > focusedElement;
687         focus->GetFocusedElement( getter_AddRefs( focusedElement ) );
688         if ( ! focusedElement )
689                 return NS_ERROR_FAILURE;
690
691         nsCOMPtr<nsIContent> focusedContent = do_QueryInterface( focusedElement );
692
693         nsCOMPtr< nsIDOMWindow > domWindow;
694         mWebBrowser->GetContentDOMWindow( getter_AddRefs( domWindow ) );
695         if ( ! domWindow )
696                 return NS_ERROR_FAILURE;
697
698         nsCOMPtr< nsIDOMDocument > domDocument;
699         domWindow->GetDocument( getter_AddRefs( domDocument ) );
700         if ( ! domDocument )
701                 return NS_ERROR_FAILURE;
702
703         nsCOMPtr< nsIDocument> document = do_QueryInterface( domDocument );
704         if ( ! document )
705                 return NS_ERROR_FAILURE;
706
707         nsIPresShell* presShell = document->GetShellAt( 0 );
708         if ( ! presShell )
709                 return NS_ERROR_FAILURE;
710
711         nsCOMPtr< nsICaret > caret;
712         presShell->GetCaret( getter_AddRefs( caret ) );
713
714         nsIFrame* frame = nsnull;
715         presShell->GetPrimaryFrameFor( focusedContent, &frame );
716         if ( ! frame )
717                 return NS_ERROR_FAILURE;
718
719         nsCOMPtr<nsISelectionController> selCtrl;
720         frame->GetSelectionController( presShell->GetPresContext(), getter_AddRefs( selCtrl ) );
721
722         nsCOMPtr<nsISelection> selection;
723         selCtrl->GetSelection( nsISelectionController::SELECTION_NORMAL, getter_AddRefs( selection ) );
724
725         PRBool collapsed;
726         nsRect coords;
727         nsIView* caretView;
728         caret->GetCaretCoordinates( nsICaret::eTopLevelWindowCoordinates, selection, &coords, &collapsed, &caretView );
729
730         float twips2Pixls = presShell->GetPresContext()->TwipsToPixels();
731
732         PRInt32 caretX = NSTwipsToIntPixels( coords.x, twips2Pixls );
733         PRInt32 caretY = NSTwipsToIntPixels( coords.y, twips2Pixls );
734         PRInt32 caretHeight = NSTwipsToIntPixels( coords.height, twips2Pixls );
735
736         if ( caretX > -1 && caretX < mBrowserWidth && caretY > -1 && caretY < mBrowserHeight )
737         {
738                 if ( mPageBuffer )
739                 {
740                         for( int y = 1; y < caretHeight - 1; ++y )
741                         {
742                                 PRInt32 base_pos = caretY + y;
743                                 if ( mFlipBitmap )
744                                         base_pos = mBrowserHeight - ( caretY + y );
745
746                                 // sometimes the caret seems valid when it really isn't - cap it to size of screen
747                                 if ( caretY + y + caretHeight < mBrowserHeight )
748                                 {
749                                         mPageBuffer[ base_pos * getBrowserRowSpan() + ( caretX + 1 ) * mBrowserDepth + 0 ] = mCaretBlue;
750                                         mPageBuffer[ base_pos * getBrowserRowSpan() + ( caretX + 1 ) * mBrowserDepth + 1 ] = mCaretGreen;
751                                         mPageBuffer[ base_pos * getBrowserRowSpan() + ( caretX + 1 ) * mBrowserDepth + 2 ] = mCaretRed;
752                                 };
753                         };
754                 };
755         };
756
757         return NS_OK;
758 }
759
760 ////////////////////////////////////////////////////////////////////////////////
761 // return the buffer that contains the rendered page
762 unsigned char* LLEmbeddedBrowserWindow::getPageBuffer()
763 {
764         return mPageBuffer;
765 }
766
767 ////////////////////////////////////////////////////////////////////////////////
768 //
769 PRInt16 LLEmbeddedBrowserWindow::getBrowserWidth()
770 {
771         return mBrowserWidth;
772 }
773
774 ////////////////////////////////////////////////////////////////////////////////
775 //
776 PRInt16 LLEmbeddedBrowserWindow::getBrowserHeight()
777 {
778         return mBrowserHeight;
779 }
780
781 ////////////////////////////////////////////////////////////////////////////////
782 //
783 PRInt16 LLEmbeddedBrowserWindow::getBrowserDepth()
784 {
785         return mBrowserDepth;
786 }
787
788 ////////////////////////////////////////////////////////////////////////////////
789 //
790 PRInt32 LLEmbeddedBrowserWindow::getBrowserRowSpan()
791 {
792         return mBrowserRowSpan;
793 }
794
795 ////////////////////////////////////////////////////////////////////////////////
796 //
797 PRBool LLEmbeddedBrowserWindow::navigateTo( const std::string uriIn )
798 {
799         if ( mWebNav )
800         {
801                 mWebNav->LoadURI( reinterpret_cast< const PRUnichar* >( NS_ConvertUTF8toUTF16( uriIn.c_str() ).get() ),
802                         nsIWebNavigation::LOAD_FLAGS_NONE,
803                                 nsnull, nsnull, nsnull );
804
805                 return PR_TRUE;
806         };
807
808         return PR_FALSE;
809 };
810
811 ////////////////////////////////////////////////////////////////////////////////
812 //
813 PRBool LLEmbeddedBrowserWindow::canNavigateBack()
814 {
815         if ( ! mWebNav )
816         {
817                 return PR_FALSE;
818         };
819
820         PRBool canGoBack = PR_FALSE;
821
822         nsresult result = mWebNav->GetCanGoBack( &canGoBack );
823         if ( NS_FAILED( result ) )
824         {
825                 return PR_FALSE;
826         };
827
828         return canGoBack;
829 };
830
831 ////////////////////////////////////////////////////////////////////////////////
832 //
833 void LLEmbeddedBrowserWindow::navigateStop()
834 {
835         if ( mWebNav )
836                 mWebNav->Stop( nsIWebNavigation::STOP_ALL );
837 };
838
839 ////////////////////////////////////////////////////////////////////////////////
840 //
841 void LLEmbeddedBrowserWindow::navigateBack()
842 {
843         if ( mWebNav )
844                 mWebNav->GoBack();
845 };
846
847 ////////////////////////////////////////////////////////////////////////////////
848 //
849 PRBool LLEmbeddedBrowserWindow::canNavigateForward()
850 {
851         if ( ! mWebNav )
852                 return PR_FALSE;
853
854         PRBool canGoForward = PR_FALSE;
855
856         nsresult result = mWebNav->GetCanGoForward( &canGoForward );
857         if ( NS_FAILED( result ) )
858         {
859                 return PR_FALSE;
860         };
861
862         return canGoForward;
863 };
864
865 ////////////////////////////////////////////////////////////////////////////////
866 //
867 void LLEmbeddedBrowserWindow::navigateForward()
868 {
869         if ( mWebNav )
870                 mWebNav->GoForward();
871 };
872
873 ////////////////////////////////////////////////////////////////////////////////
874 //
875 void LLEmbeddedBrowserWindow::navigateReload()
876 {
877         // maybe need a cache version of this too?
878         if ( mWebNav )
879                 mWebNav->Reload( nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE );
880 };
881
882 ////////////////////////////////////////////////////////////////////////////////
883 // set the size of the browser window
884 PRBool LLEmbeddedBrowserWindow::setSize( PRInt16 widthIn, PRInt16 heightIn )
885 {
886         if ( mBaseWindow )
887         {
888                 // if there is a buffer already, get rid of it (it will get created as required in grabWindow())
889                 if ( mPageBuffer )
890                 {
891                         delete[] mPageBuffer;
892                         mPageBuffer = 0;
893                 };
894
895                 // record new size (important: may change after grabWindow() is called);
896                 mBrowserWidth = widthIn;
897                 mBrowserHeight = heightIn;
898                 mBrowserRowSpan = mBrowserWidth * mBrowserDepth;
899
900                 // On the Mac, these calls do strange things to the main viewer window, and they don't seem necessary in any case.
901                 #ifdef WIN32
902                 // this is the actual OS (on Win32) Window so it needs to be hidden
903                 mBaseWindow->SetVisibility( PR_FALSE );
904
905                 // move WAY off screen (and in a place that makes the combobox hack work)
906                 mBaseWindow->SetPosition( 8000, -6000 );
907                 #endif
908
909                 // tell Mozilla about the new size
910                 mBaseWindow->SetSize( widthIn, heightIn, PR_FALSE );
911
912                 return PR_TRUE;
913         };
914
915         return PR_FALSE;
916 }
917
918 ////////////////////////////////////////////////////////////////////////////////
919 //
920 PRBool LLEmbeddedBrowserWindow::flipWindow( PRBool flip )
921 {
922         mFlipBitmap = flip;
923
924         return true;
925 }
926
927 ////////////////////////////////////////////////////////////////////////////////
928 // higher level mouse event
929 void LLEmbeddedBrowserWindow::mouseLeftDoubleClick( PRInt16 xPosIn, PRInt16 yPosIn )
930 {
931         // Internally Mozilla represents double-click as a 2-count mouse down event.
932         // TODO: support triple-click
933         const PRUint32 clickCount = 2;
934         sendMozillaMouseEvent( NS_MOUSE_LEFT_BUTTON_DOWN, xPosIn, yPosIn, clickCount );
935 }
936
937 ////////////////////////////////////////////////////////////////////////////////
938 // higher level mouse event
939 void LLEmbeddedBrowserWindow::mouseDown( PRInt16 xPosIn, PRInt16 yPosIn )
940 {
941         const PRUint32 clickCount = 1;
942         sendMozillaMouseEvent( NS_MOUSE_LEFT_BUTTON_DOWN, xPosIn, yPosIn, clickCount );
943 }
944
945 ////////////////////////////////////////////////////////////////////////////////
946 // higher level mouse event
947 void LLEmbeddedBrowserWindow::mouseUp( PRInt16 xPosIn, PRInt16 yPosIn )
948 {
949         const PRUint32 clickCount = 1;
950         sendMozillaMouseEvent( NS_MOUSE_LEFT_BUTTON_UP, xPosIn, yPosIn, clickCount );
951 }
952
953 ////////////////////////////////////////////////////////////////////////////////
954 // higher level mouse event
955 void LLEmbeddedBrowserWindow::mouseMove( PRInt16 xPosIn, PRInt16 yPosIn )
956 {
957         const PRUint32 clickCount = 1;  // ignored?
958         sendMozillaMouseEvent( NS_MOUSE_MOVE, xPosIn, yPosIn, clickCount );
959 }
960
961 ////////////////////////////////////////////////////////////////////////////////
962 // utility methods to set an error message so something else can look at it
963 void LLEmbeddedBrowserWindow::scrollByLines( PRInt16 linesIn )
964 {
965         if ( mWebBrowser )
966         {
967                 nsCOMPtr< nsIDOMWindow > window;
968                 nsresult result = mWebBrowser->GetContentDOMWindow( getter_AddRefs( window ) );
969
970                 if ( ! NS_FAILED( result ) && window )
971                 {
972                         result = window->ScrollByLines( linesIn );
973                 };
974         };
975 }
976
977 ////////////////////////////////////////////////////////////////////////////////
978 // synthesizes a mouse event and sends into the embedded instance
979 // eventIn - NS_MOUSE_LEFT_BUTTON_DOWN, NS_MOUSE_LEFT_BUTTON_UP, etc.
980 // xPosIn, yPosIn - coordinates (in browser window space)
981 // clickCountIn - use 1 for single click, 2 for double-click, etc.
982 PRBool LLEmbeddedBrowserWindow::sendMozillaMouseEvent( PRInt16 eventIn, PRInt16 xPosIn, PRInt16 yPosIn, PRUint32 clickCountIn )
983 {
984         if ( ! mEnabled )
985                 return PR_FALSE;
986
987         if ( ! mWebBrowser )
988                 return PR_FALSE;
989
990         nsCOMPtr< nsIDocShell > docShell = do_GetInterface( mWebBrowser );
991         if ( ! docShell )
992                 return PR_FALSE;
993
994         nsCOMPtr< nsPresContext > presContext;
995         nsresult result = docShell->GetPresContext( getter_AddRefs( presContext ) );
996         if ( NS_FAILED( result ) || ( ! presContext ) )
997                 return PR_FALSE;
998
999         nsIViewManager* viewManager = presContext->GetViewManager();
1000         if ( ! viewManager )
1001                 return PR_FALSE;
1002
1003         nsIView* rootView;
1004         result = viewManager->GetRootView( rootView );
1005         if ( NS_FAILED( result ) || ( ! rootView ) )
1006                 return PR_FALSE;
1007
1008         nsCOMPtr< nsIWidget > widget = rootView->GetWidget();
1009         if ( ! widget )
1010                 return PR_FALSE;
1011
1012         nsMouseEvent mouseEvent( PR_TRUE, eventIn, widget, nsMouseEvent::eReal );
1013         mouseEvent.clickCount = clickCountIn;
1014         mouseEvent.isShift = 0;
1015         mouseEvent.isControl = 0;
1016         mouseEvent.isAlt = 0;
1017         mouseEvent.isMeta = 0;
1018         mouseEvent.widget = widget;
1019         mouseEvent.nativeMsg = nsnull;
1020         mouseEvent.point.x = xPosIn;
1021         mouseEvent.point.y = yPosIn;
1022         mouseEvent.refPoint.x = xPosIn;
1023         mouseEvent.refPoint.y = yPosIn;
1024         mouseEvent.flags = 0;
1025
1026         nsEventStatus status;
1027         result = viewManager->DispatchEvent( &mouseEvent, &status );
1028         if ( NS_FAILED( result ) )
1029                 return PR_FALSE;
1030
1031         return PR_TRUE;
1032 };
1033
1034 ////////////////////////////////////////////////////////////////////////////////
1035 // higher level keyboard functions
1036
1037 // accept a (mozilla-style) keycode
1038 void LLEmbeddedBrowserWindow::keyPress( PRInt16 keyCode )
1039 {
1040         sendMozillaKeyboardEvent( 0, keyCode );
1041 }
1042
1043 // accept keyboard input that's already been translated into a unicode char.
1044 void LLEmbeddedBrowserWindow::unicodeInput( PRUint32 uni_char )
1045 {
1046         sendMozillaKeyboardEvent( uni_char, 0 );
1047 }
1048
1049 ////////////////////////////////////////////////////////////////////////////////
1050 // synthesizes a keyboard event and sends into the embedded instance
1051 PRBool LLEmbeddedBrowserWindow::sendMozillaKeyboardEvent( PRUint32 uni_char, PRUint32 ns_vk_code )
1052 {
1053         if ( ! mEnabled )
1054                 return PR_FALSE;
1055
1056         if ( ! mWebBrowser )
1057                 return PR_FALSE;
1058
1059         nsCOMPtr< nsIDocShell > docShell = do_GetInterface( mWebBrowser );
1060         if ( ! docShell )
1061                 return PR_FALSE;
1062
1063         nsCOMPtr< nsPresContext > presContext;
1064         docShell->GetPresContext( getter_AddRefs( presContext ) );
1065         if ( ! presContext )
1066                 return PR_FALSE;
1067
1068         nsIViewManager* viewManager = presContext->GetViewManager();
1069         if ( ! viewManager )
1070                 return PR_FALSE;
1071
1072         nsIView* rootView;
1073         viewManager->GetRootView( rootView );
1074         if ( ! rootView )
1075                 return PR_FALSE;
1076
1077         nsCOMPtr< nsIWidget > widget = rootView->GetWidget();
1078         if ( ! widget )
1079                 return PR_FALSE;
1080
1081         nsKeyEvent keyEvent( PR_TRUE, NS_KEY_PRESS, widget );
1082         keyEvent.keyCode = ns_vk_code;
1083         keyEvent.charCode = uni_char;
1084         keyEvent.isChar = uni_char ? PR_TRUE : PR_FALSE;
1085         keyEvent.isShift = 0;
1086         keyEvent.isControl = 0;
1087         keyEvent.isAlt = 0;
1088         keyEvent.isMeta = 0;
1089         keyEvent.widget = widget;
1090         keyEvent.nativeMsg = nsnull;
1091         keyEvent.point.x = 0;
1092         keyEvent.point.y = 0;
1093         keyEvent.refPoint.x = 0;
1094         keyEvent.refPoint.y = 0;
1095         keyEvent.flags = 0;
1096
1097         nsEventStatus status;
1098         nsresult result = viewManager->DispatchEvent( &keyEvent, &status );
1099         if ( NS_FAILED( result ) )
1100                 return PR_FALSE;
1101
1102         return PR_TRUE;
1103 }
1104
1105 ////////////////////////////////////////////////////////////////////////////////
1106 // override nsIWebBrowserChrome::HandleEvent ()
1107 NS_IMETHODIMP LLEmbeddedBrowserWindow::HandleEvent( nsIDOMEvent* anEvent )
1108 {
1109         nsCOMPtr< nsIDOMEventTarget > eventTarget;
1110         anEvent->GetTarget( getter_AddRefs( eventTarget ) );
1111
1112         nsCOMPtr<nsIDOMElement> linkElement ( do_QueryInterface ( eventTarget ) );
1113         if ( linkElement )
1114         {
1115                 // look for an href link
1116                 nsString name;
1117                 linkElement->GetAttribute( NS_ConvertUTF8toUTF16( "href" ), name );
1118                 mClickHref = std::string( NS_ConvertUTF16toUTF8( name ).get() );
1119
1120                 // look for a target element
1121                 linkElement->GetAttribute( NS_ConvertUTF8toUTF16( "target" ), name );
1122                 mClickTarget = std::string( NS_ConvertUTF16toUTF8( name ).get() );
1123
1124                 // if the href link contains something
1125                 if ( mClickHref.length() )
1126                 {
1127                         LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), mClickHref, mClickTarget );
1128                         mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onClickLinkHref, event );
1129                 };
1130         };
1131
1132         return NS_OK;
1133 };
1134
1135 ////////////////////////////////////////////////////////////////////////////////
1136 // override nsIURIContentListener methods
1137 NS_IMETHODIMP LLEmbeddedBrowserWindow::OnStartURIOpen( nsIURI *aURI, PRBool *_retval )
1138 {
1139         nsCAutoString newURI;
1140         aURI->GetSpec( newURI );
1141         std::string rawUri = newURI.get();
1142
1143         // are we navigating to a 'nofollow' link
1144         if ( mNoFollowScheme.length() && rawUri.substr( 0, mNoFollowScheme.length() ) == mNoFollowScheme )
1145         {
1146                 LLEmbeddedBrowserWindowEvent event( getWindowId(), rawUri, rawUri );
1147                 mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onClickLinkNoFollow, event );
1148
1149                 // tell browser we're handling things and don't follow link
1150                 *_retval = PR_TRUE;
1151         }
1152         else
1153         {
1154                 // tell browser to proceed as normal
1155                 *_retval = PR_FALSE;
1156         };
1157
1158         return NS_OK;
1159 }
1160
1161 ////////////////////////////////////////////////////////////////////////////////
1162 //
1163 void LLEmbeddedBrowserWindow::setNoFollowScheme( std::string schemeIn )
1164 {
1165         mNoFollowScheme = schemeIn;
1166 }
1167
1168 ////////////////////////////////////////////////////////////////////////////////
1169 //
1170 std::string LLEmbeddedBrowserWindow::getNoFollowScheme()
1171 {
1172         return mNoFollowScheme;
1173 }
1174
1175 ////////////////////////////////////////////////////////////////////////////////
1176 //
1177 NS_IMETHODIMP LLEmbeddedBrowserWindow::DoContent( const char *aContentType,
1178                                                                                                         PRBool aIsContentPreferred,
1179                                                                                                                 nsIRequest *aRequest,
1180                                                                                                                         nsIStreamListener **aContentHandler,
1181                                                                                                                                 PRBool *_retval )
1182 {
1183         return NS_ERROR_NOT_IMPLEMENTED;
1184 }
1185
1186 ////////////////////////////////////////////////////////////////////////////////
1187 //
1188 NS_IMETHODIMP LLEmbeddedBrowserWindow::IsPreferred( const char *aContentType,
1189                                                                                                                 char **aDesiredContentType,
1190                                                                                                                         PRBool *_retval )
1191 {
1192         // important (otherwise, links try to open in a new window and trigger the window watcher code)
1193         *_retval = PR_TRUE;
1194         return NS_OK;
1195 }
1196
1197 ////////////////////////////////////////////////////////////////////////////////
1198 //
1199 NS_IMETHODIMP LLEmbeddedBrowserWindow::CanHandleContent( const char *aContentType,
1200                                                                                                                         PRBool aIsContentPreferred,
1201                                                                                                                                 char **aDesiredContentType,
1202                                                                                                                                         PRBool *_retval )
1203 {
1204         return NS_ERROR_NOT_IMPLEMENTED;
1205 }
1206
1207 ////////////////////////////////////////////////////////////////////////////////
1208 //
1209 NS_IMETHODIMP LLEmbeddedBrowserWindow::GetLoadCookie( nsISupports * *aLoadCookie )
1210 {
1211         return NS_ERROR_NOT_IMPLEMENTED;
1212 }
1213
1214 ////////////////////////////////////////////////////////////////////////////////
1215 //
1216 NS_IMETHODIMP LLEmbeddedBrowserWindow::SetLoadCookie( nsISupports * aLoadCookie )
1217 {
1218         return NS_ERROR_NOT_IMPLEMENTED;
1219 }
1220
1221 ////////////////////////////////////////////////////////////////////////////////
1222 //
1223 NS_IMETHODIMP LLEmbeddedBrowserWindow::GetParentContentListener( nsIURIContentListener** aParentContentListener )
1224 {
1225         return NS_ERROR_NOT_IMPLEMENTED;
1226 }
1227
1228 ////////////////////////////////////////////////////////////////////////////////
1229 //
1230 NS_IMETHODIMP LLEmbeddedBrowserWindow::SetParentContentListener( nsIURIContentListener* aParentContentListener )
1231 {
1232         return NS_ERROR_NOT_IMPLEMENTED;
1233 }
1234
1235 ////////////////////////////////////////////////////////////////////////////////
1236 // give focus to the browser so that input keyboard events work
1237 void LLEmbeddedBrowserWindow::focusBrowser( PRBool focusBrowserIn )
1238 {
1239         if ( mWebBrowser )
1240         {
1241                 if ( focusBrowserIn )
1242                 {
1243                         nsCOMPtr< nsIWebBrowserFocus > focus( do_GetInterface( mWebBrowser ) );
1244                         focus->Activate();
1245                 }
1246                 else
1247                 {
1248                         nsCOMPtr< nsIWebBrowserFocus > focus( do_GetInterface( mWebBrowser ) );
1249                         focus->Deactivate();
1250                 };
1251         };
1252 }
1253
1254 ////////////////////////////////////////////////////////////////////////////////
1255 //
1256 void LLEmbeddedBrowserWindow::setWindowId( int windowIdIn )
1257 {
1258         mWindowId = windowIdIn;
1259 }
1260
1261 ////////////////////////////////////////////////////////////////////////////////
1262 //
1263 int LLEmbeddedBrowserWindow::getWindowId()
1264 {
1265         //printf("## Getting id for %p and it is %d\n", this, mWindowId );
1266
1267         return mWindowId;
1268 }
1269
1270 ////////////////////////////////////////////////////////////////////////////////
1271 // add / remove the toolkit (and therefore 'page changed') observer
1272 PRBool LLEmbeddedBrowserWindow::enableToolkitObserver( PRBool enableIn )
1273 {
1274         //TODO: AddObserver fails if I grab the toolkit this way.
1275         //static NS_DEFINE_CID(kNS_TOOLKIT_CID, NS_TOOLKIT_CID);
1276         //nsresult result1;
1277         //nsCOMPtr< nsIToolkit > toolkit = do_GetService( kNS_TOOLKIT_CID, &result1 );
1278         //if ( ( result1 == NS_OK ) && toolkit )
1279         //{
1280         //      if ( toolkit->AddObserver( this ) )
1281         //      {
1282         //              return true;
1283         //      };
1284         //};
1285         //return false;
1286
1287         // TODO: this is horrible but seems to work - need a better way to get the toolkit
1288         nsCOMPtr< nsIDocShell > docShell = do_GetInterface( mWebBrowser );
1289         if ( ! docShell )
1290                 return false;
1291
1292         nsCOMPtr< nsPresContext > presContext;
1293         nsresult result = docShell->GetPresContext( getter_AddRefs( presContext ) );
1294         if ( NS_FAILED( result ) || ( ! presContext ) )
1295                 return false;
1296
1297         nsIViewManager* viewManager = presContext->GetViewManager();
1298         if ( ! viewManager )
1299                 return false;
1300
1301         nsIView* rootView;
1302         result = viewManager->GetRootView( rootView );
1303         if ( NS_FAILED( result ) || ( ! rootView ) )
1304                 return false;
1305
1306         nsCOMPtr< nsIWidget > widget = rootView->GetWidget();
1307         if ( ! widget )
1308                 return false;
1309
1310         nsCOMPtr< nsIToolkit > mToolkit = widget->GetToolkit();
1311         if ( ! mToolkit )
1312                 return false;
1313
1314         if ( enableIn )
1315                 mToolkit->AddObserver( this );
1316         else
1317                 mToolkit->RemoveObserver( this );
1318
1319         return true;
1320 }
1321
1322 ////////////////////////////////////////////////////////////////////////////////
1323 // something on the page changed - e.g. a new page loaded, scrolling, user
1324 // input or as the result of some kind of animation.
1325 // NOTE: we don't call grabWindow here as this can stall graphics apps -
1326 //       we merely pass back an event to the app and let it decide when/if
1327 //       to call grabWindow()
1328 NS_METHOD LLEmbeddedBrowserWindow::NotifyInvalidated( nsIWidget *aWidget, PRInt32 x, PRInt32 y, PRInt32 width, PRInt32 height )
1329 {
1330 //      printf("LLEmbeddedBrowserWindow::NotifyInvalidated(%p, %d, %d, %d, %d)\n", (void*)aWidget, (int)x, (int)y, (int)width, (int)height);
1331
1332         // try to match widget-window against ourselves to see if we need to update the texture
1333         // only works using native widgets (on Windows) at the moment - needs to be moved to platform agnostic code ASAP
1334         #ifdef WIN32
1335
1336         // this is horrible beyond words but it seems to work...
1337         // nsToolkit tells us that a widget changed and we need to see if it's this instance
1338         // so we can emit an event that causes the parent app to update the browser texture
1339         nsIWidget* mainWidget;
1340         mBaseWindow->GetMainWidget( &mainWidget );
1341
1342         HWND nativeWidget = (HWND)aWidget->GetNativeData( NS_NATIVE_WIDGET );
1343         HWND nativeWidgetChild = 0;
1344         while ( ::GetParent( nativeWidget ) )
1345         {
1346                 nativeWidgetChild = nativeWidget;
1347                 nativeWidget = ::GetParent( nativeWidget );
1348         };
1349
1350         if ( ( (HWND)mainWidget->GetNativeData( NS_NATIVE_WIDGET ) ) == nativeWidgetChild )
1351         {
1352                 LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), x, y, width, height );
1353                 mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onPageChanged, event );
1354         };
1355
1356         // other platforms will always update - desperately inefficient but you'll see something.
1357         #else
1358                 LLEmbeddedBrowserWindowEvent event( getWindowId(), getCurrentUri(), x, y, width, height );
1359                 mEventEmitter.update( &LLEmbeddedBrowserWindowObserver::onPageChanged, event );
1360         #endif
1361
1362         return NS_OK;
1363 }
1364
1365 ////////////////////////////////////////////////////////////////////////////////
1366 //
1367 std::string LLEmbeddedBrowserWindow::evaluateJavascript( std::string scriptIn )
1368 {
1369         nsCOMPtr< nsIScriptGlobalObjectOwner > theGlobalObjectOwner( do_GetInterface( mWebBrowser ) );
1370
1371         if ( theGlobalObjectOwner )
1372         {
1373                 nsIScriptGlobalObject* theGlobalObject;
1374                 theGlobalObject = theGlobalObjectOwner->GetScriptGlobalObject();
1375
1376                 nsIScriptContext* theScriptContext = theGlobalObject->GetContext();
1377
1378                 PRBool IsUndefined;
1379                 nsString output;
1380                 nsresult result = theScriptContext->EvaluateString(NS_ConvertUTF8toUTF16(scriptIn.c_str()),
1381                    nsnull, nsnull, "", 1, nsnull, &output, &IsUndefined);
1382
1383                 if( NS_FAILED( result ) )
1384                         return "";
1385
1386                 return std::string( NS_ConvertUTF16toUTF8( output ).get() );
1387         }
1388
1389         return "";
1390 }
1391
1392 ////////////////////////////////////////////////////////////////////////////////
1393 //
1394 bool LLEmbeddedBrowserWindow::set404RedirectUrl( std::string redirect_url )
1395 {
1396         m404RedirectUrl = redirect_url;
1397
1398         return true;
1399 }
1400
1401 ////////////////////////////////////////////////////////////////////////////////
1402 //
1403 bool LLEmbeddedBrowserWindow::clr404RedirectUrl()
1404 {
1405         m404RedirectUrl = std::string( "" );
1406
1407         return true;
1408 }
1409
1410 // #define required by this file for LibXUL/Mozilla code to avoid crashes in their debug code
1411 #ifdef _DEBUG
1412         #ifdef WIN32
1413                 #undef DEBUG
1414         #endif
1415 #endif
Note: See TracBrowser for help on using the browser.