BrowserInteropHelper.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Interop / BrowserInteropHelper.cs / 1305600 / BrowserInteropHelper.cs

                            //---------------------------------------------------------------------------- 
//
// File: BrowserInteropHelper.cs
//
// Description: Implements Avalon BrowserInteropHelper class, which helps 
//              interop with the browser
// 
// Created: 08/02/05 
//
// Copyright (C) by Microsoft Corporation.  All rights reserved. 
//
//---------------------------------------------------------------------------

using System; 
using System.Runtime.InteropServices;
using System.Windows; 
using System.Windows.Interop; 
using System.Windows.Threading;
using System.Security; 
using System.Security.Permissions;
using System.Diagnostics;
using MS.Internal;
using MS.Win32; 
using System.Windows.Input;
using MS.Internal.AppModel; 
using MS.Internal.Interop; 
using System.Threading;
 
using SafeSecurityHelper=MS.Internal.PresentationFramework.SafeSecurityHelper;

namespace System.Windows.Interop
{ 
    /// 
    /// Implements Avalon BrowserInteropHelper, which helps interop with the browser 
    ///  
    public static class BrowserInteropHelper
    { 
        /// 
        /// Critical because it sets critical data.
        /// Safe because it is the static ctor, and the data doesn't go anywhere.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        static BrowserInteropHelper() 
        { 
            SetBrowserHosted(false);
            IsInitialViewerNavigation = true; 
        }

        /// 
        /// Returns the IOleClientSite interface 
        /// 
        ///  
        ///     Callers must have UnmanagedCode permission to call this API. 
        /// 
        ///  
        ///   Critical: Exposes a COM interface pointer to the IOleClientSite where the app is hosted
        ///   PublicOK: It is public, but there is a demand
        /// 
        public static object ClientSite 
        {
            [SecurityCritical] 
            get 
            {
                SecurityHelper.DemandUnmanagedCode(); 

                object oleClientSite = null;

                if (IsBrowserHosted) 
                {
                    Application.Current.BrowserCallbackServices.GetOleClientSite(out oleClientSite); 
                } 

                return oleClientSite; 
            }
        }

        ///  
        /// Critical: Calls a COM interface method.
        ///           Calls the constructor of DynamicScriptObject. 
        ///           Calls InitializeHostHtmlDocumentServiceProvider. 
        /// Safe: The browser's object model is safe for scripting.
        ///       The implementation of IHostBrowser.GetHostScriptObject() is responsible to block cross-domain access. 
        /// 
        public static dynamic HostScript
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                // Allows to disable script interop through the registry in partial trust code. 
                EnsureScriptInteropAllowed();
 
                // IE's marshaling proxy for the HTMLWindow object doesn't work in MTA.
                Verify.IsApartmentState(ApartmentState.STA);

                IHostBrowser2 hb2 = HostBrowser as IHostBrowser2; 
                if (hb2 == null)
                    return null; // One possibility is we are running under NPWPF v3.5. 
                try 
                {
                    var hostScriptObject = (UnsafeNativeMethods.IDispatch)hb2.HostScriptObject; 
                    if (hostScriptObject == null)
                        return null;

                    var scriptObject = new DynamicScriptObject(hostScriptObject); 

                    InitializeHostHtmlDocumentServiceProvider(scriptObject); 
 
                    return scriptObject;
                } 
                catch (UnauthorizedAccessException)
                {
                    return null;
                } 
            }
        } 
 
        /// 
        /// Returns true if the app is a browser hosted app. 
        /// 
        /// 
        /// Note that HostingFlags may not be set at the time this property is queried first.
        /// That's why they are still separate. Also, this one is public. 
        /// 
        public static bool IsBrowserHosted 
        { 
            get
            { 
                return _isBrowserHosted.Value;
            }
        }
 
        /// 
        /// This is critical because setting the BrowserHosted status is a critical resource. 
        ///  
        /// 
        /// HostingFlags is set after this property. 
        /// 
        [SecurityCritical]
        internal static void SetBrowserHosted(bool value)
        { 
            _isBrowserHosted.Value = value;
        } 
 
        /// 
        /// Critical: These flags are a critical resource because they are used in security decisions. 
        /// 
        internal static HostingFlags HostingFlags
        {
            get { return _hostingFlags.Value; } 
            [SecurityCritical]
            set { _hostingFlags.Value = value; } 
        } 

        ///  
        /// Returns the Uri used to launch the application.
        /// 
        public static Uri Source
        { 
            get
            { 
                return SiteOfOriginContainer.BrowserSource; 
            }
        } 

        /// 
        /// Returns true if we are running the XAML viewer pseudo-application (what used to be XamlViewer.xbap).
        /// This explicitly does not cover the case of XPS documents (MimeType.Document). 
        /// 
        internal static bool IsViewer 
        { 
            get
            { 
                Application app = Application.Current;
                return app != null && app.MimeType == MimeType.Markup;
            }
        } 

        ///  
        /// Returns true if avalon it top level. 
        /// Also returns true if not browser-hosted.
        ///  
        /// 
        /// Critical: setting this information is a critical resource.
        /// 
        internal static bool IsAvalonTopLevel 
        {
            get 
            { 
                if (!IsBrowserHosted)
                    return true; 
                return (HostingFlags & HostingFlags.hfHostedInFrame) == 0;
            }
        }
 
        /// 
        /// Returns true if the host browser is IE or the WebOC hosted in a standalone application. 
        /// Also returns false if not browser-hosted. 
        /// 
        internal static bool IsHostedInIEorWebOC 
        {
            get
            {
                return (HostingFlags & HostingFlags.hfHostedInIEorWebOC) != 0; 
            }
        } 
 
        /// 
        /// Returns true if we are in viewer mode AND this is the first time that a viewer has been navigated. 
        /// Including IsViewer is defense-in-depth in case somebody forgets to check IsViewer. There are other
        /// reasons why both IsViewer and IsViewerNavigation are necessary, however.
        /// 
        ///  
        /// Critical: setting this information is a critical resource.
        ///  
        internal static bool IsInitialViewerNavigation 
        {
            get 
            {
                return IsViewer && _isInitialViewerNavigation.Value;
            }
            [SecurityCritical] 
            set
            { 
                _isInitialViewerNavigation.Value = value; 
            }
        } 

        internal static IHostBrowser HostBrowser;

        ///  
        /// Critical: Calls Marshal.ReleaseComObject().
        ///           Drops the security critical service provider stored in _hostHtmlDocumentProvider. 
        ///  
        [SecurityCritical]
        internal static void ReleaseBrowserInterfaces() 
        {
            if (HostBrowser != null)
            {
                Marshal.ReleaseComObject(HostBrowser); 
                HostBrowser = null;
            } 
 
            if (_hostHtmlDocumentServiceProvider.Value != null)
            { 
                Marshal.ReleaseComObject(_hostHtmlDocumentServiceProvider.Value);
                _hostHtmlDocumentServiceProvider.Value = null;
            }
        } 

        ///  
        /// Retrieves the IServiceProvider object for the browser we're hosted in. 
        /// This is used for IDispatchEx operations in the script interop feature.
        ///  
        internal static UnsafeNativeMethods.IServiceProvider HostHtmlDocumentServiceProvider
        {
            get
            { 
                // HostHtmlDocumentServiceProvider is used by DynamicScriptObject for IDispatchEx
                // operations in case of IE. During initialization we get the document node from 
                // the DOM to obtain the required service provider. During this short timeframe 
                // it's valid to have a null-value returned here. In all other cases, we make sure
                // not to run with a null service provider for sake of security. 
                // See InitializeHostHtmlDocumentServiceProvider as well.
                /* */
                Invariant.Assert(!(_initializedHostScript.Value && _hostHtmlDocumentServiceProvider.Value == null));
 
                return _hostHtmlDocumentServiceProvider.Value;
            } 
        } 

        ///  
        /// Critical: Sets the critical _hostHtmlDocumentServiceProvider field, which is used during script
        ///           interop to let Internet Explorer make security decisions with regards to zones. By
        ///           passing in another service provider it may be possible to interfere with this logic.
        ///  
        [SecurityCritical]
        private static void InitializeHostHtmlDocumentServiceProvider(DynamicScriptObject scriptObject) 
        { 
            // The service provider is used for Internet Explorer IDispatchEx use.
            if (   IsHostedInIEorWebOC 
                && scriptObject.ScriptObject is UnsafeNativeMethods.IHTMLWindow4
                && _hostHtmlDocumentServiceProvider.Value == null)
            {
                // We use the IDispatch infrastructure to gain access to the document DOM node where 
                // the IServiceProvider lives that was recommended to us by IE people. Notice during
                // this call the HostHtmlDocumentServiceProvider property here is still null, so this 
                // first request is made (and succeeds properly) without the service provider in place. 
                object document;
                bool foundDoc = scriptObject.TryFindMemberAndInvokeNonWrapped("document", 
                                                                              NativeMethods.DISPATCH_PROPERTYGET,
                                                                              true  /* cache DISPID, why not? */,
                                                                              null, /* arguments */
                                                                              out document); 

                // The fact the host script is required to be a IHTMLWindow4 here ensures there is 
                // document property and because we're dealing with IE, we know it has a service 
                // provider on it.
                Invariant.Assert(foundDoc); 
                _hostHtmlDocumentServiceProvider.Value = (UnsafeNativeMethods.IServiceProvider)document;

                // See HostHtmlDocumentServiceProvider property get accessor for more information on the use of
                // this field to ensure we got a valid service provider. 
                _initializedHostScript.Value = true;
            } 
        } 

        ///  
        ///     Critical: this calls ForwardTranslateAccelerator, which is SUC'ed.
        /// 
        [SecurityCritical]
        private static void HostFilterInput(ref MSG msg, ref bool handled) 
        {
            WindowMessage message = (WindowMessage)msg.message; 
            // The host gets to see input, keyboard and mouse messages. 
            if (message == WindowMessage.WM_INPUT ||
                (message >= WindowMessage.WM_KEYFIRST && message <= WindowMessage.WM_IME_KEYLAST) || 
                (message >= WindowMessage.WM_MOUSEFIRST && message <= WindowMessage.WM_MOUSELAST))
            {
                if (MS.Win32.NativeMethods.S_OK == ForwardTranslateAccelerator(ref msg, false))
                { 
                    handled = true;
                } 
            } 
        }
 
        ///  This hook gets a "last chance" to handle a key. Such applicaton-unhandled
        /// keys are forwarded to the browser frame.
        /// 
        ///  
        ///     Critical: this calls ForwardTranslateAccelerator, which is SUC'ed.
        ///  
        [SecurityCritical] 
        internal static IntPtr PostFilterInput(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        { 
            if (!handled)
            {
                if ((WindowMessage)msg >= WindowMessage.WM_KEYFIRST && (WindowMessage)msg <= WindowMessage.WM_IME_KEYLAST)
                { 
                    MSG m = new MSG(hwnd, msg, wParam, lParam, SafeNativeMethods.GetMessageTime(), 0, 0);
                    if (MS.Win32.NativeMethods.S_OK == ForwardTranslateAccelerator(ref m, true)) 
                    { 
                        handled = true;
                    } 
                }
            }
            return IntPtr.Zero;
        } 

        ///  
        ///     Critical: this attaches an event to ThreadFilterMessage, which requires an assert 
        ///     Safe: doesn't expose anything, just does some internal plumbing stuff
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal static void InitializeHostFilterInput()
        {
            (new UIPermission(PermissionState.Unrestricted)).Assert(); // Blessed assert 
            try
            { 
                ComponentDispatcher.ThreadFilterMessage += 
                                    new ThreadMessageEventHandler(HostFilterInput);
            } 
            finally
            {
                UIPermission.RevertAssert();
            } 

        } 
 
        /// 
        ///     Critical: setting critical _isScriptInteropDisabled flag. 
        ///     Safe: _isScriptInteropDisabled is set from a trusted source.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private static void EnsureScriptInteropAllowed() 
        {
            if (_isScriptInteropDisabled.Value == null) 
            { 
                _isScriptInteropDisabled.Value = SafeSecurityHelper.IsFeatureDisabled(SafeSecurityHelper.KeyToRead.ScriptInteropDisable);
            } 

            // Similar approach as with WebBrowser.cs.
            if (_isScriptInteropDisabled.Value.Value)
            { 
                // Feature is disabled - demand unrestricted WebBrowserPermission to hand out the script object.
                MS.Internal.PresentationFramework.SecurityHelper.DemandWebBrowserPermission(); 
            } 
            else
            { 
                // Feature is enabled - demand Safe level to hand out the script object, granted in Partial Trust by default.
                (new WebBrowserPermission(WebBrowserPermissionLevel.Safe)).Demand();
            }
        } 

        private static SecurityCriticalDataForSet _isBrowserHosted; 
        private static SecurityCriticalDataForSet _hostingFlags; 
        private static SecurityCriticalDataForSet _isInitialViewerNavigation;
        private static SecurityCriticalDataForSet _isScriptInteropDisabled; 
        private static SecurityCriticalDataForSet _hostHtmlDocumentServiceProvider;
        private static SecurityCriticalDataForSet _initializedHostScript;

        /// 
        ///     Critical - call is SUC'ed
        /// 
        [SecurityCritical, SuppressUnmanagedCodeSecurity] 
        [DllImport(ExternDll.PresentationHostDll, EntryPoint="ForwardTranslateAccelerator")]
        private static extern int ForwardTranslateAccelerator(ref MSG pMsg, bool appUnhandled); 
    }
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK