Merge pull request #3066 from alexanderkyte/pedump_sgen
[mono.git] / mcs / class / Mono.WebBrowser / Mono.Mozilla / DOM / Document.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 using System;
27 using System.Runtime.InteropServices;
28 using System.Text;
29 using System.Collections;
30 using Mono.WebBrowser;
31 using Mono.WebBrowser.DOM;
32
33 namespace Mono.Mozilla.DOM
34 {
35         internal class Document : Node, IDocument
36         {
37
38                 internal nsIDOMDocument node {
39                         get { return base.node as nsIDOMDocument;}
40                         set { base.node = value as nsIDOMDocument; }
41                 }
42                 
43                 public Document (WebBrowser control, nsIDOMHTMLDocument document)
44                         : base (control, document)
45                 {
46                         if (control.platform != control.enginePlatform)
47                                 this.node = nsDOMHTMLDocument.GetProxy (control, document);
48                         else
49                                 this.node = document;
50                 }
51
52                 public Document (WebBrowser control, nsIDOMDocument document)
53                         : base (control, document)
54                 {
55                         if (control.platform != control.enginePlatform)
56                                 this.node = nsDOMDocument.GetProxy (control, document);
57                         else
58                                 this.node = document;
59                 }
60                 
61                 #region IDisposable Members
62                 protected override void Dispose (bool disposing)
63                 {
64                         if (!disposed) {
65                                 if (disposing) {
66                                         this.resources.Clear ();
67                                         this.node = null;
68                                 }
69                         }
70                         base.Dispose (disposing);
71                 }
72                 #endregion
73
74                 #region Internal
75                 internal new nsIDOMDocument XPComObject
76                 {
77                         get { return this.node; }
78                 }
79                 #endregion              
80
81                 #region IDocument Properties
82
83                 public IElement Active {
84                         get {
85                                 nsIDOMElement element;
86                                 nsIWebBrowserFocus webBrowserFocus = (nsIWebBrowserFocus) (control.navigation.navigation);
87                                 if (webBrowserFocus == null)
88                                         return null;
89                                 webBrowserFocus.getFocusedElement (out element);
90                                 return (IElement)GetTypedNode (element);
91 //                              if ((element as nsIDOMHTMLElement) != null)
92 //                                      return new HTMLElement (control, element as nsIDOMHTMLElement) as IElement;
93 //                              return new Element (control, element) as IElement;
94                         }
95                 }
96
97                 public string ActiveLinkColor {
98                         get {
99                                 if (!(node is nsIDOMHTMLDocument))
100                                         return String.Empty;
101                                 nsIDOMHTMLElement element;
102                                 ((nsIDOMHTMLDocument)node).getBody (out element);
103                                 ((nsIDOMHTMLBodyElement)element).getALink(storage);
104                                 return Base.StringGet (storage);
105                         }
106                         set {
107                                 if (!(node is nsIDOMHTMLDocument))
108                                         return;
109                                 Base.StringSet (storage, value);
110                                 nsIDOMHTMLElement element;
111                                 ((nsIDOMHTMLDocument)node).getBody (out element);
112                                 ((nsIDOMHTMLBodyElement)element).setALink(storage);
113                         }
114                 }
115                                 
116                 public IElementCollection Anchors {
117                         get {
118                                 if (!(node is nsIDOMHTMLDocument))
119                                         return null;
120                                 nsIDOMHTMLCollection ret;
121                                 ((nsIDOMHTMLDocument)node).getAnchors (out ret);
122                                 return new HTMLElementCollection(control, (nsIDOMNodeList)ret);
123                         }
124
125                 }
126
127                 public IElementCollection Applets {
128                         get {
129                                 if (!(node is nsIDOMHTMLDocument))
130                                         return null;
131                                 nsIDOMHTMLCollection ret;
132                                 ((nsIDOMHTMLDocument)node).getApplets (out ret);
133                                 return new HTMLElementCollection(control, (nsIDOMNodeList)ret);
134                         }
135
136                 }
137
138                 public string Background {
139                         get {
140                                 if (!(node is nsIDOMHTMLDocument))
141                                         return String.Empty;
142                                 nsIDOMHTMLElement element;
143                                 ((nsIDOMHTMLDocument)node).getBody (out element);
144                                 ((nsIDOMHTMLBodyElement)element).getBackground(storage);
145                                 return Base.StringGet (storage);
146                         }
147                         set {
148                                 if (!(node is nsIDOMHTMLDocument))
149                                         return;                         
150                                 Base.StringSet (storage, value);
151                                 nsIDOMHTMLElement element;
152                                 ((nsIDOMHTMLDocument)node).getBody (out element);
153                                 ((nsIDOMHTMLBodyElement)element).setBackground(storage);
154                         }
155                 }
156
157                 public string BackColor {
158                         get {
159                                 if (!(node is nsIDOMHTMLDocument))
160                                         return String.Empty;
161                                 nsIDOMHTMLElement element;
162                                 ((nsIDOMHTMLDocument)node).getBody (out element);
163                                 ((nsIDOMHTMLBodyElement)element).getBgColor(storage);
164                                 return Base.StringGet (storage);
165                         }
166                         set {
167                                 if (!(node is nsIDOMHTMLDocument))
168                                         return;                         
169                                 Base.StringSet (storage, value);
170                                 nsIDOMHTMLElement element;
171                                 ((nsIDOMHTMLDocument)node).getBody (out element);
172                                 ((nsIDOMHTMLBodyElement)element).setBgColor(storage);
173                         }
174                 }
175
176                 public IElement Body {
177                         get {
178                                 if (!(node is nsIDOMHTMLDocument))
179                                         return null;
180                                 
181                                 if (!resources.Contains ("Body")) {
182                                         nsIDOMHTMLElement element;
183                                         ((nsIDOMHTMLDocument)node).getBody (out element);
184                                         resources.Add ("Body", GetTypedNode (element));
185                                 }
186                                 return resources["Body"] as IElement;
187                         }
188                 }
189
190                 // This is the most ugly code *ever*. TODO: find out why a simple thing as getting the 
191                 // document encoding is not available in any frozen public interface
192                 public string Charset {
193                         get {           
194                                 nsIDOMDocumentView docView = (nsIDOMDocumentView) this.node;
195                                 nsIDOMAbstractView abstractView;
196                                 docView.getDefaultView (out abstractView);
197
198                                 nsIInterfaceRequestor requestor = (nsIInterfaceRequestor) abstractView;
199
200                                 IntPtr ret;                             
201                                 requestor.getInterface (typeof(nsIDocCharset).GUID, out ret);
202                                 nsIDocCharset charset = (nsIDocCharset) Marshal.GetObjectForIUnknown (ret);
203
204                                 StringBuilder s = new StringBuilder (30);
205                                 IntPtr r = Marshal.StringToHGlobalUni (s.ToString ());
206                                 charset.getCharset (ref r);
207
208                                 return Marshal.PtrToStringAnsi (r);
209                         }
210                         set {
211                                 nsIDOMDocumentView docView = (nsIDOMDocumentView) this.node;
212                                 nsIDOMAbstractView abstractView;
213                                 docView.getDefaultView (out abstractView);
214
215                                 nsIInterfaceRequestor requestor = (nsIInterfaceRequestor) abstractView;
216
217                                 IntPtr ret;
218                                 requestor.getInterface (typeof (nsIDocCharset).GUID, out ret);
219                                 nsIDocCharset charset = (nsIDocCharset) Marshal.GetTypedObjectForIUnknown (ret, typeof (nsIDocCharset));
220
221                                 charset.setCharset (value);
222                                 control.navigation.Go (this.Url, LoadFlags.CharsetChange);
223                         }
224                 }
225
226                 public string Cookie {
227                         get {
228                                 if (!(node is nsIDOMHTMLDocument))
229                                         return String.Empty;
230                                 ((nsIDOMHTMLDocument)node).getCookie (storage);
231                                 return Base.StringGet (storage);
232                         }
233                         set {
234                                 if (!(node is nsIDOMHTMLDocument))
235                                         return;                         
236                                 Base.StringSet (storage, value);
237                                 ((nsIDOMHTMLDocument)node).setCookie (storage);
238                         }
239                 }
240                 public string Domain {
241                         get {
242                                 if (!(node is nsIDOMHTMLDocument))
243                                         return String.Empty;
244                                 ((nsIDOMHTMLDocument)node).getDomain (storage);
245                                 return Base.StringGet (storage);
246                         }
247                 }
248                 public IElement DocumentElement {
249                         get {
250                                 if (!resources.Contains ("DocumentElement")) {
251                                         nsIDOMElement element;
252                                         this.node.getDocumentElement (out element);
253                                         resources.Add ("DocumentElement", GetTypedNode (element));
254                                 }
255                                 return resources["DocumentElement"] as IElement;
256                         }
257                 }
258                 
259                 public IDocumentType DocType {
260                         get {
261                                 nsIDOMDocumentType doctype;
262                                 this.node.getDoctype (out doctype);
263                                 return new DocumentType (this.control, doctype);
264                         }
265                 }
266                 
267
268                 public string ForeColor {
269                         get {
270                                 if (!(node is nsIDOMHTMLDocument))
271                                         return String.Empty;
272                                 nsIDOMHTMLElement element;
273                                 ((nsIDOMHTMLDocument)node).getBody (out element);
274                                 ((nsIDOMHTMLBodyElement)element).getText(storage);
275                                 return Base.StringGet (storage);
276                         }
277                         set {
278                                 if (!(node is nsIDOMHTMLDocument))
279                                         return;
280                                 Base.StringSet (storage, value);
281                                 nsIDOMHTMLElement element;
282                                 ((nsIDOMHTMLDocument)node).getBody (out element);
283                                 ((nsIDOMHTMLBodyElement)element).setText(storage);
284                         }
285                 }
286
287                 public IElementCollection Forms {
288                         get {
289                                 if (!(node is nsIDOMHTMLDocument))
290                                         return null;
291                                 nsIDOMHTMLCollection ret;
292                                 ((nsIDOMHTMLDocument)node).getForms (out ret);
293                                 return new HTMLElementCollection(control, (nsIDOMNodeList)ret);
294                         }
295
296                 }
297
298                 public IElementCollection Images {
299                         get {
300                                 if (!(node is nsIDOMHTMLDocument))
301                                         return null;
302                                 nsIDOMHTMLCollection ret;
303                                 ((nsIDOMHTMLDocument)node).getImages (out ret);
304                                 return new HTMLElementCollection(control, (nsIDOMNodeList)ret);
305                         }
306
307                 }
308                 
309                 public IDOMImplementation Implementation {
310                         get {
311                                 nsIDOMDOMImplementation implementation;
312                                 node.getImplementation (out implementation);
313                                 return new DOMImplementation (this.control, implementation);
314                         }
315                 }
316
317                 public string LinkColor {
318                         get {
319                                 if (!(node is nsIDOMHTMLDocument))
320                                         return String.Empty;
321                                 nsIDOMHTMLElement element;
322                                 ((nsIDOMHTMLDocument)node).getBody (out element);
323                                 ((nsIDOMHTMLBodyElement)element).getLink(storage);
324                                 return Base.StringGet (storage);
325                         }
326                         set {
327                                 if (!(node is nsIDOMHTMLDocument))
328                                         return;
329                                 Base.StringSet (storage, value);
330                                 nsIDOMHTMLElement element;
331                                 ((nsIDOMHTMLDocument)node).getBody (out element);
332                                 ((nsIDOMHTMLBodyElement)element).setLink(storage);
333                         }
334                 }
335
336                 public IElementCollection Links {
337                         get {
338                                 if (!(node is nsIDOMHTMLDocument))
339                                         return null;
340                                 nsIDOMHTMLCollection ret;
341                                 ((nsIDOMHTMLDocument)node).getLinks (out ret);
342                                 return new HTMLElementCollection(control, (nsIDOMNodeList)ret);
343                         }
344
345                 }
346                 
347                 public IStylesheetList Stylesheets
348                 {
349                         get {
350                                 nsIDOMStyleSheetList styleList;
351                                 nsIDOMDocumentStyle docStyle = ((nsIDOMDocumentStyle)this.node);
352                                 docStyle.getStyleSheets (out styleList);
353                                 return new StylesheetList (this.control, styleList);
354                         }
355                 }
356                 
357                 public string Title {
358                         get {
359                                 if (!(node is nsIDOMHTMLDocument))
360                                         return String.Empty;
361                                 ((nsIDOMHTMLDocument)node).getTitle (storage);
362                                 return Base.StringGet (storage);
363                         }
364                         set {
365                                 Base.StringSet (storage, value);
366                                 ((nsIDOMHTMLDocument)node).setTitle (storage);
367                         }
368                 }
369
370                 public string Url {
371                         get {
372                                 if (!(node is nsIDOMHTMLDocument))
373                                         return String.Empty;
374                                 ((nsIDOMHTMLDocument)node).getURL (storage);
375                                 return Base.StringGet (storage);
376                         }
377                 }
378
379                 public string VisitedLinkColor {
380                         get {
381                                 if (!(node is nsIDOMHTMLDocument))
382                                         return String.Empty;
383                                 nsIDOMHTMLElement element;
384                                 ((nsIDOMHTMLDocument)node).getBody (out element);
385                                 ((nsIDOMHTMLBodyElement)element).getVLink(storage);
386                                 return Base.StringGet (storage);
387                         }
388                         set {
389                                 if (!(node is nsIDOMHTMLDocument))
390                                         return;
391                                 Base.StringSet (storage, value);
392                                 nsIDOMHTMLElement element;
393                                 ((nsIDOMHTMLDocument)node).getBody (out element);
394                                 ((nsIDOMHTMLBodyElement)element).setVLink(storage);
395                         }
396                 }
397                 
398                 public IWindow Window {
399                         get {
400                                 nsIDOMDocumentView docView = (nsIDOMDocumentView) this.node;
401                                 nsIDOMAbstractView abstractView;
402                                 docView.getDefaultView (out abstractView);
403                                 nsIInterfaceRequestor requestor = (nsIInterfaceRequestor) abstractView;
404                                 if (requestor == null)
405                                         return null;
406                                 IntPtr ret;                             
407                                 requestor.getInterface (typeof(nsIDOMWindow).GUID, out ret);
408                                 nsIDOMWindow window = (nsIDOMWindow) Marshal.GetObjectForIUnknown (ret);
409                                 return new Window (this.control, window);
410                         }
411                 }
412
413                 #endregion
414
415                 #region Public IDocument Methods
416                 public IAttribute CreateAttribute (string name)
417                 {
418                         nsIDOMAttr nsAttribute;
419                         Base.StringSet (storage, name);
420                         this.node.createAttribute (storage, out nsAttribute);
421                         return new Attribute (control, nsAttribute);                    
422                 }
423
424                 public IElement CreateElement (string tagName)
425                 {
426                         nsIDOMElement nsElement;
427                         Base.StringSet (storage, tagName);
428                         this.node.createElement (storage, out nsElement);
429                         if (node is nsIDOMHTMLDocument)
430                                 return new HTMLElement (control, (nsIDOMHTMLElement)nsElement);
431                         return new Element (control, nsElement);                        
432                 }
433
434                 public IElement GetElementById (string id)
435                 {
436                         if (!resources.Contains ("GetElementById" + id)) {
437                                 nsIDOMElement nsElement;
438                                 Base.StringSet (storage, id);
439                                 this.node.getElementById (storage, out nsElement);
440                                 if (nsElement == null)
441                                         return null;
442                                 resources.Add ("GetElementById" + id, GetTypedNode (nsElement));
443                         }
444                         return resources["GetElementById" + id] as IElement;
445                 }
446
447                 public IElementCollection GetElementsByTagName (string name)
448                 {
449                         if (!resources.Contains ("GetElementsByTagName" + name)) {
450                                 nsIDOMNodeList nodes;
451                                 this.node.getElementsByTagName (storage, out nodes);
452                                 if (nodes == null)
453                                         return null;
454                                 resources.Add ("GetElementsByTagName" + name, new HTMLElementCollection(control, nodes));
455                         }
456                         return resources["GetElementsByTagName" + name] as IElementCollection;
457                 }
458
459                 public IElement GetElement (int x, int y)
460                 {
461                         nsIDOMNodeList nodes;
462                         this.node.getChildNodes (out nodes);
463                         HTMLElementCollection col = new HTMLElementCollection(control, nodes);
464                         IElement ret = null;
465                         foreach (Element el in col) {
466                                 if (el.Left <= x && el.Top <= y &&
467                                         el.Left + el.Width >= x && el.Top + el.Height >= y) {
468                                         ret = el;
469                                         break;
470                                 }
471                         }
472                         return ret;
473                 }
474                 
475                 public void Write (string text) {
476                         if (!(node is nsIDOMHTMLDocument))
477                                 return;
478                         Base.StringSet (storage, text);
479                         ((nsIDOMHTMLDocument)node).write (storage);
480                 }
481
482                 public string InvokeScript (string script)
483                 {
484                         return Base.EvalScript (this.control, script);
485                 }
486                 
487                 #endregion
488                 
489                 #region Events
490                 private System.ComponentModel.EventHandlerList events;
491                 internal System.ComponentModel.EventHandlerList Events {
492                         get {
493                                 if (events == null)
494                                         events = new System.ComponentModel.EventHandlerList();
495
496                                 return events;
497                         }
498                 }
499                 internal static object LoadStoppedEvent = new object ();
500                 public event EventHandler LoadStopped
501                 {
502                         add { Events.AddHandler (LoadStoppedEvent, value); }
503                         remove { Events.RemoveHandler (LoadStoppedEvent, value); }
504                 }
505                 #endregion
506                 
507                 
508                 public override int GetHashCode () {
509                         return this.node.GetHashCode ();
510                 }               
511         }
512 }