* Mono.Mozilla/WebBrowser.cs: create the browser window when the control gets
[mono.git] / mcs / class / Mono.WebBrowser / Mono.Mozilla / WebBrowser.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2007, 2008 Novell, Inc.
21 //
22 // Authors:
23 //      Andreia Gaita (avidigal@novell.com)
24 //
25
26 #undef debug
27
28 using System;
29 using System.Collections;
30 using System.Reflection;
31 using System.Runtime.InteropServices;
32 using System.Text;
33 using System.Diagnostics;
34 using Mono.WebBrowser;
35 using Mono.WebBrowser.DOM;
36
37 namespace Mono.Mozilla
38 {
39         internal class WebBrowser : IWebBrowser
40         {
41                 bool loaded;
42                 internal bool created = false;
43                 bool creating = false;
44
45                 internal DOM.Document document;
46                 
47                 internal DOM.Navigation navigation;
48                 internal Platform platform;
49                 internal Platform enginePlatform;
50                 internal Callback callbacks;
51                 System.ComponentModel.EventHandlerList events;
52                 System.ComponentModel.EventHandlerList domEvents;
53
54                 string statusText;
55
56                 bool streamingMode;
57                 
58                 internal Hashtable documents;
59                 
60                 public WebBrowser (Platform platform)
61                 {
62                         this.platform = platform;
63                         callbacks = new Callback(this);
64                         loaded = Base.Init (this, platform);
65                         documents = new Hashtable ();
66                 }
67
68                 public bool Load (IntPtr handle, int width, int height)
69                 {
70                         loaded = Base.Bind (this, handle, width, height);
71                         return loaded;
72                 }
73
74                 bool Created {
75                         get {
76                                 if (!creating && !created) {
77                                         creating = true;
78                                         created = Base.Create (this);
79                                 }
80                                 return created;
81                         }
82                 }
83
84                 public void Shutdown ()
85                 {
86                         Base.Shutdown (this);
87                 }
88                 
89                 internal void Reset ()
90                 {
91                         this.document = null;
92                         this.DomEvents.Dispose ();
93                         this.domEvents = null;
94                         this.documents.Clear ();
95                 }
96
97                 public bool Initialized {
98                         get { return this.loaded; }
99                 }
100                 
101                 public IWindow Window {
102                         get {
103                                 if (Navigation != null) {
104                                         nsIWebBrowserFocus webBrowserFocus = (nsIWebBrowserFocus) (navigation.navigation);
105                                         nsIDOMWindow window;
106                                         webBrowserFocus.getFocusedWindow (out window);
107                                         return new DOM.Window (this, window) as IWindow;
108                                 }
109                                 return null;
110                         }
111                 }
112
113                 public IDocument Document {
114                         get {
115                                 if (Navigation != null && document == null) {
116                                         document = navigation.Document;
117                                 }
118                                 return document as IDocument;
119                         }
120                 }
121
122                 public INavigation Navigation {
123                         get {
124                                 if (!Created) return null;
125
126                                 if (navigation == null) {
127                                         
128                                         nsIWebNavigation webNav = Base.GetWebNavigation (this);
129                                         navigation = new DOM.Navigation (this, webNav);
130                                 }
131                                 return navigation as INavigation;
132                         }
133                 }
134                 
135                 public string StatusText {
136                         get { return statusText; }
137                 }
138                 
139                 public bool Offline {
140                         get {
141                                 bool ret;
142                                 if (!Created) return true;
143                                 IOService.getOffline (out ret);
144                                 return ret;
145                         }
146                         set {
147                                 IOService.setOffline (value);
148                         }
149                 }
150                 
151                 internal System.ComponentModel.EventHandlerList DomEvents {
152                         get {
153                                 if (domEvents == null)
154                                         domEvents = new System.ComponentModel.EventHandlerList();
155
156                                 return domEvents;
157                         }
158                 }
159
160                 internal System.ComponentModel.EventHandlerList Events {
161                         get {
162                                 if (events == null)
163                                         events = new System.ComponentModel.EventHandlerList();
164
165                                 return events;
166                         }
167                 }
168                 
169                 Mono.Mozilla.DOM.ContentListener contentListener;
170                 Mono.Mozilla.DOM.ContentListener ContentListener {
171                         get {
172                                 if (contentListener == null)
173                                         contentListener = new Mono.Mozilla.DOM.ContentListener (this);
174                                 return contentListener;
175                         }
176                 }               
177                 
178                 
179                 nsIServiceManager servMan;
180                 internal nsIServiceManager ServiceManager {
181                         get {
182                                 if (servMan == null) {
183                                         servMan = Base.GetServiceManager (this);
184                                 }
185                                 return servMan;
186                         }
187                 }
188                 
189                 nsIIOService ioService;
190                 internal nsIIOService IOService {
191                         get {
192                                 if (ioService == null) {
193                                         IntPtr ioServicePtr = IntPtr.Zero;
194
195                                         ServiceManager.getServiceByContractID ("@mozilla.org/network/io-service;1", typeof (nsIIOService).GUID,
196                                                 out ioServicePtr);
197                                         if (ioServicePtr == IntPtr.Zero)
198                                                 throw new Mono.WebBrowser.Exception (Mono.WebBrowser.Exception.ErrorCodes.IOService);
199
200                                         try {
201                                                 ioService = (nsIIOService)Marshal.GetObjectForIUnknown (ioServicePtr);
202                                         } catch (System.Exception ex) {
203                                                 throw new Mono.WebBrowser.Exception (Mono.WebBrowser.Exception.ErrorCodes.IOService, ex);
204                                         }
205                                 }
206                                 return ioService;
207                         }
208                 }
209
210                 nsIAccessibilityService accessibilityService;
211                 internal nsIAccessibilityService AccessibilityService {
212                         get {
213                                 if (accessibilityService == null) {
214                                         IntPtr accessibilityServicePtr = IntPtr.Zero;
215                                         ServiceManager.getServiceByContractID ("@mozilla.org/accessibilityService;1", typeof (nsIAccessibilityService).GUID,
216                                                 out accessibilityServicePtr);
217                                         if (accessibilityServicePtr == IntPtr.Zero) {
218                                                 throw new Mono.WebBrowser.Exception (Mono.WebBrowser.Exception.ErrorCodes.AccessibilityService);
219                                         }
220
221                                         try {
222                                                 accessibilityService = (nsIAccessibilityService)Marshal.GetObjectForIUnknown (accessibilityServicePtr);
223                                         } catch (System.Exception ex) {
224                                                 throw new Mono.WebBrowser.Exception (Mono.WebBrowser.Exception.ErrorCodes.AccessibilityService, ex);
225                                         }
226                                 }
227                                 return accessibilityService;
228                         }
229                 }
230
231                 nsIErrorService errorService;
232                 internal nsIErrorService ErrorService {
233                         get {
234                                 if (errorService == null) {
235                                         IntPtr errorServicePtr = IntPtr.Zero;
236
237                                         ServiceManager.getServiceByContractID ("@mozilla.org/xpcom/error-service;1", typeof (nsIErrorService).GUID,
238                                                 out errorServicePtr);
239                                         if (errorServicePtr == IntPtr.Zero)
240                                                 return null;
241
242                                         try {
243                                                 errorService = (nsIErrorService)Marshal.GetObjectForIUnknown (errorServicePtr);
244                                         } catch (System.Exception ex) {
245                                                 return null;
246                                         }
247                                 }
248                                 return errorService;
249                         }
250                 }
251                 
252                 DocumentEncoder docEncoder;
253                 internal DocumentEncoder DocEncoder {
254                         get {
255                                 if (docEncoder == null) {
256                                         docEncoder = new DocumentEncoder (this);
257                                 }
258                                 return docEncoder;
259                         }
260                 }               
261                 
262                 #region Layout
263                 public void FocusIn (FocusOption focus)
264                 {
265                         if (!created) return;
266                         Base.Focus (this, focus);
267                 }
268                 public void FocusOut ()
269                 {
270                         if (!created) return;
271                         Base.Blur (this);
272                 }
273                 
274                 public void Activate ()
275                 {
276                         if (!Created) return;
277                         Base.Activate (this);
278                 }
279                 public void Deactivate ()
280                 {
281                         if (!created) return;
282                         Base.Deactivate (this);
283                 }
284
285                 public void Resize (int width, int height)
286                 {
287                         if (!created) return;
288                         Base.Resize (this, width, height);                      
289                 }
290
291                 public void Render (byte[] data)
292                 {
293                         if (!Created) return;
294                         if (data == null)
295                                 throw new ArgumentNullException ("data");
296                         string html = System.Text.ASCIIEncoding.UTF8.GetString (data);
297                         Render (html);
298                 }
299
300                 public void Render (string html)
301                 {
302                         if (!Created) return;
303                         Render (html, "file:///", "text/html");
304                 }
305
306                                 
307                 public void Render (string html, string uri, string contentType)
308                 {
309                         if (!Created) return;
310                         nsIWebBrowserStream stream;
311                         if (Navigation != null) {
312                                 stream = (nsIWebBrowserStream) navigation.navigation;
313                         } else
314                                 throw new Mono.WebBrowser.Exception (Mono.WebBrowser.Exception.ErrorCodes.Navigation);
315                         AsciiString asciiUri = new AsciiString (uri);
316                         nsIURI ret;
317                         IOService.newURI (asciiUri.Handle, null, null, out ret);
318
319                         AsciiString ctype = new AsciiString(contentType);
320
321                         HandleRef han = ctype.Handle;
322
323                         stream.openStream (ret, han);
324
325                         IntPtr native_html = Marshal.StringToHGlobalAnsi (html);
326                         stream.appendToStream (native_html, (uint)html.Length);
327                         Marshal.FreeHGlobal (native_html);
328
329                         stream.closeStream ();
330
331                 }
332                 
333                 public void ExecuteScript (string script) {
334                         if (!Created) return;
335                         Base.EvalScript (this, script);
336                 }
337                                 
338                 internal void AttachEvent (INode node, string eve, EventHandler handler) {
339                         string key = String.Intern (node.GetHashCode() + ":" + eve);
340 #if debug
341                         Console.Error.WriteLine ("Event Attached: " + key);
342 #endif
343                         DomEvents.AddHandler (key, handler);
344                 }
345
346                 internal void DetachEvent (INode node, string eve, EventHandler handler) {
347                         string key = String.Intern (node.GetHashCode() + ":" + eve);
348 #if debug                       
349                         Console.Error.WriteLine ("Event Detached: " + key);
350 #endif                  
351                         DomEvents.RemoveHandler (key, handler);
352                 }
353                 
354                 #endregion
355
356                 #region Events
357                 internal static object KeyDownEvent = new object ();
358                 internal static object KeyPressEvent = new object ();
359                 internal static object KeyUpEvent = new object ();
360                 internal static object MouseClickEvent = new object ();
361                 internal static object MouseDoubleClickEvent = new object ();
362                 internal static object MouseDownEvent = new object ();
363                 internal static object MouseEnterEvent = new object ();
364                 internal static object MouseLeaveEvent = new object ();
365                 internal static object MouseMoveEvent = new object ();
366                 internal static object MouseUpEvent = new object ();
367                 internal static object FocusEvent = new object ();
368                 internal static object BlurEvent = new object ();
369                 internal static object CreateNewWindowEvent = new object ();
370                 internal static object AlertEvent = new object ();
371                         
372                 internal static object LoadStartedEvent = new object ();
373                 internal static object LoadCommitedEvent = new object ();
374                 internal static object ProgressChangedEvent = new object ();
375                 internal static object LoadFinishedEvent = new object ();       
376                 
377                 internal static object LoadEvent = new object ();
378                 internal static object UnloadEvent = new object ();
379                 internal static object StatusChangedEvent = new object ();
380                 internal static object SecurityChangedEvent = new object ();
381                 internal static object ProgressEvent = new object ();
382                 internal static object ContextMenuEvent = new object ();
383                 
384                 internal static object NavigationRequestedEvent = new object ();
385                 
386                 public event NodeEventHandler KeyDown
387                 {
388                         add { Events.AddHandler (KeyDownEvent, value); }
389                         remove { Events.RemoveHandler (KeyDownEvent, value); }
390                 }
391
392                 public event NodeEventHandler KeyPress
393                 {
394                         add { Events.AddHandler (KeyPressEvent, value); }
395                         remove { Events.RemoveHandler (KeyPressEvent, value); }
396                 }
397                 public event NodeEventHandler KeyUp
398                 {
399                         add { Events.AddHandler (KeyUpEvent, value); }
400                         remove { Events.RemoveHandler (KeyUpEvent, value); }
401                 }
402                 public event NodeEventHandler MouseClick
403                 {
404                         add { Events.AddHandler (MouseClickEvent, value); }
405                         remove { Events.RemoveHandler (MouseClickEvent, value); }
406                 }
407                 public event NodeEventHandler MouseDoubleClick
408                 {
409                         add { Events.AddHandler (MouseDoubleClickEvent, value); }
410                         remove { Events.RemoveHandler (MouseDoubleClickEvent, value); }
411                 }
412                 public event NodeEventHandler MouseDown
413                 {
414                         add { Events.AddHandler (MouseDownEvent, value); }
415                         remove { Events.RemoveHandler (MouseDownEvent, value); }
416                 }
417                 public event NodeEventHandler MouseEnter
418                 {
419                         add { Events.AddHandler (MouseEnterEvent, value); }
420                         remove { Events.RemoveHandler (MouseEnterEvent, value); }
421                 }
422                 public event NodeEventHandler MouseLeave
423                 {
424                         add { Events.AddHandler (MouseLeaveEvent, value); }
425                         remove { Events.RemoveHandler (MouseLeaveEvent, value); }
426                 }
427                 public event NodeEventHandler MouseMove
428                 {
429                         add { Events.AddHandler (MouseMoveEvent, value); }
430                         remove { Events.RemoveHandler (MouseMoveEvent, value); }
431                 }
432                 public event NodeEventHandler MouseUp
433                 {
434                         add { Events.AddHandler (MouseUpEvent, value); }
435                         remove { Events.RemoveHandler (MouseUpEvent, value); }
436                 }
437                 public event EventHandler Focus
438                 {
439                         add { Events.AddHandler (FocusEvent, value); }
440                         remove { Events.RemoveHandler (FocusEvent, value); }
441                 }
442                 public event EventHandler Blur
443                 {
444                         add { Events.AddHandler (BlurEvent, value); }
445                         remove { Events.RemoveHandler (BlurEvent, value); }
446                 }
447                 public event CreateNewWindowEventHandler CreateNewWindow
448                 {
449                         add { Events.AddHandler (CreateNewWindowEvent, value); }
450                         remove { Events.RemoveHandler (CreateNewWindowEvent, value); }
451                 }
452                 public event AlertEventHandler Alert
453                 {
454                         add { Events.AddHandler (AlertEvent, value); }
455                         remove { Events.RemoveHandler (AlertEvent, value); }
456                 }
457                 public event EventHandler Loaded
458                 {
459                         add { Events.AddHandler (LoadEvent, value); }
460                         remove { Events.RemoveHandler (LoadEvent, value); }
461                 }
462                 public event EventHandler Unloaded
463                 {
464                         add { Events.AddHandler (UnloadEvent, value); }
465                         remove { Events.RemoveHandler (UnloadEvent, value); }
466                 }
467
468                 public event StatusChangedEventHandler StatusChanged
469                 {
470                         add { Events.AddHandler (StatusChangedEvent, value); }
471                         remove { Events.RemoveHandler (StatusChangedEvent, value); }
472                 }
473                 
474                 public event SecurityChangedEventHandler SecurityChanged
475                 {
476                         add { Events.AddHandler (SecurityChangedEvent, value); }
477                         remove { Events.RemoveHandler (SecurityChangedEvent, value); }
478                 }
479
480                 public event LoadStartedEventHandler LoadStarted
481                 {
482                         add { Events.AddHandler (LoadStartedEvent, value); }
483                         remove { Events.RemoveHandler (LoadStartedEvent, value); }
484                 }
485                 
486                 public event LoadCommitedEventHandler LoadCommited
487                 {
488                         add { Events.AddHandler (LoadCommitedEvent, value); }
489                         remove { Events.RemoveHandler (LoadCommitedEvent, value); }
490                 }               
491                 
492                 public event ProgressChangedEventHandler ProgressChanged
493                 {
494                         add { Events.AddHandler (ProgressChangedEvent, value); }
495                         remove { Events.RemoveHandler (ProgressChangedEvent, value); }
496                 }
497                 
498                 public event LoadFinishedEventHandler LoadFinished
499                 {
500                         add { Events.AddHandler (LoadFinishedEvent, value); }
501                         remove { Events.RemoveHandler (LoadFinishedEvent, value); }
502                 }
503
504                 public event ContextMenuEventHandler ContextMenuShown
505                 {
506                         add { Events.AddHandler (ContextMenuEvent, value); }
507                         remove { Events.RemoveHandler (ContextMenuEvent, value); }
508                 }
509
510                 public event NavigationRequestedEventHandler NavigationRequested
511                 {
512                         add { ContentListener.AddHandler (value); }
513                         remove { ContentListener.RemoveHandler (value); }
514                 }
515
516                 internal static object GenericEvent = new object ();
517                 internal event EventHandler Generic
518                 {
519                         add { Events.AddHandler (GenericEvent, value); }
520                         remove { Events.RemoveHandler (GenericEvent, value); }
521                 }
522
523                 #endregion
524
525
526         }
527 }