/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is RaptorCanvas. * * The Initial Developer of the Original Code is Kirk Baker and * Ian Wilkinson. Portions created by Kirk Baker and Ian Wilkinson are * Copyright (C) 1999 Kirk Baker and Ian Wilkinson. All * Rights Reserved. * * Contributor(s): Kirk Baker * Ian Wilkinson * Mark Lin * Mark Goddard * Ed Burns * Ashutosh Kulkarni * Ann Sunhachawee */ #include "nsIEventQueueService.h" // for PLEventQueue #include "nsIServiceManager.h" // for do_GetService #include "nsEmbedAPI.h" // for NS_HandleEmbeddingEvent #include // for initializing our window watcher service #include "EmbedWindow.h" #include "WindowCreator.h" #include "EmbedProgress.h" #include "EmbedEventListener.h" #include "NativeBrowserControl.h" #include "ns_util.h" #include "ns_globals.h" // all of the crap that we need for event listeners // and when chrome windows finish loading #include #include #include #include // for the focus hacking we need to do #include NativeBrowserControl::NativeBrowserControl(void) { parentHWnd = nsnull; mNavigation = nsnull; mSessionHistory = nsnull; mWindow = nsnull; mJavaBrowserControl = nsnull; mChromeMask = 0; mIsChrome = PR_FALSE; mChromeLoaded = PR_FALSE; mIsDestroyed = PR_FALSE; mListenersAttached = PR_FALSE; mNewWindowListenerAttached = PR_FALSE; } NativeBrowserControl::~NativeBrowserControl() { // PENDING(edburns): assert that this widget has been destroyed mChromeMask = 0; mIsChrome = PR_FALSE; mChromeLoaded = PR_FALSE; mJavaBrowserControl = nsnull; } nsresult NativeBrowserControl::Init(NativeWrapperFactory *yourWrapperFactory) { if (!util_StringConstantsAreInitialized()) { util_InitStringConstants(); } wrapperFactory = yourWrapperFactory; // Create our embed window, and create an owning reference to it and // initialize it. It is assumed that this window will be destroyed // when we go out of scope. mWindow = new EmbedWindow(); mWindowGuard = static_cast(mWindow); mWindow->Init(this); // Create our progress listener object, make an owning reference, // and initialize it. It is assumed that this progress listener // will be destroyed when we go out of scope. mProgress = new EmbedProgress(); mProgressGuard = static_cast (mProgress); mProgress->Init(this); // Create our key listener object and initialize it. It is assumed // that this will be destroyed before we go out of scope. mEventListener = new EmbedEventListener(); mEventListenerGuard = static_cast(static_cast (mEventListener)); mEventListener->Init(this); nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // get a handle on the navigation object mNavigation = do_QueryInterface(webBrowser); // // create the WindowCreator: see WindowCreator *creator = new WindowCreator(this); nsCOMPtr windowCreator; windowCreator = static_cast(creator); // Attach it via the watcher service nsCOMPtr watcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID); if (watcher) { watcher->SetWindowCreator(windowCreator); } return NS_OK; } nsresult NativeBrowserControl::Realize(jobject javaBrowserControl, void *parentWinPtr, PRBool *aAlreadyRealized, PRUint32 width, PRUint32 height) { PR_LOG(prLogModuleInfo, PR_LOG_DEBUG, ("NativeBrowserControl::Realize: start")); // parentWinPtr is whatever was returned from // BrowserControlCanvas.getWindow(). nsresult rv = NS_OK; mJavaBrowserControl = javaBrowserControl; // Create our session history object and tell the navigation object // to use it. We need to do this before we create the web browser // window. mSessionHistory = do_CreateInstance(NS_SHISTORY_CONTRACTID); mNavigation->SetSessionHistory(mSessionHistory); #if defined(XP_UNIX) && !defined(XP_MACOSX) PR_ASSERT(PR_FALSE); GtkWidget *ownerAsWidget (GTK_WIDGET(parentWinPtr)); parentHWnd = ownerAsWidget; width = ownerAsWidget->allocation.width; height = ownerAsWidget->allocation.height; #elif defined(XP_PC) parentHWnd = (HWND) parentWinPtr; #elif (defined(XP_MAC) || defined(XP_MACOSX)) && defined(MOZ_WIDGET_COCOA) parentHWnd = (void *) parentWinPtr; #endif // create the window rv = mWindow->CreateWindow_(width, height); if (NS_FAILED(rv)) { PR_LOG(prLogModuleInfo, PR_LOG_DEBUG, ("NativeBrowserControl::Realize: EmbedWindow::CreateWindow returned: %d", rv)); JNIEnv *env = (JNIEnv *) JNU_GetEnv(gVm, JNI_VERSION); ::util_ThrowExceptionToJava(env, "Can't CreateWindow"); } // bind the progress listener to the browser object nsCOMPtr supportsWeak; supportsWeak = do_QueryInterface(mProgressGuard); nsCOMPtr weakRef; supportsWeak->GetWeakReference(getter_AddRefs(weakRef)); mWindow->AddWebBrowserListener(weakRef, nsIWebProgressListener::GetIID()); // set the eventRegistration into the progress listener jobject eventRegistration = this->QueryInterfaceJava(EVENT_REGISTRATION_INDEX); if (nsnull != eventRegistration) { mProgress->SetEventRegistration(eventRegistration); mEventListener->SetEventRegistration(eventRegistration); } else { JNIEnv *env = (JNIEnv *) JNU_GetEnv(gVm, JNI_VERSION); ::util_ThrowExceptionToJava(env, "Can't get EventRegistration from BrowserControl"); } PR_LOG(prLogModuleInfo, PR_LOG_DEBUG, ("NativeBrowserControl::Realize: succeeded")); return NS_OK; } void NativeBrowserControl::Unrealize(void) { } void NativeBrowserControl::Show(void) { // Get the nsIWebBrowser object for our embedded window. nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // and set the visibility on the thing nsCOMPtr baseWindow = do_QueryInterface(webBrowser); baseWindow->SetVisibility(PR_TRUE); } void NativeBrowserControl::Hide(void) { // Get the nsIWebBrowser object for our embedded window. nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // and set the visibility on the thing nsCOMPtr baseWindow = do_QueryInterface(webBrowser); baseWindow->SetVisibility(PR_FALSE); } void NativeBrowserControl::Resize(PRUint32 x, PRUint32 y, PRUint32 aWidth, PRUint32 aHeight) { mWindow->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION | nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER, x, y, aWidth, aHeight); } void NativeBrowserControl::Destroy(void) { mIsDestroyed = PR_TRUE; // PENDING(edburns): take over the stuff from // WindowControlActionEvents // wsDeallocateInitContextEvent::handleEvent() // This flag might have been set from // EmbedWindow::DestroyBrowserWindow() as well if someone used a // window.close() or something or some other script action to close // the window. No harm setting it again. // Get the nsIWebBrowser object for our embedded window. nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // detach our event listeners and release the event receiver DetachListeners(); if (mEventReceiver) mEventReceiver = nsnull; // release navigation mNavigation = nsnull; // Release our progress listener nsCOMPtr supportsWeak; supportsWeak = do_QueryInterface(mProgressGuard); nsCOMPtr weakRef; supportsWeak->GetWeakReference(getter_AddRefs(weakRef)); webBrowser->RemoveWebBrowserListener(weakRef, nsIWebProgressListener::GetIID()); weakRef = nsnull; supportsWeak = nsnull; // Now that we have removed the listener, release our progress // object mProgressGuard = nsnull; mProgress = nsnull; fflush(stdout); // destroy our child window mWindow->ReleaseChildren(); parentHWnd = nsnull; } // handle focus in and focus out events void NativeBrowserControl::TopLevelFocusIn(void) { if (mIsDestroyed) return; nsCOMPtr piWin; GetPIDOMWindow(getter_AddRefs(piWin)); if (!piWin) return; nsIFocusController *focusController = nsnull; focusController = piWin->GetRootFocusController(); if (focusController) focusController->SetActive(PR_TRUE); } void NativeBrowserControl::TopLevelFocusOut(void) { if (mIsDestroyed) return; nsCOMPtr piWin; GetPIDOMWindow(getter_AddRefs(piWin)); if (!piWin) return; nsIFocusController *focusController; focusController = piWin->GetRootFocusController(); if (focusController) focusController->SetActive(PR_FALSE); } NativeWrapperFactory *NativeBrowserControl::GetWrapperFactory() { return wrapperFactory; } jobject NativeBrowserControl::QueryInterfaceJava(WEBCLIENT_INTERFACES interface) { PR_ASSERT(nsnull != mJavaBrowserControl); JNIEnv *env = (JNIEnv *) JNU_GetEnv(gVm, JNI_VERSION); env->ExceptionClear(); jobject result = nsnull; jstring interfaceJStr = ::util_NewStringUTF(env, gImplementedInterfaces[interface]); jclass clazz = env->GetObjectClass(mJavaBrowserControl); jmethodID mid = env->GetMethodID(clazz, "queryInterface", "(Ljava/lang/String;)Ljava/lang/Object;"); if (nsnull != mid) { result = env->CallObjectMethod(mJavaBrowserControl, mid, interfaceJStr); } else { ::util_ThrowExceptionToJava(env, "Can't QueryInterface BrowserControl"); } ::util_DeleteStringUTF(env, interfaceJStr); return result; } void NativeBrowserControl::ContentStateChange(void) { // we don't attach listeners to chrome if (mListenersAttached && !mIsChrome) { return; } GetListener(); if (!mEventReceiver) { return; } AttachListeners(); } nsresult NativeBrowserControl::SetNewWindowListenerAttached(PRBool newState) { mNewWindowListenerAttached = newState; return NS_OK; } nsresult NativeBrowserControl::GetNewWindowListenerAttached(PRBool *_retval) { nsresult result = NS_ERROR_NULL_POINTER; if (nsnull != _retval) { *_retval = mNewWindowListenerAttached; result = NS_OK; } return result; } void NativeBrowserControl::GetListener() { if (mEventReceiver) { return; } nsCOMPtr piWin; GetPIDOMWindow(getter_AddRefs(piWin)); if (!piWin) { return; } nsIChromeEventHandler *chromeHandler; chromeHandler = piWin->GetChromeEventHandler(); mEventReceiver = do_QueryInterface(chromeHandler); } void NativeBrowserControl::AttachListeners() { if (!mEventReceiver || mListenersAttached) { return; } nsIDOMEventListener *eventListener = static_cast (static_cast(mEventListener)); // add the key listener nsresult rv; rv = mEventReceiver->AddEventListenerByIID(eventListener, NS_GET_IID(nsIDOMKeyListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to add key listener\n"); return; } rv = mEventReceiver->AddEventListenerByIID(eventListener, NS_GET_IID(nsIDOMMouseListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to add mouse listener\n"); return; } // ok, all set. mListenersAttached = PR_TRUE; } void NativeBrowserControl::DetachListeners() { if (!mListenersAttached || !mEventReceiver) { return; } nsIDOMEventListener *eventListener = static_cast (static_cast(mEventListener)); nsresult rv; rv = mEventReceiver->RemoveEventListenerByIID(eventListener, NS_GET_IID(nsIDOMKeyListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to remove key listener\n"); return; } rv = mEventReceiver->RemoveEventListenerByIID(eventListener, NS_GET_IID(nsIDOMMouseListener)); if (NS_FAILED(rv)) { NS_WARNING("Failed to remove mouse listener\n"); return; } mListenersAttached = PR_FALSE; } nsresult NativeBrowserControl::GetPIDOMWindow(nsPIDOMWindow **aPIWin) { *aPIWin = nsnull; // get the web browser nsCOMPtr webBrowser; mWindow->GetWebBrowser(getter_AddRefs(webBrowser)); // get the content DOM window for that web browser nsCOMPtr domWindow; webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); if (!domWindow) { return NS_ERROR_FAILURE; } // get the private DOM window nsCOMPtr domWindowPrivate = do_QueryInterface(domWindow); // and the root window for that DOM window nsIDOMWindowInternal *rootWindow; rootWindow = domWindowPrivate->GetPrivateRoot(); nsCOMPtr chromeHandler; nsCOMPtr piWin(do_QueryInterface(rootWindow)); *aPIWin = piWin.get(); if (*aPIWin) { NS_ADDREF(*aPIWin); return NS_OK; } return NS_ERROR_FAILURE; }