private static extern int NS_NewLocalFile( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Gecko.CustomMarshalers.AStringMarshaler)) ] nsAString path, bool followLinks, [MarshalAs(UnmanagedType.IUnknown)] out object result);
/// <summary> /// Initializes XPCOM using the specified directory. /// </summary> /// <param name="binDirectory">The directory which contains xul.dll.</param> public static void Initialize(string binDirectory) { if (_IsInitialized) { return; } Debug.WriteLineIf(Thread.CurrentThread.GetApartmentState() != ApartmentState.STA, "Warning: Main Entry point missing [STAThread] attribute."); Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA, "Main Entry point missing [STAThread] attribute."); if (BeforeInitalization != null) { BeforeInitalization(); } Interlocked.Exchange(ref _XpcomThreadId, Thread.CurrentThread.ManagedThreadId); if (IsWindows) { Kernel32.SetDllDirectory(binDirectory); } string folder = binDirectory ?? Environment.CurrentDirectory; string xpcomPath = Path.Combine(folder, IsLinux ? "libxul.so" : "xul.dll"); try { // works on windows // but some classes can be not exist on mono (may be) // so make it in another function(stack allocation is making on function start) ReadXulrunnerVersion(xpcomPath); } catch (Exception) { } if (binDirectory != null) { Environment.SetEnvironmentVariable("PATH", string.Format("{0}{1}{2}", Environment.GetEnvironmentVariable("PATH"), Path.PathSeparator, binDirectory), EnvironmentVariableTarget.Process); } object mreAppDir = null; if (binDirectory != null) { using (nsAString str = new nsAString(Path.GetFullPath(binDirectory))) if (NS_NewLocalFile(str, true, out mreAppDir) != 0) { throw new Exception("Failed on NS_NewLocalFile"); } } // temporarily change the current directory so NS_InitEmbedding can find all the DLLs it needs String oldCurrent = Environment.CurrentDirectory; Environment.CurrentDirectory = folder; nsIServiceManager serviceManager; //int res = NS_InitXPCOM2(out serviceManagerPtr, mreAppDir, new DirectoryServiceProvider()); //Note: the error box that this can generate can't be prevented with try/catch, and res is 0 even if it fails //REVIEW: how else can we determine what happened and give a more useful answer, to help new GeckoFX users, //Telling them that probably the version of firefox or xulrunner didn't match this library version? // calling NS_InitXPCOM2 invokes AddRef to the returned nsIServerManager, but as this gets assigned to the __ComObject serviceManager // Release will be called by the when the GC runs __ComObject finaliser. int res = NS_InitXPCOM2(out serviceManager, mreAppDir, null); // change back Environment.CurrentDirectory = oldCurrent; if (res != 0) { throw new Exception("Failed on NS_InitXPCOM2"); } ServiceManager = (nsIServiceManager)serviceManager; // get some global objects we will need later NS_GetComponentManager(out ComponentManager); NS_GetComponentRegistrar(out ComponentRegistrar); if (IsMono) { _comGC = new COMGC(); } // RegisterProvider is necessary to get link styles etc. nsIDirectoryService directoryService = GetService <nsIDirectoryService>("@mozilla.org/file/directory_service;1"); if (directoryService != null) { directoryService.RegisterProvider(new DirectoryServiceProvider()); } _IsInitialized = true; // On Linux calling CreateWindowlessBrowser too early crashes with passing null to gdk_window_enable_synchronized_configure() // the gdkwidgets window is null. if (!Xpcom.IsLinux) { InitChromeContext(); } XULAppInfoFactory.Init(); OnProfileStartup(); PromptFactoryFactory.Init(); if (AfterInitalization != null) { AfterInitalization(); } if (Xpcom.IsLinux) { // Firefox enable offmainthreadcomposition on Linux around May 2015. // (see https://mozillagfx.wordpress.com/2015/05/19/off-main-thread-compositing-on-linux/ ) // However with geckofx on Linux we end up with two Compositors. // So we end up with a ClientLayerManager with an uninitalzied mTransactionIdAllocator // which causes segfault on Paint. GeckoPreferences.User["layers.offmainthreadcomposition.enabled"] = false; } }
protected override void OnHandleCreated(EventArgs e) { try { InOnHandleCreate = true; #if GTK if (Xpcom.IsMono) { base.OnHandleCreated(e); if (m_wrapper != null) { m_wrapper.Init(); } } #endif if (!this.DesignMode) { Xpcom.Initialize(); WindowCreator.Register(); #if !GTK LauncherDialogFactory.Register(); #endif WebBrowser = Xpcom.CreateInstance <nsIWebBrowser>(Contracts.WebBrowser); WebBrowserFocus = (nsIWebBrowserFocus)WebBrowser; BaseWindow = (nsIBaseWindow)WebBrowser; WebNav = (nsIWebNavigation)WebBrowser; WebBrowser.SetContainerWindowAttribute(this); #if GTK if (Xpcom.IsMono && m_wrapper != null) { BaseWindow.InitWindow(m_wrapper.BrowserWindow.Handle, IntPtr.Zero, 0, 0, this.Width, this.Height); } else #endif BaseWindow.InitWindow(this.Handle, IntPtr.Zero, 0, 0, this.Width, this.Height); BaseWindow.Create(); var docShell = Xpcom.QueryInterface <nsIDocShell>(BaseWindow); // Allow visible control before finished loading see https://bugzilla.mozilla.org/show_bug.cgi?id=1138536 docShell.CreateAboutBlankContentViewer(null); Xpcom.FreeComObject(ref docShell); BaseWindow.SetVisibilityAttribute(true); Guid nsIWebProgressListenerGUID = typeof(nsIWebProgressListener).GUID; Guid nsIWebProgressListener2GUID = typeof(nsIWebProgressListener2).GUID; WebBrowser.AddWebBrowserListener(this.GetWeakReference(), ref nsIWebProgressListenerGUID); WebBrowser.AddWebBrowserListener(this.GetWeakReference(), ref nsIWebProgressListener2GUID); if (UseHttpActivityObserver) { ObserverService.AddObserver(this, ObserverNotifications.HttpRequests.HttpOnModifyRequest, false); Net.HttpActivityDistributor.AddObserver(this); } // force inital window initialization. (Events now get added after document navigation. { var domWindow = WebBrowser.GetContentDOMWindowAttribute(); EventTarget = ((nsIDOMEventTarget)domWindow).AsComPtr(); using (var eventType = new nsAString("somedummyevent")) { EventTarget.Instance.AddEventListener(eventType, this, true, true, 2); EventTarget.Instance.RemoveEventListener(eventType, this, true); } } // history { var sessionHistory = WebNav.GetSessionHistoryAttribute(); if (sessionHistory != null) { sessionHistory.AddSHistoryListener(this); } } WindowMediator.RegisterWindow(this); } #if !GTK base.OnHandleCreated(e); #endif } finally { InOnHandleCreate = false; GeckoHandleCreated(this, EventArgs.Empty); } }
/// <summary> /// Initializes XPCOM using the specified directory. /// </summary> /// <param name="binDirectory">The directory which contains xul.dll.</param> public static void Initialize(string binDirectory) { if (_IsInitialized) { return; } if (BeforeInitalization != null) { BeforeInitalization(); } Interlocked.Exchange(ref _XpcomThreadId, Thread.CurrentThread.ManagedThreadId); if (IsWindows) { Kernel32.SetDllDirectory(binDirectory); } string folder = binDirectory ?? Environment.CurrentDirectory; string xpcomPath = Path.Combine(folder, IsLinux ? "libxul.so" : "xul.dll"); try { // works on windows // but some classes can be not exist on mono (may be) // so make it in another function(stack allocation is making on function start) ReadXulrunnerVersion(xpcomPath); } catch (Exception) { } if (binDirectory != null) { Environment.SetEnvironmentVariable("path", Environment.GetEnvironmentVariable("path") + ";" + binDirectory, EnvironmentVariableTarget.Process); } object mreAppDir = null; if (binDirectory != null) { using (nsAString str = new nsAString(Path.GetFullPath(binDirectory))) if (NS_NewLocalFile(str, true, out mreAppDir) != 0) { throw new Exception("Failed on NS_NewLocalFile"); } } // temporarily change the current directory so NS_InitEmbedding can find all the DLLs it needs String oldCurrent = Environment.CurrentDirectory; Environment.CurrentDirectory = folder; nsIServiceManager serviceManager; //int res = NS_InitXPCOM2(out serviceManagerPtr, mreAppDir, new DirectoryServiceProvider()); //Note: the error box that this can generate can't be prevented with try/catch, and res is 0 even if it fails //REVIEW: how else can we determine what happened and give a more useful answer, to help new GeckoFX users, //Telling them that probably the version of firefox or xulrunner didn't match this library version? // calling NS_InitXPCOM2 invokes AddRef to the returned nsIServerManager, but as this gets assigned to the __ComObject serviceManager // Release will be called by the when the GC runs __ComObject finaliser. int res = NS_InitXPCOM2(out serviceManager, mreAppDir, null); // change back Environment.CurrentDirectory = oldCurrent; if (res != 0) { throw new Exception("Failed on NS_InitXPCOM2"); } ServiceManager = (nsIServiceManager)serviceManager; // get some global objects we will need later NS_GetComponentManager(out ComponentManager); NS_GetComponentRegistrar(out ComponentRegistrar); if (IsMono) { _comGC = new COMGC(); } // RegisterProvider is necessary to get link styles etc. nsIDirectoryService directoryService = GetService <nsIDirectoryService>("@mozilla.org/file/directory_service;1"); if (directoryService != null) { directoryService.RegisterProvider(new ProfileProvider()); } _IsInitialized = true; GlobalJSContextHolder.Initialize(); if (AfterInitalization != null) { AfterInitalization(); } }
static extern int NS_NewLocalFile(nsAString path, bool followLinks, [MarshalAs(UnmanagedType.IUnknown)] out object result);
protected override void OnHandleDestroyed(EventArgs e) { if (BaseWindow != null) { this.Stop(); WindowMediator.UnregisterWindow(this); nsIDocShell docShell = Xpcom.QueryInterface <nsIDocShell>(BaseWindow); if (docShell != null && !docShell.IsBeingDestroyed()) { try { var window = Xpcom.QueryInterface <nsIDOMWindow>(docShell); if (window != null) { try { if (!window.GetClosedAttribute()) { window.Close(); } } finally { Xpcom.FreeComObject(ref window); } } } finally { Xpcom.FreeComObject(ref docShell); } } if (EventTarget != null) { //Remove Event Listener foreach (string sEventType in this.DefaultEvents) { using (var eventType = new nsAString(sEventType)) { EventTarget.Instance.RemoveEventListener(eventType, this, true); } } EventTarget.Dispose(); EventTarget = null; } BaseWindow.Destroy(); Xpcom.FreeComObject(ref CommandParams); var webBrowserFocus = this.WebBrowserFocus; this.WebBrowserFocus = null; Xpcom.FreeComObject(ref webBrowserFocus); Xpcom.FreeComObject(ref WebNav); Xpcom.FreeComObject(ref BaseWindow); Xpcom.FreeComObject(ref WebBrowser); #if GTK if (m_wrapper != null) { m_wrapper.Dispose(); m_wrapper = null; } #endif } base.OnHandleDestroyed(e); }
protected override void OnHandleCreated(EventArgs e) { #if GTK if (Xpcom.IsMono) { base.OnHandleCreated(e); if (m_wrapper != null) { m_wrapper.Init(); } } #endif if (!this.DesignMode) { Xpcom.Initialize(); WindowCreator.Register(); #if !GTK LauncherDialogFactory.Register(); #endif WebBrowser = Xpcom.CreateInstance <nsIWebBrowser>(Contracts.WebBrowser); WebBrowserFocus = ( nsIWebBrowserFocus )WebBrowser; BaseWindow = ( nsIBaseWindow )WebBrowser; WebNav = ( nsIWebNavigation )WebBrowser; WebBrowser.SetContainerWindowAttribute(this); #if GTK if (Xpcom.IsMono && m_wrapper != null) { BaseWindow.InitWindow(m_wrapper.BrowserWindow.Handle, IntPtr.Zero, 0, 0, this.Width, this.Height); } else #endif BaseWindow.InitWindow(this.Handle, IntPtr.Zero, 0, 0, this.Width, this.Height); BaseWindow.Create(); Guid nsIWebProgressListenerGUID = typeof(nsIWebProgressListener).GUID; Guid nsIWebProgressListener2GUID = typeof(nsIWebProgressListener2).GUID; WebBrowser.AddWebBrowserListener(this.GetWeakReference(), ref nsIWebProgressListenerGUID); WebBrowser.AddWebBrowserListener(this.GetWeakReference(), ref nsIWebProgressListener2GUID); if (UseHttpActivityObserver) { ObserverService.AddObserver(this, ObserverNotifications.HttpRequests.HttpOnModifyRequest, false); Net.HttpActivityDistributor.AddObserver(this); } // var domEventListener = new GeckoDOMEventListener(this); { var domWindow = WebBrowser.GetContentDOMWindowAttribute(); EventTarget = domWindow.GetWindowRootAttribute().AsComPtr(); Marshal.ReleaseComObject(domWindow); } foreach (string sEventName in this.DefaultEvents) { using (var eventType = new nsAString(sEventName)) { EventTarget.Instance.AddEventListener(eventType, this, true, true, 2); } } // history { var sessionHistory = WebNav.GetSessionHistoryAttribute(); if (sessionHistory != null) { sessionHistory.AddSHistoryListener(this); } } BaseWindow.SetVisibilityAttribute(true); // this fix prevents the browser from crashing if the first page loaded is invalid (missing file, invalid URL, etc) using (var doc = Document) { if (doc != null) { // only for html documents doc.Cookie = ""; } WindowMediator.RegisterWindow(this); } } base.OnHandleCreated(e); }