Back to index

lightning-sunbird  0.9+nobinonly
EmbedPrivate.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright (C) Christopher Blizzard.  All Rights Reserved.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Christopher Blizzard <blizzard@mozilla.org>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <nsIDocShell.h>
00039 #include <nsIWebProgress.h>
00040 #include "nsIWidget.h"
00041 #include "nsCRT.h"
00042 #include "nsNetUtil.h"
00043 #include "nsIWebBrowserStream.h"
00044 #include "nsIWebBrowserFocus.h"
00045 
00046 // for NS_APPSHELL_CID
00047 #include <nsWidgetsCID.h>
00048 
00049 // for do_GetInterface
00050 #include <nsIInterfaceRequestor.h>
00051 // for do_CreateInstance
00052 #include <nsIComponentManager.h>
00053 
00054 // for initializing our window watcher service
00055 #include <nsIWindowWatcher.h>
00056 
00057 #include <nsILocalFile.h>
00058 #include <nsEmbedAPI.h>
00059 
00060 // all of the crap that we need for event listeners
00061 // and when chrome windows finish loading
00062 #include <nsIDOMWindow.h>
00063 #include <nsPIDOMWindow.h>
00064 #include <nsIDOMWindowInternal.h>
00065 #include <nsIChromeEventHandler.h>
00066 
00067 // For seting scrollbar visibilty
00068 #include <nsIDOMBarProp.h>
00069 
00070 // for the focus hacking we need to do
00071 #include <nsIFocusController.h>
00072 
00073 // for profiles
00074 #include <nsProfileDirServiceProvider.h>
00075 
00076 // app component registration
00077 #include <nsIGenericFactory.h>
00078 #include <nsIComponentRegistrar.h>
00079 
00080 // all of our local includes
00081 #include "EmbedPrivate.h"
00082 #include "EmbedWindow.h"
00083 #include "EmbedProgress.h"
00084 #include "EmbedContentListener.h"
00085 #include "EmbedEventListener.h"
00086 #include "EmbedWindowCreator.h"
00087 #ifdef MOZ_WIDGET_GTK2
00088 #include "GtkPromptService.h"
00089 #else
00090 #include "nsNativeCharsetUtils.h"
00091 #endif
00092 
00093 #ifdef MOZ_ACCESSIBILITY_ATK
00094 #include "nsIAccessibilityService.h"
00095 #include "nsIAccessible.h"
00096 #include "nsIDOMDocument.h"
00097 #endif
00098 
00099 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
00100 
00101 PRUint32     EmbedPrivate::sWidgetCount = 0;
00102 char        *EmbedPrivate::sCompPath    = nsnull;
00103 nsIAppShell *EmbedPrivate::sAppShell    = nsnull;
00104 nsVoidArray *EmbedPrivate::sWindowList  = nsnull;
00105 char        *EmbedPrivate::sProfileDir  = nsnull;
00106 char        *EmbedPrivate::sProfileName = nsnull;
00107 nsIPref     *EmbedPrivate::sPrefs       = nsnull;
00108 GtkWidget   *EmbedPrivate::sOffscreenWindow = 0;
00109 GtkWidget   *EmbedPrivate::sOffscreenFixed  = 0;
00110 nsIDirectoryServiceProvider *EmbedPrivate::sAppFileLocProvider = nsnull;
00111 nsProfileDirServiceProvider *EmbedPrivate::sProfileDirServiceProvider = nsnull;
00112 
00113 #define NS_PROMPTSERVICE_CID \
00114  {0x95611356, 0xf583, 0x46f5, {0x81, 0xff, 0x4b, 0x3e, 0x01, 0x62, 0xc6, 0x19}}
00115 
00116 #ifdef MOZ_WIDGET_GTK2
00117 NS_GENERIC_FACTORY_CONSTRUCTOR(GtkPromptService)
00118 #endif
00119 
00120 #ifdef MOZ_WIDGET_GTK2
00121 
00122 static const nsModuleComponentInfo defaultAppComps[] = {
00123   {
00124     "Prompt Service",
00125     NS_PROMPTSERVICE_CID,
00126     "@mozilla.org/embedcomp/prompt-service;1",
00127     GtkPromptServiceConstructor
00128   }
00129 };
00130 
00131 const nsModuleComponentInfo *EmbedPrivate::sAppComps = defaultAppComps;
00132 int   EmbedPrivate::sNumAppComps = sizeof(defaultAppComps) / sizeof(nsModuleComponentInfo);
00133 
00134 #else
00135 
00136 const nsModuleComponentInfo *EmbedPrivate::sAppComps = nsnull;
00137 int   EmbedPrivate::sNumAppComps = 0;
00138 
00139 #endif
00140 
00141 EmbedPrivate::EmbedPrivate(void)
00142 {
00143   mOwningWidget     = nsnull;
00144   mWindow           = nsnull;
00145   mProgress         = nsnull;
00146   mContentListener  = nsnull;
00147   mEventListener    = nsnull;
00148   mChromeMask       = nsIWebBrowserChrome::CHROME_ALL;
00149   mIsChrome         = PR_FALSE;
00150   mChromeLoaded     = PR_FALSE;
00151   mListenersAttached = PR_FALSE;
00152   mMozWindowWidget  = 0;
00153   mIsDestroyed      = PR_FALSE;
00154 
00155   PushStartup();
00156   if (!sWindowList) {
00157     sWindowList = new nsVoidArray();
00158   }
00159   sWindowList->AppendElement(this);
00160 }
00161 
00162 EmbedPrivate::~EmbedPrivate()
00163 {
00164   sWindowList->RemoveElement(this);
00165   PopStartup();
00166 }
00167 
00168 nsresult
00169 EmbedPrivate::Init(GtkMozEmbed *aOwningWidget)
00170 {
00171   // are we being re-initialized?
00172   if (mOwningWidget)
00173     return NS_OK;
00174 
00175   // hang on with a reference to the owning widget
00176   mOwningWidget = aOwningWidget;
00177 
00178   // Create our embed window, and create an owning reference to it and
00179   // initialize it.  It is assumed that this window will be destroyed
00180   // when we go out of scope.
00181   mWindow = new EmbedWindow();
00182   mWindowGuard = NS_STATIC_CAST(nsIWebBrowserChrome *, mWindow);
00183   mWindow->Init(this);
00184 
00185   // Create our progress listener object, make an owning reference,
00186   // and initialize it.  It is assumed that this progress listener
00187   // will be destroyed when we go out of scope.
00188   mProgress = new EmbedProgress();
00189   mProgressGuard = NS_STATIC_CAST(nsIWebProgressListener *,
00190                                    mProgress);
00191   mProgress->Init(this);
00192 
00193   // Create our content listener object, initialize it and attach it.
00194   // It is assumed that this will be destroyed when we go out of
00195   // scope.
00196   mContentListener = new EmbedContentListener();
00197   mContentListenerGuard = NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(nsIURIContentListener*, mContentListener));
00198   mContentListener->Init(this);
00199 
00200   // Create our key listener object and initialize it.  It is assumed
00201   // that this will be destroyed before we go out of scope.
00202   mEventListener = new EmbedEventListener();
00203   mEventListenerGuard =
00204     NS_STATIC_CAST(nsISupports *, NS_STATIC_CAST(nsIDOMKeyListener *,
00205                                            mEventListener));
00206   mEventListener->Init(this);
00207 
00208   // has the window creator service been set up?
00209   static int initialized = PR_FALSE;
00210   // Set up our window creator ( only once )
00211   if (!initialized) {
00212     // We set this flag here instead of on success.  If it failed we
00213     // don't want to keep trying and leaking window creator objects.
00214     initialized = PR_TRUE;
00215 
00216     // create our local object
00217     EmbedWindowCreator *creator = new EmbedWindowCreator();
00218     nsCOMPtr<nsIWindowCreator> windowCreator;
00219     windowCreator = NS_STATIC_CAST(nsIWindowCreator *, creator);
00220 
00221     // Attach it via the watcher service
00222     nsCOMPtr<nsIWindowWatcher> watcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
00223     if (watcher)
00224       watcher->SetWindowCreator(windowCreator);
00225   }
00226   return NS_OK;
00227 }
00228 
00229 nsresult
00230 EmbedPrivate::Realize(PRBool *aAlreadyRealized)
00231 {
00232 
00233   *aAlreadyRealized = PR_FALSE;
00234 
00235   // create the offscreen window if we have to
00236   EnsureOffscreenWindow();
00237 
00238   // Have we ever been initialized before?  If so then just reparetn
00239   // from the offscreen window.
00240   if (mMozWindowWidget) {
00241     gtk_widget_reparent(mMozWindowWidget, GTK_WIDGET(mOwningWidget));
00242     *aAlreadyRealized = PR_TRUE;
00243     return NS_OK;
00244   }
00245 
00246   // Get the nsIWebBrowser object for our embedded window.
00247   nsCOMPtr<nsIWebBrowser> webBrowser;
00248   mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00249 
00250   // get a handle on the navigation object
00251   mNavigation = do_QueryInterface(webBrowser);
00252 
00253   // Create our session history object and tell the navigation object
00254   // to use it.  We need to do this before we create the web browser
00255   // window.
00256   mSessionHistory = do_CreateInstance(NS_SHISTORY_CONTRACTID);
00257   mNavigation->SetSessionHistory(mSessionHistory);
00258 
00259   // create the window
00260   mWindow->CreateWindow();
00261 
00262   // bind the progress listener to the browser object
00263   nsCOMPtr<nsISupportsWeakReference> supportsWeak;
00264   supportsWeak = do_QueryInterface(mProgressGuard);
00265   nsCOMPtr<nsIWeakReference> weakRef;
00266   supportsWeak->GetWeakReference(getter_AddRefs(weakRef));
00267   webBrowser->AddWebBrowserListener(weakRef,
00268                                 nsIWebProgressListener::GetIID());
00269 
00270   // set ourselves as the parent uri content listener
00271   nsCOMPtr<nsIURIContentListener> uriListener;
00272   uriListener = do_QueryInterface(mContentListenerGuard);
00273   webBrowser->SetParentURIContentListener(uriListener);
00274 
00275   // save the window id of the newly created window
00276   nsCOMPtr<nsIWidget> mozWidget;
00277   mWindow->mBaseWindow->GetMainWidget(getter_AddRefs(mozWidget));
00278   // get the native drawing area
00279   GdkWindow *tmp_window =
00280     NS_STATIC_CAST(GdkWindow *,
00281                  mozWidget->GetNativeData(NS_NATIVE_WINDOW));
00282   // and, thanks to superwin we actually need the parent of that.
00283   tmp_window = gdk_window_get_parent(tmp_window);
00284   // save the widget ID - it should be the mozarea of the window.
00285   gpointer data = nsnull;
00286   gdk_window_get_user_data(tmp_window, &data);
00287   mMozWindowWidget = NS_STATIC_CAST(GtkWidget *, data);
00288 
00289   // Apply the current chrome mask
00290   ApplyChromeMask();
00291 
00292   return NS_OK;
00293 }
00294 
00295 void
00296 EmbedPrivate::Unrealize(void)
00297 {
00298   // reparent to our offscreen window
00299   gtk_widget_reparent(mMozWindowWidget, sOffscreenFixed);
00300 }
00301 
00302 void
00303 EmbedPrivate::Show(void)
00304 {
00305   // Get the nsIWebBrowser object for our embedded window.
00306   nsCOMPtr<nsIWebBrowser> webBrowser;
00307   mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00308 
00309   // and set the visibility on the thing
00310   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(webBrowser);
00311   baseWindow->SetVisibility(PR_TRUE);
00312 }
00313 
00314 void
00315 EmbedPrivate::Hide(void)
00316 {
00317   // Get the nsIWebBrowser object for our embedded window.
00318   nsCOMPtr<nsIWebBrowser> webBrowser;
00319   mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00320 
00321   // and set the visibility on the thing
00322   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(webBrowser);
00323   baseWindow->SetVisibility(PR_FALSE);
00324 }
00325 
00326 void
00327 EmbedPrivate::Resize(PRUint32 aWidth, PRUint32 aHeight)
00328 {
00329   mWindow->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION |
00330                       nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER,
00331                       0, 0, aWidth, aHeight);
00332 }
00333 
00334 void
00335 EmbedPrivate::Destroy(void)
00336 {
00337   // This flag might have been set from
00338   // EmbedWindow::DestroyBrowserWindow() as well if someone used a
00339   // window.close() or something or some other script action to close
00340   // the window.  No harm setting it again.
00341   mIsDestroyed = PR_TRUE;
00342 
00343   // Get the nsIWebBrowser object for our embedded window.
00344   nsCOMPtr<nsIWebBrowser> webBrowser;
00345   mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00346 
00347   // Release our progress listener
00348   nsCOMPtr<nsISupportsWeakReference> supportsWeak;
00349   supportsWeak = do_QueryInterface(mProgressGuard);
00350   nsCOMPtr<nsIWeakReference> weakRef;
00351   supportsWeak->GetWeakReference(getter_AddRefs(weakRef));
00352   webBrowser->RemoveWebBrowserListener(weakRef,
00353                                    nsIWebProgressListener::GetIID());
00354   weakRef = nsnull;
00355   supportsWeak = nsnull;
00356 
00357   // Release our content listener
00358   webBrowser->SetParentURIContentListener(nsnull);
00359   mContentListenerGuard = nsnull;
00360   mContentListener = nsnull;
00361 
00362   // Now that we have removed the listener, release our progress
00363   // object
00364   mProgressGuard = nsnull;
00365   mProgress = nsnull;
00366 
00367   // detach our event listeners and release the event receiver
00368   DetachListeners();
00369   if (mEventReceiver)
00370     mEventReceiver = nsnull;
00371 
00372   // destroy our child window
00373   mWindow->ReleaseChildren();
00374 
00375   // release navigation
00376   mNavigation = nsnull;
00377 
00378   // release session history
00379   mSessionHistory = nsnull;
00380 
00381   mOwningWidget = nsnull;
00382 
00383   mMozWindowWidget = 0;
00384 }
00385 
00386 void
00387 EmbedPrivate::SetURI(const char *aURI)
00388 {
00389 #ifdef MOZ_WIDGET_GTK
00390   // XXX: Even though NS_CopyNativeToUnicode is not designed for non-filenames,
00391   // we know that it will do "the right thing" on UNIX.
00392   NS_CopyNativeToUnicode(nsDependentCString(aURI), mURI);
00393 #endif
00394 
00395 #ifdef MOZ_WIDGET_GTK2
00396   CopyUTF8toUTF16(aURI, mURI);
00397 #endif
00398 }
00399 
00400 void
00401 EmbedPrivate::LoadCurrentURI(void)
00402 {
00403   if (mURI.Length()) {
00404     nsCOMPtr<nsPIDOMWindow> piWin;
00405     GetPIDOMWindow(getter_AddRefs(piWin));
00406 
00407     nsAutoPopupStatePusher popupStatePusher(piWin, openAllowed);
00408 
00409     mNavigation->LoadURI(mURI.get(),                        // URI string
00410                          nsIWebNavigation::LOAD_FLAGS_NONE, // Load flags
00411                          nsnull,                            // Referring URI
00412                          nsnull,                            // Post data
00413                          nsnull);                           // extra headers
00414   }
00415 }
00416 
00417 void
00418 EmbedPrivate::Reload(PRUint32 reloadFlags)
00419 {
00420   /* Use the session history if it is available, this
00421    * allows framesets to reload correctly */
00422   nsCOMPtr<nsIWebNavigation> wn;
00423 
00424   if (mSessionHistory) {
00425     wn = do_QueryInterface(mSessionHistory);
00426   }
00427   if (!wn)
00428     wn = mNavigation;
00429 
00430   if (wn)
00431     wn->Reload(reloadFlags);
00432 }
00433 
00434 
00435 void
00436 EmbedPrivate::ApplyChromeMask()
00437 {
00438    if (mWindow) {
00439       nsCOMPtr<nsIWebBrowser> webBrowser;
00440       mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00441 
00442       nsCOMPtr<nsIDOMWindow> domWindow;
00443       webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
00444       if (domWindow) {
00445 
00446          nsCOMPtr<nsIDOMBarProp> scrollbars;
00447          domWindow->GetScrollbars(getter_AddRefs(scrollbars));
00448          if (scrollbars) {
00449 
00450             scrollbars->SetVisible
00451                (mChromeMask & nsIWebBrowserChrome::CHROME_SCROLLBARS ?
00452                 PR_TRUE : PR_FALSE);
00453          }
00454       }
00455    }
00456 }
00457 
00458 
00459 void
00460 EmbedPrivate::SetChromeMask(PRUint32 aChromeMask)
00461 {
00462    mChromeMask = aChromeMask;
00463 
00464    ApplyChromeMask();
00465 }
00466 
00467 
00468 /* static */
00469 void
00470 EmbedPrivate::PushStartup(void)
00471 {
00472   // increment the number of widgets
00473   sWidgetCount++;
00474 
00475   // if this is the first widget, fire up xpcom
00476   if (sWidgetCount == 1) {
00477     nsresult rv;
00478     nsCOMPtr<nsILocalFile> binDir;
00479 
00480     if (sCompPath) {
00481       rv = NS_NewNativeLocalFile(nsDependentCString(sCompPath), 1, getter_AddRefs(binDir));
00482       if (NS_FAILED(rv))
00483        return;
00484     }
00485 
00486     rv = NS_InitEmbedding(binDir, sAppFileLocProvider);
00487     if (NS_FAILED(rv))
00488       return;
00489 
00490     // we no longer need a reference to the DirectoryServiceProvider
00491     if (sAppFileLocProvider) {
00492       NS_RELEASE(sAppFileLocProvider);
00493       sAppFileLocProvider = nsnull;
00494     }
00495 
00496     rv = StartupProfile();
00497     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Warning: Failed to start up profiles.\n");
00498 
00499     rv = RegisterAppComponents();
00500     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Warning: Failed to register app components.\n");
00501 
00502     // XXX startup appshell service?
00503     // XXX create offscreen window for appshell service?
00504     // XXX remove X prop from offscreen window?
00505 
00506     nsCOMPtr<nsIAppShell> appShell;
00507     appShell = do_CreateInstance(kAppShellCID);
00508     if (!appShell) {
00509       NS_WARNING("Failed to create appshell in EmbedPrivate::PushStartup!\n");
00510       return;
00511     }
00512     sAppShell = appShell.get();
00513     NS_ADDREF(sAppShell);
00514     sAppShell->Create(0, nsnull);
00515     sAppShell->Spinup();
00516   }
00517 }
00518 
00519 /* static */
00520 void
00521 EmbedPrivate::PopStartup(void)
00522 {
00523   sWidgetCount--;
00524   if (sWidgetCount == 0) {
00525 
00526     // destroy the offscreen window
00527     DestroyOffscreenWindow();
00528 
00529     // shut down the profiles
00530     ShutdownProfile();
00531 
00532     if (sAppShell) {
00533       // Shutdown the appshell service.
00534       sAppShell->Spindown();
00535       NS_RELEASE(sAppShell);
00536       sAppShell = 0;
00537     }
00538 
00539     // shut down XPCOM/Embedding
00540     NS_TermEmbedding();
00541   }
00542 }
00543 
00544 /* static */
00545 void
00546 EmbedPrivate::SetCompPath(const char *aPath)
00547 {
00548   if (sCompPath)
00549     free(sCompPath);
00550   if (aPath)
00551     sCompPath = strdup(aPath);
00552   else
00553     sCompPath = nsnull;
00554 }
00555 
00556 /* static */
00557 void
00558 EmbedPrivate::SetAppComponents(const nsModuleComponentInfo* aComps,
00559                                int aNumComponents)
00560 {
00561   sAppComps = aComps;
00562   sNumAppComps = aNumComponents;
00563 }
00564 
00565 /* static */
00566 void
00567 EmbedPrivate::SetProfilePath(const char *aDir, const char *aName)
00568 {
00569   if (sProfileDir) {
00570     nsMemory::Free(sProfileDir);
00571     sProfileDir = nsnull;
00572   }
00573 
00574   if (sProfileName) {
00575     nsMemory::Free(sProfileName);
00576     sProfileName = nsnull;
00577   }
00578 
00579   if (aDir)
00580     sProfileDir = (char *)nsMemory::Clone(aDir, strlen(aDir) + 1);
00581 
00582   if (aName)
00583     sProfileName = (char *)nsMemory::Clone(aName, strlen(aName) + 1);
00584 }
00585 
00586 void
00587 EmbedPrivate::SetDirectoryServiceProvider(nsIDirectoryServiceProvider * appFileLocProvider)
00588 {
00589   if (sAppFileLocProvider)
00590     NS_RELEASE(sAppFileLocProvider);
00591 
00592   if (appFileLocProvider) {
00593     sAppFileLocProvider = appFileLocProvider;
00594     NS_ADDREF(sAppFileLocProvider);
00595   }
00596 }
00597 
00598 nsresult
00599 EmbedPrivate::OpenStream(const char *aBaseURI, const char *aContentType)
00600 {
00601   nsCOMPtr<nsIWebBrowser> webBrowser;
00602   mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00603 
00604   nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
00605   if (!wbStream) return NS_ERROR_FAILURE;
00606 
00607   nsCOMPtr<nsIURI> uri;
00608   nsresult rv = NS_NewURI(getter_AddRefs(uri), aBaseURI);
00609   if (NS_FAILED(rv))
00610     return rv;
00611 
00612   rv = wbStream->OpenStream(uri, nsDependentCString(aContentType));
00613   return rv;
00614 }
00615 
00616 nsresult
00617 EmbedPrivate::AppendToStream(const PRUint8 *aData, PRUint32 aLen)
00618 {
00619   // Attach listeners to this document since in some cases we don't
00620   // get updates for content added this way.
00621   ContentStateChange();
00622 
00623   nsCOMPtr<nsIWebBrowser> webBrowser;
00624   mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00625 
00626   nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
00627   if (!wbStream) return NS_ERROR_FAILURE;
00628 
00629   return wbStream->AppendToStream(aData, aLen);
00630 }
00631 
00632 nsresult
00633 EmbedPrivate::CloseStream(void)
00634 {
00635   nsCOMPtr<nsIWebBrowser> webBrowser;
00636   mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00637 
00638   nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
00639   if (!wbStream) return NS_ERROR_FAILURE;
00640 
00641   return wbStream->CloseStream();
00642 }
00643 
00644 /* static */
00645 EmbedPrivate *
00646 EmbedPrivate::FindPrivateForBrowser(nsIWebBrowserChrome *aBrowser)
00647 {
00648   if (!sWindowList)
00649     return nsnull;
00650 
00651   // Get the number of browser windows.
00652   PRInt32 count = sWindowList->Count();
00653   // This function doesn't get called very often at all ( only when
00654   // creating a new window ) so it's OK to walk the list of open
00655   // windows.
00656   for (int i = 0; i < count; i++) {
00657     EmbedPrivate *tmpPrivate = NS_STATIC_CAST(EmbedPrivate *,
00658                                          sWindowList->ElementAt(i));
00659     // get the browser object for that window
00660     nsIWebBrowserChrome *chrome = NS_STATIC_CAST(nsIWebBrowserChrome *,
00661                                            tmpPrivate->mWindow);
00662     if (chrome == aBrowser)
00663       return tmpPrivate;
00664   }
00665 
00666   return nsnull;
00667 }
00668 
00669 void
00670 EmbedPrivate::ContentStateChange(void)
00671 {
00672 
00673   // we don't attach listeners to chrome
00674   if (mListenersAttached && !mIsChrome)
00675     return;
00676 
00677   GetListener();
00678 
00679   if (!mEventReceiver)
00680     return;
00681 
00682   AttachListeners();
00683 
00684 }
00685 
00686 void
00687 EmbedPrivate::ContentFinishedLoading(void)
00688 {
00689   if (mIsChrome) {
00690     // We're done loading.
00691     mChromeLoaded = PR_TRUE;
00692 
00693     // get the web browser
00694     nsCOMPtr<nsIWebBrowser> webBrowser;
00695     mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00696 
00697     // get the content DOM window for that web browser
00698     nsCOMPtr<nsIDOMWindow> domWindow;
00699     webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
00700     if (!domWindow) {
00701       NS_WARNING("no dom window in content finished loading\n");
00702       return;
00703     }
00704 
00705     // resize the content
00706     domWindow->SizeToContent();
00707 
00708     // and since we're done loading show the window, assuming that the
00709     // visibility flag has been set.
00710     PRBool visibility;
00711     mWindow->GetVisibility(&visibility);
00712     if (visibility)
00713       mWindow->SetVisibility(PR_TRUE);
00714   }
00715 }
00716 
00717 #ifdef MOZ_WIDGET_GTK
00718 // handle focus in and focus out events
00719 void
00720 EmbedPrivate::TopLevelFocusIn(void)
00721 {
00722   if (mIsDestroyed)
00723     return;
00724 
00725   nsCOMPtr<nsPIDOMWindow> piWin;
00726   GetPIDOMWindow(getter_AddRefs(piWin));
00727 
00728   if (!piWin)
00729     return;
00730 
00731   nsIFocusController *focusController = piWin->GetRootFocusController();
00732   if (focusController)
00733     focusController->SetActive(PR_TRUE);
00734 }
00735 
00736 void
00737 EmbedPrivate::TopLevelFocusOut(void)
00738 {
00739   if (mIsDestroyed)
00740     return;
00741 
00742   nsCOMPtr<nsPIDOMWindow> piWin;
00743   GetPIDOMWindow(getter_AddRefs(piWin));
00744 
00745   if (!piWin)
00746     return;
00747 
00748   nsIFocusController *focusController = piWin->GetRootFocusController();
00749   if (focusController)
00750     focusController->SetActive(PR_FALSE);
00751 }
00752 #endif /* MOZ_WIDGET_GTK */
00753 
00754 void
00755 EmbedPrivate::ChildFocusIn(void)
00756 {
00757   if (mIsDestroyed)
00758     return;
00759 
00760 #ifdef MOZ_WIDGET_GTK2
00761   nsresult rv;
00762   nsCOMPtr<nsIWebBrowser> webBrowser;
00763   rv = mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00764   if (NS_FAILED(rv))
00765     return;
00766 
00767   nsCOMPtr<nsIWebBrowserFocus> webBrowserFocus(do_QueryInterface(webBrowser));
00768   if (!webBrowserFocus)
00769     return;
00770   
00771   webBrowserFocus->Activate();
00772 #endif /* MOZ_WIDGET_GTK2 */
00773 
00774 #ifdef MOZ_WIDGET_GTK
00775   nsCOMPtr<nsPIDOMWindow> piWin;
00776   GetPIDOMWindow(getter_AddRefs(piWin));
00777 
00778   if (!piWin)
00779     return;
00780 
00781   piWin->Activate();
00782 #endif /* MOZ_WIDGET_GTK */
00783 }
00784 
00785 void
00786 EmbedPrivate::ChildFocusOut(void)
00787 {
00788   if (mIsDestroyed)
00789     return;
00790 
00791 #ifdef MOZ_WIDGET_GTK2
00792   nsresult rv;
00793   nsCOMPtr<nsIWebBrowser> webBrowser;
00794   rv = mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00795   if (NS_FAILED(rv))
00796          return;
00797 
00798   nsCOMPtr<nsIWebBrowserFocus> webBrowserFocus(do_QueryInterface(webBrowser));
00799   if (!webBrowserFocus)
00800          return;
00801   
00802   webBrowserFocus->Deactivate();
00803 #endif /* MOZ_WIDGET_GTK2 */
00804 
00805 #ifdef MOZ_WIDGET_GTK
00806   nsCOMPtr<nsPIDOMWindow> piWin;
00807   GetPIDOMWindow(getter_AddRefs(piWin));
00808 
00809   if (!piWin)
00810     return;
00811 
00812   piWin->Deactivate();
00813 
00814   // but the window is still active until the toplevel gets a focus
00815   // out
00816   nsIFocusController *focusController = piWin->GetRootFocusController();
00817   if (focusController)
00818     focusController->SetActive(PR_TRUE);
00819 #endif /* MOZ_WIDGET_GTK */
00820 }
00821 
00822 // Get the event listener for the chrome event handler.
00823 
00824 void
00825 EmbedPrivate::GetListener(void)
00826 {
00827   if (mEventReceiver)
00828     return;
00829 
00830   nsCOMPtr<nsPIDOMWindow> piWin;
00831   GetPIDOMWindow(getter_AddRefs(piWin));
00832 
00833   if (!piWin)
00834     return;
00835 
00836   mEventReceiver = do_QueryInterface(piWin->GetChromeEventHandler());
00837 }
00838 
00839 // attach key and mouse event listeners
00840 
00841 void
00842 EmbedPrivate::AttachListeners(void)
00843 {
00844   if (!mEventReceiver || mListenersAttached)
00845     return;
00846 
00847   nsIDOMEventListener *eventListener =
00848     NS_STATIC_CAST(nsIDOMEventListener *,
00849                  NS_STATIC_CAST(nsIDOMKeyListener *, mEventListener));
00850 
00851   // add the key listener
00852   nsresult rv;
00853   rv = mEventReceiver->AddEventListenerByIID(eventListener,
00854                                         NS_GET_IID(nsIDOMKeyListener));
00855   if (NS_FAILED(rv)) {
00856     NS_WARNING("Failed to add key listener\n");
00857     return;
00858   }
00859 
00860   rv = mEventReceiver->AddEventListenerByIID(eventListener,
00861                                         NS_GET_IID(nsIDOMMouseListener));
00862   if (NS_FAILED(rv)) {
00863     NS_WARNING("Failed to add mouse listener\n");
00864     return;
00865   }
00866 
00867   rv = mEventReceiver->AddEventListenerByIID(eventListener,
00868                                              NS_GET_IID(nsIDOMUIListener));
00869   if (NS_FAILED(rv)) {
00870     NS_WARNING("Failed to add UI listener\n");
00871     return;
00872   }
00873 
00874   // ok, all set.
00875   mListenersAttached = PR_TRUE;
00876 }
00877 
00878 void
00879 EmbedPrivate::DetachListeners(void)
00880 {
00881   if (!mListenersAttached || !mEventReceiver)
00882     return;
00883 
00884   nsIDOMEventListener *eventListener =
00885     NS_STATIC_CAST(nsIDOMEventListener *,
00886                  NS_STATIC_CAST(nsIDOMKeyListener *, mEventListener));
00887 
00888   nsresult rv;
00889   rv = mEventReceiver->RemoveEventListenerByIID(eventListener,
00890                                           NS_GET_IID(nsIDOMKeyListener));
00891   if (NS_FAILED(rv)) {
00892     NS_WARNING("Failed to remove key listener\n");
00893     return;
00894   }
00895 
00896   rv =
00897     mEventReceiver->RemoveEventListenerByIID(eventListener,
00898                                         NS_GET_IID(nsIDOMMouseListener));
00899   if (NS_FAILED(rv)) {
00900     NS_WARNING("Failed to remove mouse listener\n");
00901     return;
00902   }
00903 
00904   rv = mEventReceiver->RemoveEventListenerByIID(eventListener,
00905                                           NS_GET_IID(nsIDOMUIListener));
00906   if (NS_FAILED(rv)) {
00907     NS_WARNING("Failed to remove UI listener\n");
00908     return;
00909   }
00910 
00911   mListenersAttached = PR_FALSE;
00912 }
00913 
00914 nsresult
00915 EmbedPrivate::GetPIDOMWindow(nsPIDOMWindow **aPIWin)
00916 {
00917   *aPIWin = nsnull;
00918 
00919   // get the web browser
00920   nsCOMPtr<nsIWebBrowser> webBrowser;
00921   mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
00922 
00923   // get the content DOM window for that web browser
00924   nsCOMPtr<nsIDOMWindow> domWindow;
00925   webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
00926   if (!domWindow)
00927     return NS_ERROR_FAILURE;
00928 
00929   // get the private DOM window
00930   nsCOMPtr<nsPIDOMWindow> domWindowPrivate = do_QueryInterface(domWindow);
00931   // and the root window for that DOM window
00932   *aPIWin = domWindowPrivate->GetPrivateRoot();
00933 
00934   if (*aPIWin) {
00935     NS_ADDREF(*aPIWin);
00936     return NS_OK;
00937   }
00938 
00939   return NS_ERROR_FAILURE;
00940 
00941 }
00942 
00943 #ifdef MOZ_ACCESSIBILITY_ATK
00944 void *
00945 EmbedPrivate::GetAtkObjectForCurrentDocument()
00946 {
00947   if (!mNavigation)
00948     return nsnull;
00949 
00950   nsCOMPtr<nsIAccessibilityService> accService =
00951     do_GetService("@mozilla.org/accessibilityService;1");
00952   if (accService) {
00953     //get current document
00954     nsCOMPtr<nsIDOMDocument> domDoc;
00955     mNavigation->GetDocument(getter_AddRefs(domDoc));
00956     NS_ENSURE_TRUE(domDoc, nsnull);
00957 
00958     nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(domDoc));
00959     NS_ENSURE_TRUE(domNode, nsnull);
00960 
00961     nsCOMPtr<nsIAccessible> acc;
00962     accService->GetAccessibleFor(domNode, getter_AddRefs(acc));
00963     NS_ENSURE_TRUE(acc, nsnull);
00964 
00965     void *atkObj = nsnull;
00966     if (NS_SUCCEEDED(acc->GetNativeInterface(&atkObj)))
00967       return atkObj;
00968   }
00969   return nsnull;
00970 }
00971 #endif /* MOZ_ACCESSIBILITY_ATK */
00972 
00973 /* static */
00974 nsresult
00975 EmbedPrivate::StartupProfile(void)
00976 {
00977   // initialize profiles
00978   if (sProfileDir && sProfileName) {
00979     nsresult rv;
00980     nsCOMPtr<nsILocalFile> profileDir;
00981     NS_NewNativeLocalFile(nsDependentCString(sProfileDir), PR_TRUE,
00982                           getter_AddRefs(profileDir));
00983     if (!profileDir)
00984       return NS_ERROR_FAILURE;
00985     rv = profileDir->AppendNative(nsDependentCString(sProfileName));
00986     if (NS_FAILED(rv))
00987       return NS_ERROR_FAILURE;
00988 
00989     nsCOMPtr<nsProfileDirServiceProvider> locProvider;
00990     NS_NewProfileDirServiceProvider(PR_TRUE, getter_AddRefs(locProvider));
00991     if (!locProvider)
00992       return NS_ERROR_FAILURE;
00993     rv = locProvider->Register();
00994     if (NS_FAILED(rv))
00995       return rv;
00996     rv = locProvider->SetProfileDir(profileDir);
00997     if (NS_FAILED(rv))
00998       return rv;
00999     // Keep a ref so we can shut it down.
01000     NS_ADDREF(sProfileDirServiceProvider = locProvider);
01001 
01002     // get prefs
01003     nsCOMPtr<nsIPref> pref;
01004     pref = do_GetService(NS_PREF_CONTRACTID);
01005     if (!pref)
01006       return NS_ERROR_FAILURE;
01007     sPrefs = pref.get();
01008     NS_ADDREF(sPrefs);
01009   }
01010   return NS_OK;
01011 }
01012 
01013 /* static */
01014 void
01015 EmbedPrivate::ShutdownProfile(void)
01016 {
01017   if (sProfileDirServiceProvider) {
01018     sProfileDirServiceProvider->Shutdown();
01019     NS_RELEASE(sProfileDirServiceProvider);
01020     sProfileDirServiceProvider = 0;
01021   }
01022   if (sPrefs) {
01023     NS_RELEASE(sPrefs);
01024     sPrefs = 0;
01025   }
01026 }
01027 
01028 /* static */
01029 nsresult
01030 EmbedPrivate::RegisterAppComponents(void)
01031 {
01032   nsCOMPtr<nsIComponentRegistrar> cr;
01033   nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(cr));
01034   NS_ENSURE_SUCCESS(rv, rv);
01035 
01036   nsCOMPtr<nsIComponentManager> cm;
01037   rv = NS_GetComponentManager (getter_AddRefs (cm));
01038   NS_ENSURE_SUCCESS (rv, rv);
01039 
01040   for (int i = 0; i < sNumAppComps; ++i) {
01041     nsCOMPtr<nsIGenericFactory> componentFactory;
01042     rv = NS_NewGenericFactory(getter_AddRefs(componentFactory),
01043                               &(sAppComps[i]));
01044     if (NS_FAILED(rv)) {
01045       NS_WARNING("Unable to create factory for component");
01046       continue;  // don't abort registering other components
01047     }
01048 
01049     rv = cr->RegisterFactory(sAppComps[i].mCID, sAppComps[i].mDescription,
01050                              sAppComps[i].mContractID, componentFactory);
01051     NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to register factory for component");
01052 
01053     // Call the registration hook of the component, if any
01054     if (sAppComps[i].mRegisterSelfProc) {
01055       rv = sAppComps[i].mRegisterSelfProc(cm, nsnull, nsnull, nsnull,
01056                                           &(sAppComps[i]));
01057       NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to self-register component");
01058     }
01059   }
01060 
01061   return rv;
01062 }
01063 
01064 /* static */
01065 void
01066 EmbedPrivate::EnsureOffscreenWindow(void)
01067 {
01068   if (sOffscreenWindow)
01069     return;
01070   sOffscreenWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
01071   gtk_widget_realize(sOffscreenWindow);
01072   sOffscreenFixed = gtk_fixed_new();
01073   gtk_container_add(GTK_CONTAINER(sOffscreenWindow), sOffscreenFixed);
01074   gtk_widget_realize(sOffscreenFixed);
01075 }
01076 
01077 /* static */
01078 void
01079 EmbedPrivate::DestroyOffscreenWindow(void)
01080 {
01081   if (!sOffscreenWindow)
01082     return;
01083   gtk_widget_destroy(sOffscreenWindow);
01084   sOffscreenWindow = 0;
01085 }