void nsIContextMenuListener2.OnShowContextMenu(uint aContextFlags, nsIContextMenuInfo info)
        {
            // if we don't have a target node, we can't do anything by default.  this happens in XUL forms (i.e. about:config)
            if (info.GetTargetNode() == null)
                return;

            ContextMenu menu = new ContextMenu();

            // no default items are added when the context menu is disabled
            if (!this.NoDefaultContextMenu)
            {
                List<MenuItem> optionals = new List<MenuItem>();

                if (this.CanUndo || this.CanRedo)
                {
                    optionals.Add(new MenuItem("Undo", delegate { Undo(); }));
                    optionals.Add(new MenuItem("Redo", delegate { Redo(); }));

                    optionals[0].Enabled = this.CanUndo;
                    optionals[1].Enabled = this.CanRedo;
                }
                else
                {
                    optionals.Add(new MenuItem("Back", delegate { GoBack(); }));
                    optionals.Add(new MenuItem("Forward", delegate { GoForward(); }));

                    optionals[0].Enabled = this.CanGoBack;
                    optionals[1].Enabled = this.CanGoForward;
                }

                optionals.Add(new MenuItem("-"));

                if (this.CanCopyImageContents)
                    optionals.Add(new MenuItem("Copy Image Contents", delegate { CopyImageContents(); }));

                if (this.CanCopyImageLocation)
                    optionals.Add(new MenuItem("Copy Image Location", delegate { CopyImageLocation(); }));

                if (this.CanCopyLinkLocation)
                    optionals.Add(new MenuItem("Copy Link Location", delegate { CopyLinkLocation(); }));

                if (this.CanCopySelection)
                    optionals.Add(new MenuItem("Copy Selection", delegate { CopySelection(); }));

                MenuItem mnuSelectAll = new MenuItem("Select All");
                mnuSelectAll.Click += delegate { SelectAll(); };

                GeckoDocument doc = GeckoDocument.Create((nsIDOMHTMLDocument)info.GetTargetNode().GetOwnerDocument());

                string viewSourceUrl = (doc == null) ? null : Convert.ToString(doc.Url);

                MenuItem mnuViewSource = new MenuItem("View Source");
                mnuViewSource.Enabled = !string.IsNullOrEmpty(viewSourceUrl);
                mnuViewSource.Click += delegate { ViewSource(viewSourceUrl); };

                string properties = (doc != null && doc.Url == Document.Url) ? "Page Properties" : "IFRAME Properties";

                MenuItem mnuProperties = new MenuItem(properties);
                mnuProperties.Enabled = doc != null;
                mnuProperties.Click += delegate { ShowPageProperties(doc); };

                menu.MenuItems.AddRange(optionals.ToArray());
                menu.MenuItems.Add(mnuSelectAll);
                menu.MenuItems.Add("-");
                menu.MenuItems.Add(mnuViewSource);
                menu.MenuItems.Add(mnuProperties);
            }

            // get image urls
            Uri backgroundImageSrc = null, imageSrc = null;
            nsIURI src;

            if (info.GetBackgroundImageSrc(out src) == 0)
            {
                backgroundImageSrc = new Uri(new nsURI(src).Spec);
            }

            if (info.GetImageSrc(out src) == 0)
            {
                imageSrc = new Uri(new nsURI(src).Spec);
            }

            // get associated link.  note that this needs to be done manually because GetAssociatedLink returns a non-zero
            // result when no associated link is available, so an exception would be thrown by nsString.Get()
            string associatedLink = null;
            using (nsAString str = new nsAString())
            {
                if (info.GetAssociatedLink(str) == 0)
                {
                    associatedLink = str.ToString();
                }
            }

            GeckoContextMenuEventArgs e = new GeckoContextMenuEventArgs(
                PointToClient(MousePosition), menu, associatedLink, backgroundImageSrc, imageSrc,
                GeckoNode.Create(Xpcom.QueryInterface<nsIDOMNode>(info.GetTargetNode()))
                );

            OnShowContextMenu(e);

            if (e.ContextMenu != null && e.ContextMenu.MenuItems.Count > 0)
            {
                e.ContextMenu.Show(this, e.Location);
            }
        }
		void nsIContextMenuListener2.OnShowContextMenu(uint aContextFlags, nsIContextMenuInfo info)
		{
			List<MenuItem> optionals = new List<MenuItem>();
			
			if (this.CanUndo || this.CanRedo)
			{
				optionals.Add(new MenuItem("Undo", delegate { Undo(); }));
				optionals.Add(new MenuItem("Redo", delegate { Redo(); }));
				
				optionals[0].Enabled = this.CanUndo;
				optionals[1].Enabled = this.CanRedo;
			}
			else
			{
				optionals.Add(new MenuItem("Back", delegate { GoBack(); }));
				optionals.Add(new MenuItem("Forward", delegate { GoForward(); }));
				
				optionals[0].Enabled = this.CanGoBack;
				optionals[1].Enabled = this.CanGoForward;
			}
			
			optionals.Add(new MenuItem("-"));
			
			if (this.CanCopyImageContents)
				optionals.Add(new MenuItem("Copy Image Contents", delegate { CopyImageContents(); }));
			
			if (this.CanCopyImageLocation)
				optionals.Add(new MenuItem("Copy Image Location", delegate { CopyImageLocation(); }));
			
			if (this.CanCopyLinkLocation)
				optionals.Add(new MenuItem("Copy Link Location", delegate { CopyLinkLocation(); }));
			
			if (this.CanCopySelection)
				optionals.Add(new MenuItem("Copy Selection", delegate { CopySelection(); }));
			
			MenuItem mnuSelectAll = new MenuItem("Select All");
			mnuSelectAll.Click += delegate { SelectAll(); };
			
			GeckoDocument doc = GeckoDocument.Create((nsIDOMHTMLDocument)info.GetTargetNode().GetOwnerDocument());
			
			string viewSourceUrl = (doc == null) ? null : Convert.ToString(doc.Url);
			
			MenuItem mnuViewSource = new MenuItem("View Source");
			mnuViewSource.Enabled = !string.IsNullOrEmpty(viewSourceUrl);
			mnuViewSource.Click += delegate { ViewSource(viewSourceUrl); };
			
			string properties = (doc.Url == Document.Url) ? "Page Properties" : "IFRAME Properties";
			
			MenuItem mnuProperties = new MenuItem(properties);
			mnuProperties.Enabled = true;
			mnuProperties.Click += delegate { ShowPageProperties(doc); };
			
			ContextMenu menu = new ContextMenu();
			menu.MenuItems.AddRange(optionals.ToArray());
			menu.MenuItems.Add(mnuSelectAll);
			menu.MenuItems.Add("-");
			menu.MenuItems.Add(mnuViewSource);
			menu.MenuItems.Add(mnuProperties);
			
			menu.Show(this, PointToClient(MousePosition));
		}