未验证 提交 8a32ce0a 编写于 作者: V Vatsan Madhavan 提交者: GitHub

Cleanup #if NETFX guarded code and remove XBAP related types (#1009)

* Remove CallerHasPermissionWithAppDomainOptimization
* Remove the following:
 - AppDomainGrantedUnrestrictedUIPermission
- CallerAndAppDomainHaveUnrestrictedWebBrowserPermission
- AppDomainHasPermission
- IsWebOCHostedInBrowserProcess
- IsWebOCPermissionRestricted
- WebOCHostedInBrowserAdaptor
* Remove #if NETFX from WebBrowser.cs
* Remove IsOnNetworkShareForDeployedApps
* Hollow out BrowserInteropHelper.IsBrowserHosted
* Fixes to DynamicScriptObject and StartupEventArgs
* Remove DocObjHost type
* Update HostScript
* Remove IHostBrowser, IHostBrowser2
* Remove IBrowserCallbackServices
* Cleanup Application.cs
* Cleanup BindStream
* Cleanup lingering #if NETFX in BrowserInteropHelper
* Remove #if NETFX from NavigationService
* Remove remaining #if NETFX controlled code
* Simplifying GetKeyStatesFromSystem
上级 9271e6e3
Compat issues with assembly PresentationFramework:
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.AttachedPropertyBrowsableForChildrenAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.ResourceReferenceKeyNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.StyleTypedPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.TemplatePartAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.TemplateVisualStateAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.ThemeInfoAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Controls.PrintDialogException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Data.ValueConversionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Data.ValueUnavailableException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Documents.TextElementEditingBehaviorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Markup.XamlParseException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveAttribute : Attribute 'System.Security.SecurityCriticalAttribute' exists on 'System.Windows.Shell.JumpList' in the contract but not the implementation.
Total Issues: 12
Compat issues with assembly PresentationFramework:
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.AttachedPropertyBrowsableForChildrenAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.ResourceReferenceKeyNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.StyleTypedPropertyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.TemplatePartAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.TemplateVisualStateAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.ThemeInfoAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Controls.PrintDialogException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Data.ValueConversionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Data.ValueUnavailableException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Documents.TextElementEditingBehaviorAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Windows.Interop.DocObjHost' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Windows.Markup.XamlParseException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveAttribute : Attribute 'System.Security.SecurityCriticalAttribute' exists on 'System.Windows.Shell.JumpList' in the contract but not the implementation.
Total Issues: 13
......@@ -11217,12 +11217,7 @@ public static partial class BrowserInteropHelper
public static bool IsBrowserHosted { get { throw null; } }
public static System.Uri Source { get { throw null; } }
}
public sealed partial class DocObjHost : System.MarshalByRefObject, System.IServiceProvider
{
public DocObjHost() { }
public override object InitializeLifetimeService() { throw null; }
object System.IServiceProvider.GetService(System.Type serviceType) { throw null; }
}
public sealed partial class DynamicScriptObject : System.Dynamic.DynamicObject
{
internal DynamicScriptObject() { }
......
......@@ -47,55 +47,14 @@ protected override KeyStates GetKeyStatesFromSystem(Key key)
{
KeyStates keyStates = KeyStates.None;
bool getKeyStatesFromSystem = false;
if(IsActive)
{
// Our keyboard device is only active if some WPF window in
// this AppDomain has focus. It is always safe to return
// the state of keys.
getKeyStatesFromSystem = true;
}
else if (SecurityHelper.AppDomainGrantedUnrestrictedUIPermission)
{
// This is a trusted AppDomain, so we are willing to expose
// the state of keys regardless of whether or not a WPF
// window has focus. This is important for child HWND
// hosting scenarios.
getKeyStatesFromSystem = true;
}
else
{
// Security Mitigation:
// No WPF window has focus in this AppDomain, and this is a
// partially-trusted AppDomain, so we do not generally want
// to expose the state of keys. However, we make an exception
// for modifier keys, as they are considered safe.
switch (key)
{
case Key.LeftAlt:
case Key.RightAlt:
case Key.LeftCtrl:
case Key.RightCtrl:
case Key.LeftShift:
case Key.RightShift:
getKeyStatesFromSystem = true;
break;
}
}
int virtualKeyCode = KeyInterop.VirtualKeyFromKey(key);
int nativeKeyState = UnsafeNativeMethods.GetKeyState(virtualKeyCode);
if (getKeyStatesFromSystem)
{
int virtualKeyCode = KeyInterop.VirtualKeyFromKey(key);
int nativeKeyState;
if ((nativeKeyState & 0x00008000) == 0x00008000)
keyStates |= KeyStates.Down;
nativeKeyState = UnsafeNativeMethods.GetKeyState(virtualKeyCode);
if( (nativeKeyState & 0x00008000) == 0x00008000 )
keyStates |= KeyStates.Down;
if( (nativeKeyState & 0x00000001) == 0x00000001 )
keyStates |= KeyStates.Toggled;
}
if ((nativeKeyState & 0x00000001) == 0x00000001)
keyStates |= KeyStates.Toggled;
return keyStates;
}
......
......@@ -103,38 +103,29 @@ bool IKeyboardInputProvider.AcquireFocus(bool checkOnly)
// In either case, the window must be enabled.
if(SafeNativeMethods.IsWindowEnabled(thisWindow))
{
if (SecurityHelper.AppDomainGrantedUnrestrictedUIPermission)
{
// In fully-trusted AppDomains, the only hard requirement
// is that Win32 keyboard focus be on some window owned
// by a thread that is attached to our Win32 queue. This
// presumes that the thread's message pump will cooperate
// by calling ComponentDispatcher.RaiseThreadMessage.
// If so, WPF will be able to route the keyboard events to the
// element with WPF keyboard focus, regardless of which
// window has Win32 keyboard focus.
//
// Menus/ComboBoxes use this feature.
//
// Dev11 is moving more towards cross-process designer
// support. They make sure to call AttachThreadInput so
// the the two threads share the same Win32 queue. In
// addition, they repost the keyboard messages to the
// main UI process/thread for handling.
//
// We rely on the behavior of GetFocus to only return a
// window handle for windows attached to the calling
// thread's queue.
//
result = focus != IntPtr.Zero;
}
else
{
// In partially-trusted AppDomains, we do not want to expose input
// intended for other native windows, or for WPF windows in other
// AppDomains.
result = IsOurWindow(focus);
}
// In fully-trusted AppDomains, the only hard requirement
// is that Win32 keyboard focus be on some window owned
// by a thread that is attached to our Win32 queue. This
// presumes that the thread's message pump will cooperate
// by calling ComponentDispatcher.RaiseThreadMessage.
// If so, WPF will be able to route the keyboard events to the
// element with WPF keyboard focus, regardless of which
// window has Win32 keyboard focus.
//
// Menus/ComboBoxes use this feature.
//
// Dev11 is moving more towards cross-process designer
// support. They make sure to call AttachThreadInput so
// the the two threads share the same Win32 queue. In
// addition, they repost the keyboard messages to the
// main UI process/thread for handling.
//
// We rely on the behavior of GetFocus to only return a
// window handle for windows attached to the calling
// thread's queue.
//
result = focus != IntPtr.Zero;
}
}
else
......
......@@ -340,13 +340,7 @@ private void Initialize(HwndSourceParameters parameters)
AddSource();
// Register dropable window.
// The checking CallerHasPermissionWithAppDomainOptimization will call RegisterDropTarget
// safely without the security exception in case of no unmanaged code permission.
// So RegisterDropTarget will be called safely in case of having the unmanged code permission.
// Otherwise, the security exception cause System.Printing to be instatiated which will
// load system.drawing module.
if (_hwndWrapper.Handle != IntPtr.Zero &&
SecurityHelper.CallerHasPermissionWithAppDomainOptimization(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)))
if (_hwndWrapper.Handle != IntPtr.Zero)
{
// This call is safe since DragDrop.RegisterDropTarget is checking the unmanged
// code permission.
......
......@@ -105,29 +105,7 @@ internal static LaunchResult SafeLaunchBrowserOnlyIfPossible(Uri originatingUri,
MS.Internal.PresentationFramework.SecurityHelper.CallerHasUserInitiatedNavigationPermission()) &&
((fIsTopLevel && isKnownScheme) || fIsMailTo))
{
if (isKnownScheme)
{
#if NETFX
IBrowserCallbackServices ibcs = ( Application.Current != null ) ? Application.Current.BrowserCallbackServices : null ;
if (ibcs != null)
{
launched = CanNavigateToUrlWithZoneCheck(originatingUri , destinationUri);
if ( launched == LaunchResult.Launched )
{
// resetting launched to NotLaunched here; if the assert succeeds
// and ibcs.DelegateNavigation does not throw then we will set it to Launched.
launched = LaunchResult.NotLaunched;
// Browser app.
// We need to see if this is the right behavior when clicking on a link in
// a secondary window in a multi-window browser app
ibcs.DelegateNavigation( BindUriHelper.UriToString( destinationUri ), targetName, GetHeaders(destinationUri));
launched = LaunchResult.Launched ;
}
}
#endif
}
else if (fIsMailTo) // unnecessary if - but being paranoid.
if (!isKnownScheme && fIsMailTo) // unnecessary if - but being paranoid.
{
// Shell-Exec the browser to the mailto url.
// assumed safe - because we're only allowing this for mailto urls.
......@@ -150,22 +128,6 @@ internal static LaunchResult SafeLaunchBrowserOnlyIfPossible(Uri originatingUri,
// Whoever is calling this function should do the right demands.
internal static void UnsafeLaunchBrowser(Uri uri, string targetFrame = null)
{
#if NETFX
// This'll likely go into SafeLaunchBrowser() function.
if (Application.Current != null && Application.Current.CheckAccess())
{
IBrowserCallbackServices ibcs = Application.Current.BrowserCallbackServices;
if (ibcs != null)
{
// Browser app.
// TODO: See if this is the right behavior when clicking on a link in
// a secondary window in a multi-window browser app - PS # 840726
ibcs.DelegateNavigation(BindUriHelper.UriToString(uri), targetFrame, GetHeaders(uri));
return;
}
}
#endif
ShellExecuteDefaultBrowser(uri);
}
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// Description:
// Managed definition for IBrowserCallbackServices & IHostBrowser, used for
// communicating from managed code back to the native DocObject code and the
// in-proc handlers in the host browser.
//
// ***********************IMPORTANT**************************
//
// If you change any of the interface definitions here
// make sure you also change the interface definitions
// on the native side (src\host\inc\HostServices.idl & HostSupport.idl).
// If you are not sure about how to define it
// here, TEMPORARILY mark the interface as
// ComVisible in the managed side, use tlbexp to generate
// a typelibrary from the managed dll and copy the method
// signatures from there. REMEMBER to remove the ComVisible
// in the managed code when you are done.
// Defining the interfaces at both ends prevents us from
// publicly exposing these interfaces to the outside world.
// In order for marshaling to work correctly, the vtable
// and data types should match EXACTLY in both the managed
// and unmanaged worlds
//
using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Windows.Interop;
using MS.Internal;
using MS.Utility;
using MS.Internal.Interop;
namespace MS.Internal.AppModel
{
//********************************************************************************************//
// IMPORTANT: IMPORTANT: IMPORTANT: IMPORTANT: //
//********************************************************************************************//
// If you change or update this interface, make sure you update the definitions in
// wcp\host\inc\hostservices.idl
/// <summary>
/// Internal interface used for Interop in browser hosting scenarios. This
/// interface is passed in by the Docobj Server hosted in the browser and is
/// used to communicate from the Windows Client application back to the browser
/// The master definition is in HostServices.idl.
/// </summary>
/// <remarks>
/// The original (v1) interface has been partly superseded by IHostBrowser.
/// </remarks>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("5FFAD804-61C8-445c-8C31-A2101C64C510")]
internal interface IBrowserCallbackServices
{
void OnBeforeShowNavigationWindow();
/// <summary>
/// Causes the browser host to fire a ReadyState change to Complete to let
/// shdocvw know that the navigation is complete
/// </summary>
/// <param name="readyState"></param>
void PostReadyStateChange([In, MarshalAs(UnmanagedType.I4)] int readyState);
/// <summary>
/// Allows browser host to navigate to the url. This method is typically called
/// to delegate navigation back to the browser for mime types we don't handle eg: html
/// </summary>
/// <param name="url"></param>
/// <param name="targetName"></param>
/// <param name="headers"></param>
/// <returns></returns>
void DelegateNavigation([In, MarshalAs(UnmanagedType.BStr)] string url, [In, MarshalAs(UnmanagedType.BStr)] string targetName, [In, MarshalAs(UnmanagedType.BStr)] string headers);
/// <summary>
/// Notifies the avalon host to update the address bar with the current url
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
[PreserveSig]
[return: MarshalAs(UnmanagedType.Bool)]
bool UpdateAddressBar([In, MarshalAs(UnmanagedType.BStr)] string url);
/// <summary>
/// When the internal Journal state changes, we need to make sure it is reflected
/// appropriately in the browser. Adding entries will make this happen automatically
/// since we explicitly add entries to the browser's TravelLog
/// We need this callback for the following purposes
/// 1.. Deleting visible entries will not reflect the change immediately unless
/// we explicitly notify the browser (think the browser calls CanInvoke but its nice
/// to update UI immediately)
/// 2. Back/Forward state needs to be updated automatically when frames are
/// programmatically removed from the tree. Since frames don't have their own
/// journal, reparenting a frame to a new tree doesn't affect the new tree.
/// Its only the tree state where it is being removed from that is affected.
/// </summary>
[PreserveSig]
void UpdateBackForwardState();
/// <summary>
/// Add entry to shdocvw's TravelLog. Will fail on downlevel platform.
/// </summary>
/// <param name="topLevelNav"></param>
/// <param name="addNewEntry"></param>
/// <returns></returns>
void UpdateTravelLog([In, MarshalAs(UnmanagedType.Bool)]bool addNewEntry);
/// <summary>
/// Change status of progress bar.
/// </summary>
/// <returns></returns>
[PreserveSig]
[return: MarshalAs(UnmanagedType.Bool)]
bool UpdateProgress([In, MarshalAs(UnmanagedType.I8)]long cBytesCompleted, [In, MarshalAs(UnmanagedType.I8)]long cBytesTotal);
/// <summary>
/// Change the download state (spin the globe/wave the flag).
/// </summary>
/// <returns></returns>
[PreserveSig]
[return: MarshalAs(UnmanagedType.Bool)]
bool ChangeDownloadState([In]bool fIsDownloading);
/// <summary>
/// Is this a downlevel platform that is not fully integrated
/// </summary>
[PreserveSig]
[return: MarshalAs(UnmanagedType.Bool)]
bool IsDownlevelPlatform();
/// <summary>
/// Check if browser is shutting us down
/// </summary>
[PreserveSig]
[return: MarshalAs(UnmanagedType.Bool)]
bool IsShuttingDown();
/// <summary>
/// Moves focus out of the application, to the browser frame.
/// </summary>
[PreserveSig]
bool TabOut(bool forward);
/// <summary>
/// When an unhandled exception occurs in PresentationHost a stack trace is generated
/// and passed to native code via this method. Then an html error page is generated
/// and the browser navigates to it.
/// NOTE: There's also a DLL-exported function from PresentationHostDll for this purpose.
/// See DocObjHost.ProcessUnhandledException().
/// </summary>
[PreserveSig]
void ProcessUnhandledException([In, MarshalAs(UnmanagedType.BStr)] string pErrorMsg);
/// <summary>
/// Returns the IOleClientSite interface
/// </summary>
[PreserveSig]
int GetOleClientSite([Out, MarshalAs(UnmanagedType.IUnknown)] out object oleClientSite);
/// <summary>
/// Asks the browser to re-query for command status
/// </summary>
[PreserveSig]
int UpdateCommands();
/// <remarks>
/// The return value is declared as an IntPtr, not as a typed IWebBrowser2 interface, to prevent CLR
/// Remoting from getting involved when the object is passed cross-AppDomain. When making calls on this
/// interface, there is no point in switching to the default AppDomain, given that that object actually
/// lives in another process.
/// The caller must call Release() on the COM interface.
/// </remarks>
IntPtr CreateWebBrowserControlInBrowserProcess();
}
/// <summary>
/// [See master definition in HostSupport.idl.]
/// </summary>
[ComImport, Guid("AD5D6F02-5F4E-4D77-9FC0-381981317144"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IHostBrowser
{
/// <summary>
/// Returns the browser's top-level URL and whether the DocObject is top-level or in a frame.
/// If querying from a frame in a less secure zone than the top window, NULL may be returned for top-level URL.
/// </summary>
string DetermineTopLevel(out bool pbIsTopLevel);
/// <summary>
/// Delegates a navigation to the browser. This may cause the Avalon application to be shut down.
/// targetName is the name of a frame/window or one of the predefined targets: _parent, _blank, etc.
/// Normally, IBCS.DelegateNavigation() should be used instead. It calls CoAllowSetForegroundWindow()
/// to let a new browser window become active.
/// </summary>
void Navigate(string url, string targetName = null, string headers = null);
void GoBack();
void GoForward();
void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string title);
[PreserveSig]
long SetStatusText([MarshalAs(UnmanagedType.LPWStr)] string text);
void SetWidth(uint width);
void SetHeight(uint height);
uint GetWidth();
uint GetHeight();
int GetLeft();
int GetTop();
// These methods should not be used directly. They are used in the implementation of the cookie shim in PHDLL.
// Managed code can use Application.Get/SetCookie().
string GetCookie_DoNotUse(string url, string cookieName, bool thirdParty);
void SetCookie_NoNotUse(string url, string cookieName, string cookieData, bool thirdParty, string P3PHeader = null);
[PreserveSig]
MS.Internal.Interop.HRESULT GetUserAgentString(out string userAgent);
// The implementation of IBCS.CreateWebBrowserControlInBrowserProcess() performs an important security
// check before calling this method.
void CreateWebBrowserControl_DoNotUse([Out] out IntPtr ppWebBrowser);
void TabOut_v35SP1QFE(bool forward);
};
[ComImport, Guid("AD5D6F03-0002-4D77-9FC0-381981317144"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IHostBrowser2
{
// Use IBCS.TabOut() instead. The implementation of TabOut is not fully factored out yet.
void TabOut_DoNotUse(bool forward);
object HostScriptObject { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
string PluginName { get; }
string PluginVersion { get; }
};
}
......@@ -51,113 +51,6 @@ enum HostingFlags
hfInDebugMode = 0x20
};
// <summary>
// This interface is used to host Windows Client Applications in the browser
// The unmanaged docobj server communicates with the application through this
// interface using COM interop.
// </summary>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("a0aa9153-65b4-3b57-9f2b-126f9c76c9f5")]
internal interface IBrowserHostServices
{
// <summary> This method inits and runs the server </summary>
// <returns>Int indicating whether the exit code of the application, failure could also
// mean that the app was not launched successfully</returns>
[PreserveSig]
[return: MarshalAs(UnmanagedType.I4)]
int Run([In, MarshalAs(UnmanagedType.LPWStr)] string strUrl,
[In, MarshalAs(UnmanagedType.LPWStr)] string strFragment,
MimeType mime,
[In, MarshalAs(UnmanagedType.LPWStr)] string strDebugSecurityZoneURL,
[In, MarshalAs(UnmanagedType.LPWStr)] string strApplicationId,
[In, MarshalAs(UnmanagedType.Interface)] object storageIUnknown,
[In, MarshalAs(UnmanagedType.Interface)] object loadByteArray,
HostingFlags hostingFlags,
INativeProgressPage nativeProgressPage,
[In, MarshalAs(UnmanagedType.BStr)] string bstrProgressAssemblyName,
[In, MarshalAs(UnmanagedType.BStr)] string bstrProgressClassName,
[In, MarshalAs(UnmanagedType.BStr)] string bstrErrorAssemblyName,
[In, MarshalAs(UnmanagedType.BStr)] string bstrErrorClassName,
IHostBrowser hostBrowser
);
// <summary> Reparent the viewport </summary>
void SetParent(IntPtr parentHandle);
// <summary> Show the viewport </summary>
void Show([MarshalAs(UnmanagedType.Bool)]bool showView);
// <summary> Move the viewport </summary>
void Move(int x, int y, int width, int height);
/// <summary>
/// Used by C# hosting code to get back to the native browser hosting code.
/// (The interface type is IBrowserCallbackServices.)
/// </summary>
void SetBrowserCallback([In, MarshalAs(UnmanagedType.Interface)]object browserCallback);
// <summary>If the Application is loaded we use LoadHistory else create a new app object </summary>
// <returns></returns>
[PreserveSig]
[return: MarshalAs(UnmanagedType.Bool)]
bool IsAppLoaded();
// <summary>Returns the Environment.ExitCode set by the application object when it Shutdown</summary>
// <returns></returns>
[PreserveSig]
int GetApplicationExitCode();
// <summary>Returns whether a journalEntry at that index is invokable. If the entry is a frame
// and we are not in the context of its host page, we return failure</summary>
// <returns></returns>
[PreserveSig]
[return: MarshalAs(UnmanagedType.Bool)]
bool CanInvokeJournalEntry([In, MarshalAs(UnmanagedType.I4)] int entryId);
//<summary> IPersistHistory::SaveHistory implementation called
//when hosted in the browser </summary>
void SaveHistory([MarshalAs(UnmanagedType.Interface)]object ucomIStream,
[MarshalAs(UnmanagedType.Bool)]bool persistEntireJournal,
[Out, MarshalAs(UnmanagedType.I4)] out int entryIndex,
[Out, MarshalAs(UnmanagedType.LPWStr)]out string url,
[Out, MarshalAs(UnmanagedType.LPWStr)]out string title);
//<summary> IPersistHistory::LoadHistory implementation called
//when hosted in the browser </summary>
void LoadHistory([MarshalAs(UnmanagedType.Interface)]object ucomIStream);
//<summary>
// IOleCommandTarget::QueryStatus called when hosted in the browser
//</summary>
[PreserveSig]
int QueryStatus([MarshalAs(UnmanagedType.LPStruct)]Guid guidCmdGroup, [In] uint command, [Out] out uint flags);
//<summary>
// IOleCommandTarget::Exec called when hosted in the browser
//</summary>
[PreserveSig]
int ExecCommand([MarshalAs(UnmanagedType.LPStruct)]Guid guidCmdGroup, uint command, object arg);
/// <summary> Shuts down the application. </summary>
/// <remarks>
/// The "post" in the method name is legacy. Now all of Application's shutdown work is complete
/// when this method returns. In particular, the managed Dispatcher is shut down.
/// </remarks>
void PostShutdown();
// <summary> Activate or deactivate RootBrowswerWindow </summary>
void Activate([MarshalAs(UnmanagedType.Bool)]bool fActivated);
void TabInto(bool forward);
/// <summary>
/// Returns true is the focused element wants the backspace key
/// </summary>
[PreserveSig]
[return: MarshalAs(UnmanagedType.Bool)]
bool FocusedElementWantsBackspace();
}
//********************************************************************************************//
// IMPORTANT: IMPORTANT: IMPORTANT: IMPORTANT: //
......
......@@ -207,7 +207,7 @@ protected override PackagePart GetPartCore(Uri uri)
// old version dll when a newer one is loaded. So whenever the AssemblyLoad event is fired, we will need to update the cache
// with the newly loaded assembly. This is currently only for designer so not needed for browser hosted apps.
// Attach the event handler before the first time we get the ResourceManagerWrapper.
if ((!assemblyLoadhandlerAttached) && (!BrowserInteropHelper.IsBrowserHosted))
if (!assemblyLoadhandlerAttached)
{
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(OnAssemblyLoadEventHandler);
assemblyLoadhandlerAttached = true;
......
......@@ -30,11 +30,6 @@ public void GetWindow( /* [out] */ ref IntPtr phwnd)
if (Application.Current != null)
{
Window curWindow = Application.Current.MainWindow;
#if NETFX
Invariant.Assert( Application.Current.BrowserCallbackServices == null || ( curWindow is RootBrowserWindow ));
#endif
if (curWindow != null)
{
phwnd = curWindow.CriticalHandle;
......
......@@ -96,20 +96,6 @@ internal enum AttributesToIgnore
#region Internal Constructors
/// <summary>
/// The class constructor initializes trace and event logging.
/// </summary>
static XamlFilter()
{
#if TRACE
#if NETFX
EventLog xamlFilterEventLog = new EventLog();
xamlFilterEventLog.Log = "Application";
xamlFilterEventLog.Source = "XAML filter";
Trace.Listeners.Add(new EventLogTraceListener(xamlFilterEventLog));
#endif
#endif
}
/// <summary>
/// Constructor. Does initialization.
......
......@@ -11,9 +11,6 @@
using System;
using System.IO;
#if NETFX
using System.Runtime.Remoting;
#endif
using System.Security; // SecurityCritical attribute
using System.Security.Permissions;
using MS.Internal.AppModel;
......@@ -219,20 +216,6 @@ public override void Close()
}
}
#if NETFX
/// <summary>
/// Overridden CreateObjRef method
/// </summary>
/// <param name="requestedType"></param>
/// <returns></returns>
public override ObjRef CreateObjRef(
Type requestedType
)
{
return _stream.CreateObjRef(requestedType);
}
#endif
/// <summary>
/// Overridden EndRead method
/// </summary>
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime;
using System.Security;
using System.Security.Permissions;
namespace MS.Internal.Utility
{
#region SponsorHelper Class
/// <summary>
/// We either mark the Sponsor as MarshalByRef or make it serializable.
/// If we make it MarshalByRef, then this sponsor which is used to control
/// the lifetime of a MBR object in turn needs to have another sponsor OR
/// the sponsor can mark itself to remain alive for the life of the AppDomain
/// by overriding InitializeLifetimeService and returning null OR the object
/// can be marked as Serializeable instead of MBR in which case it is marshaled
/// by value to the client appdomain and will not have the state of the host
/// appdomain to make renewal decisions. In our case we don't have any state so
/// its easier and better perf-wise to mark it Serializable.
/// </summary>
[Serializable]
internal class SponsorHelper : ISponsor
{
#region Private Data
private ILease _lease;
private TimeSpan _timespan;
#endregion Private Data
#region Constructor
internal SponsorHelper(ILease lease, TimeSpan timespan)
{
Debug.Assert(lease != null && timespan != null, "Lease and TimeSpan arguments cannot be null");
_lease = lease;
_timespan = timespan;
}
#endregion Constructor
#region ISponsor Interface
TimeSpan ISponsor.Renewal(ILease lease)
{
if (lease == null)
{
throw new ArgumentNullException("lease");
}
return _timespan;
}
#endregion ISponsor Interface
#region Internal Methods
internal void Register()
{
_lease.Register((ISponsor)this);
}
internal void Unregister()
{
_lease.Unregister((ISponsor)this);
}
#endregion Internal Methods
}
#endregion SponsorHelper Class
}
......@@ -118,7 +118,6 @@
<Compile Include="MS\Internal\AppModel\ComGuids.cs" />
<Compile Include="MS\Internal\AppModel\ContentFilePart.cs" />
<!-- <Compile Include="MS\Internal\AppModel\DeploymentExceptionMapper.cs" /> -->
<Compile Include="MS\Internal\AppModel\IBrowserCallbackServices.cs" />
<Compile Include="MS\Internal\AppModel\IBrowserHostServices.cs" />
<Compile Include="MS\Internal\AppModel\IconHelper.cs" />
<Compile Include="MS\Internal\AppModel\IContentContainer.cs" />
......@@ -1136,7 +1135,6 @@
<Compile Include="System\Windows\Input\KeyboardNavigation.cs" />
<Compile Include="System\Windows\Interop\ActiveXHost.cs" />
<Compile Include="System\Windows\Interop\BrowserInteropHelper.cs" />
<Compile Include="System\Windows\Interop\DocobjHost.cs" />
<Compile Include="System\Windows\Interop\DynamicScriptObject.cs" />
<Compile Include="System\Windows\Interop\HwndHost.cs" />
<Compile Include="System\Windows\Interop\IErrorPage.cs" />
......
......@@ -29,10 +29,6 @@
using System.Globalization;
using System.IO;
using System.Reflection;
#if NETFX
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime;
#endif
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
......@@ -101,10 +97,6 @@ public class Application : DispatcherObject, IHaveResources, IQueryAmbient
static Application()
{
ApplicationInit();
#if NETFX
NetFxVersionTraceLogger.LogVersionDetails();
#endif
}
/// <summary>
......@@ -140,12 +132,6 @@ public Application()
}
}
// Post a work item to start the Dispatcher (if we are browser hosted) so that the Dispatcher
// will be running before OnStartup is fired. We can't check to see if we are browser-hosted
// in the app ctor because BrowerInteropHelper.IsBrowserHosted hasn't been set yet.
Dispatcher.BeginInvoke(
DispatcherPriority.Send,
new DispatcherOperationCallback(StartDispatcherInBrowser), null);
//
// (Application not shutting down when calling
......@@ -232,35 +218,9 @@ public int Run()
public int Run(Window window)
{
VerifyAccess();
//
// Browser hosted app should not explictly call App.Run(). We need to filter out those
// calls here
//
if (InBrowserHostedApp())
{
throw new InvalidOperationException(SR.Get(SRID.CannotCallRunFromBrowserHostedApp));
}
else
{
return RunInternal(window);
}
return RunInternal(window);
}
/// <summary>
/// This will return true IFF this is a browser hosted, and this is the user's deployed
/// application, not our deployment application. We can't use BrowserCallbackServices for
/// this test, because it may not be hooked up yet. BrowserInteropHelper.IsBrowserHosted
/// is set before any of the code in the new AppDomain will be run yet.
/// </summary>
internal static bool InBrowserHostedApp()
{
#if NETFX
return BrowserInteropHelper.IsBrowserHosted && !(Application.Current is XappLauncherApp);
#else
return false;
#endif
}
/// <summary>
///
......@@ -877,21 +837,6 @@ public Window MainWindow
{
VerifyAccess();
#if NETFX
//
// Throw if an attempt is made to change RBW.
// or we are browser hosted, main window is null, and attempt is made to change RBW.
//
if ( ( _mainWindow is RootBrowserWindow )
||
((BrowserCallbackServices != null ) &&
( _mainWindow == null ) &&
( !( value is RootBrowserWindow ))) )
{
throw new InvalidOperationException( SR.Get( SRID.CannotChangeMainWindowInBrowser ) ) ;
}
#endif
if (value != _mainWindow)
{
_mainWindow = value;
......@@ -1532,7 +1477,6 @@ protected virtual void OnFragmentNavigation(FragmentNavigationEventArgs e)
switch (state)
{
case NavigationStateChange.Navigating:
ChangeBrowserDownloadState(true);
if (playNavigatingSound)
{
PlaySound(SOUND_NAVIGATING);
......@@ -1540,29 +1484,13 @@ protected virtual void OnFragmentNavigation(FragmentNavigationEventArgs e)
break;
case NavigationStateChange.Completed:
PlaySound(SOUND_COMPLETE_NAVIGATION);
ChangeBrowserDownloadState(false);
UpdateBrowserCommands();
break;
case NavigationStateChange.Stopped:
ChangeBrowserDownloadState(false);
break;
}
}
}
internal void UpdateBrowserCommands()
{
EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordHosting | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Verbose, EventTrace.Event.WpfHost_UpdateBrowserCommandsStart);
IBrowserCallbackServices ibcs = (IBrowserCallbackServices)this.GetService(typeof(IBrowserCallbackServices));
if (ibcs != null)
{
// ask the browser to re-query us for toolbar button state
ibcs.UpdateCommands();
}
EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordHosting | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Verbose, EventTrace.Event.WpfHost_UpdateBrowserCommandsEnd);
}
/// <summary>
/// Application Startup.
......@@ -1766,10 +1694,7 @@ internal int RunInternal(Window window)
//Shutdown DispatcherOperationCallback
// Invoke the Dispatcher synchronously if we are not in the browser
if (!BrowserInteropHelper.IsBrowserHosted)
{
RunDispatcher(null);
}
RunDispatcher(null);
return _exitCode;
}
......@@ -1788,29 +1713,12 @@ internal void InvalidateResourceReferences(ResourcesChangeInfo info)
// is created before the application.Run is called.
internal NavigationWindow GetAppWindow()
{
NavigationWindow appWin = null;
IBrowserCallbackServices ibcs = (IBrowserCallbackServices)this.GetService(typeof(IBrowserCallbackServices));
NavigationWindow appWin = new NavigationWindow();
// standalone case
if (ibcs == null)
{
appWin = new NavigationWindow();
// We don't want to show the window before the content is ready, but for compatibility reasons
// we do want it to have an HWND available. Not doing this can cause Application's MainWindow
// to be null when LoadCompleted has happened.
new WindowInteropHelper(appWin).EnsureHandle();
}
#if NETFX
else // browser hosted case
{
IHostService ihs = (IHostService)this.GetService(typeof(IHostService));
Debug.Assert(ihs != null, "IHostService in RootBrowserWindow cannot be null");
appWin = ihs.RootBrowserWindowProxy.RootBrowserWindow;
Debug.Assert(appWin != null, "appWin must be non-null");
Debug.Assert(appWin is RootBrowserWindow, "appWin must be a RootBrowserWindow");
}
#endif
// We don't want to show the window before the content is ready, but for compatibility reasons
// we do want it to have an HWND available. Not doing this can cause Application's MainWindow
// to be null when LoadCompleted has happened.
new WindowInteropHelper(appWin).EnsureHandle();
return appWin;
}
......@@ -1955,52 +1863,9 @@ private get
{
VerifyAccess();
_serviceProvider = value ;
#if NETFX
if (value != null)
{
_browserCallbackServices = (IBrowserCallbackServices)(_serviceProvider.GetService(typeof(IBrowserCallbackServices)));
ILease lease = RemotingServices.GetLifetimeService(_browserCallbackServices as MarshalByRefObject) as ILease;
if (lease != null)
{
//Per the remoting infrastructure, any remote object will get released in 5 mins unless the lease
//is extended with the lease manager by a sponsor
_browserCallbackSponsor = new SponsorHelper(lease, new TimeSpan(0, 5, 0));
_browserCallbackSponsor.Register();
}
}
else
{
CleanUpBrowserCallBackServices();
}
#endif
}
}
#if NETFX
private void CleanUpBrowserCallBackServices()
{
if (_browserCallbackServices != null)
{
if (_browserCallbackSponsor != null)
{
_browserCallbackSponsor.Unregister();
_browserCallbackSponsor = null;
}
_browserCallbackServices = null;
// Marshal.ReleaseComObject(IBHS) is called from ApplicationProxyInternal.
}
}
internal IBrowserCallbackServices BrowserCallbackServices
{
get
{
VerifyAccess();
return _browserCallbackServices;
}
}
#endif
// is called by NavigationService to detect TopLevel container
// We check there to call this only if NavigationService is on
......@@ -2032,17 +1897,6 @@ internal static bool IsShuttingDown
return _isShuttingDown;
}
#if NETFX
if (BrowserInteropHelper.IsBrowserHosted)
{
Application app = Application.Current;
if ((app != null) && (app.CheckAccess()))
{
IBrowserCallbackServices bcs = app.BrowserCallbackServices;
return ((bcs != null) && bcs.IsShuttingDown());
}
}
#endif
return false;
}
set
......@@ -2202,14 +2056,7 @@ private static Package GetResourcePackage(Uri packageUri)
/// </summary>
private void EnsureHwndSource()
{
// We don't support Activate, Deactivate, and SessionEnding
// events for browser hosted scenarios thus don't create
// this HwndSource if BrowserCallbackServices is valid
#if NETFX
if (BrowserCallbackServices == null && _parkingHwnd == null)
#else
if (_parkingHwnd == null)
#endif
{
// _appFilterHook needs to be member variable otherwise
// it is GC'ed and we don't get messages from HwndWrapper
......@@ -2432,15 +2279,6 @@ private void ConfigAppWindowAndRootElement(object root, Uri uri)
}
}
private void ChangeBrowserDownloadState(bool newState)
{
IBrowserCallbackServices ibcs = (IBrowserCallbackServices)this.GetService(typeof(IBrowserCallbackServices));
if (ibcs != null)
{
// start or stop waving the flag
ibcs.ChangeDownloadState(newState);
}
}
/// <summary>
/// Plays a system sound using the PlaySound api. This is a managed equivalent of the
......@@ -2570,31 +2408,6 @@ private static bool IsComponentBeingLoadedFromOuterLoadBaml(Uri curComponentUri)
return isRootElement;
}
[DebuggerNonUserCode] // to treat this method as non-user code even when symbols are available
private object StartDispatcherInBrowser(object unused)
{
if (BrowserInteropHelper.IsBrowserHosted)
{
BrowserInteropHelper.InitializeHostFilterInput();
// This seemingly meaningless try-catch-throw is a workaround for a CLR deficiency/bug in
// exception handling. When an unhandled exception on the main thread crosses
// the AppDomain boundary, the p/invoke layer catches it and throws another exception. Thus,
// the original exception is lost before the debugger is notified. The result is no managed
// callstack whatsoever. The workaround is based on a debugger/CLR feature that notifies of
// exceptions unhandled in 'user code'. This works only when the Just My Code feature is enabled
// in VS.
try
{
RunDispatcher(null);
}
catch
{
throw;
}
}
return null;
}
private object RunDispatcher(object ignore)
{
......@@ -2641,10 +2454,6 @@ private object RunDispatcher(object ignore)
private SecurityCriticalDataForSet<MimeType> _appMimeType;
private IServiceProvider _serviceProvider;
#if NETFX
private IBrowserCallbackServices _browserCallbackServices;
private SponsorHelper _browserCallbackSponsor;
#endif
private bool _appIsShutdown;
private int _exitCode;
......
......@@ -2950,11 +2950,7 @@ internal bool IsChildPopup
{
if (!_isChildPopupInitialized)
{
// Force popup to be a child window if it we don't have unmanaged code permission (needed by bitmap effect)
// This is a tighter restriction than just UIWindowPermission
_isChildPopup = BrowserInteropHelper.IsBrowserHosted ||
!SecurityHelper.CheckUnmanagedCodePermission();
_isChildPopup = false;
_isChildPopupInitialized = true;
}
return (_isChildPopup);
......
......@@ -83,14 +83,6 @@ internal TextBoxBase() : base()
// b) create TextContainer and call InitializeTextContainer
// c) configure TextEditor by setting appropriate properties
CoerceValue(HorizontalScrollBarVisibilityProperty);
// Security team really wants to set AllowDrop property value as "False"
// not to generate the security exception that can be happened in the
// partial trust environment.
if (!SecurityHelper.CallerHasPermissionWithAppDomainOptimization(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)))
{
AllowDrop = false;
}
}
#endregion Constructors
......
......@@ -81,49 +81,8 @@ public sealed class WebBrowser : ActiveXHost
static WebBrowser()
{
#if NETFX
if (IsWebOCPermissionRestricted)
{
// Breaking change for v4, intended to be backported to v3.x: We block PT hosting of the WebOC:
// - In non-IE browser (intended for Firefox presently) for Internet-zone XBAPs, in order
// not to expose IE's attack surface;
// - In PT standalone ClickOnce application. WPF does not support this in general, but a WebBrowser
// can be instantiated and navigated, and script in it will run, which could be harmful.
if (BrowserInteropHelper.IsBrowserHosted)
{
if ((BrowserInteropHelper.HostingFlags & HostingFlags.hfHostedInIEorWebOC) == 0)
{
// Explicitly trust only these zones...
int sourceZone = AppSecurityManager.MapUrlToZone(BrowserInteropHelper.Source);
if (sourceZone != NativeMethods.URLZONE_INTRANET && sourceZone != NativeMethods.URLZONE_TRUSTED &&
sourceZone != NativeMethods.URLZONE_LOCAL_MACHINE)
{
// Enable explicit opt-out of this blocking.
if (RegistryKeys.ReadLocalMachineBool(RegistryKeys.WPF_Hosting, RegistryKeys.value_UnblockWebBrowserControl) != true)
{
//[Using a resource string for another issue that's close enough in meaning.]
throw new SecurityException(SR.Get(SRID.AffectedByMsCtfIssue, "http://go.microsoft.com/fwlink/?LinkID=168882"));
}
}
}
}
else
{
// ClickOnce uses AppLaunch.exe to host partial-trust applications.
string hostProcessName = Path.GetFileName(UnsafeNativeMethods.GetModuleFileName(new HandleRef()));
if (string.Compare(hostProcessName, "AppLaunch.exe", StringComparison.OrdinalIgnoreCase) == 0)
{
// No explanation message is warranted in this case since it's not supported anyway.
SecurityHelperPF.DemandWebBrowserPermission();
}
}
RegisterWithRBW();
}
#endif
TurnOnFeatureControlKeys();
ControlsTraceLogger.AddControl(TelemetryControls.WebBrowser);
}
......@@ -142,17 +101,7 @@ public WebBrowser()
(new WebBrowserPermission(WebBrowserPermissionLevel.Safe)).Demand();
}
#if NETFX
// If the webbrowser permission is restricted, we don't allow webbrowser to be inside Popup.
if (IsWebOCPermissionRestricted)
{
Loaded += new RoutedEventHandler(LoadedHandler);
}
_hostingAdaptor = IsWebOCHostedInBrowserProcess ?
new WebOCHostedInBrowserAdaptor(this) : new WebOCHostingAdaptor(this);
#else
_hostingAdaptor = new WebOCHostingAdaptor(this);
#endif
}
#endregion Constructor
......@@ -527,11 +476,8 @@ public object ObjectForScripting
if (value != null)
{
Type t = value.GetType();
#if NETFX
if (!System.Runtime.InteropServices.Marshal.IsTypeVisibleFromCom(t))
#else
if (!System.Runtime.InteropServices.MarshalLocal.IsTypeVisibleFromCom(t))
#endif
{
throw new ArgumentException(SR.Get(SRID.NeedToBeComVisible));
}
......@@ -823,27 +769,6 @@ internal Guid LastNavigation
}
}
internal static bool IsWebOCHostedInBrowserProcess
{
get
{
#if NETFX
if(!IsWebOCPermissionRestricted)
return false;
HostingFlags hf = BrowserInteropHelper.HostingFlags;
return (hf & HostingFlags.hfHostedInIE) != 0
|| // Backup condition in case the low-integrity IE process is compromised.
// The hfHostedInIE flag cannot be trusted, because it's derived by talking to code
// in the IE process. (Theretically, one could pretend to be our Mozilla plugin by
// creating a similar hosting envrionment within IE! Then no IWebBrowser...)
// But hfIsBrowserLowIntegrityProcess is reliable because it's determined externally.
(hf & HostingFlags.hfIsBrowserLowIntegrityProcess) != 0;
#else
return false;
#endif
}
}
#endregion Internal Properties
//----------------------------------------------
......@@ -884,17 +809,6 @@ private void LoadedHandler(object sender, RoutedEventArgs args)
}
}
private static void RegisterWithRBW()
{
#if NETFX
// if we are browser hosted, rbw should have been created here.
// what if RootBrowserWindow is null.
if (RootBrowserWindow != null)
{
RootBrowserWindow.AddLayoutUpdatedHandler();
}
#endif
}
// Turn on all the WebOC Feature Control Keys implementing various security mitigations.
// Whenever possible, we do it programmatically instead of adding reg-keys so that these are on on all WPF apps.
......@@ -980,19 +894,6 @@ private static void TurnOnFeatureControlKeys()
UnsafeNativeMethods.CoInternetSetFeatureEnabled( NativeMethods.FEATURE_DISABLE_LEGACY_COMPRESSION, NativeMethods.SET_FEATURE_ON_PROCESS, true ) ;
UnsafeNativeMethods.CoInternetSetFeatureEnabled( NativeMethods.FEATURE_DISABLE_TELNET_PROTOCOL, NativeMethods.SET_FEATURE_ON_PROCESS, true ) ;
#if NETFX
// For use of the WebOC in stand-alone applications and full-trust XBAPs, we don't want to
// impact existing behavior causing potential different layout due to the appearance of
// address bar and status bar. We therefore only apply the following flag where the spoofing
// threat is the most relevant, when restricted permissions apply.
if (IsWebOCPermissionRestricted)
{
UnsafeNativeMethods.CoInternetSetFeatureEnabled( NativeMethods.FEATURE_FORCE_ADDR_AND_STATUS, NativeMethods.SET_FEATURE_ON_PROCESS, true ) ;
}
#endif
// The relevant IE 8 FCKs are applied only in the registry because they don't work through the API.
// We are trying to change this unfortunate trend. .
}
private void DoNavigate(Uri source, ref object targetFrameName, ref object postData, ref object headers, bool ignoreEscaping = false)
......@@ -1156,33 +1057,6 @@ protected override bool TabIntoCore(TraversalRequest request)
#endregion Private Methods
//----------------------------------------------
//
// Private Properties
//
//----------------------------------------------
#region Private Properties
#if NETFX
private static RootBrowserWindow RootBrowserWindow
{
get
{
if (_rbw.Value == null)
{
if (Application.Current != null)
{
_rbw.Value = Application.Current.MainWindow as RootBrowserWindow;
}
}
return _rbw.Value;
}
}
#endif
#endregion Private Properties
//----------------------------------------------
//
......@@ -1192,10 +1066,6 @@ private static RootBrowserWindow RootBrowserWindow
#region Private Fields
#if NETFX
private static readonly bool IsWebOCPermissionRestricted =
!SecurityHelperPF.CallerAndAppDomainHaveUnrestrictedWebBrowserPermission();
#endif
// Reference to the native ActiveX control's IWebBrowser2
// Do not reference this directly. Use the AxIWebBrowser2 property instead since that
......@@ -1206,11 +1076,6 @@ private static RootBrowserWindow RootBrowserWindow
// To hook up events from the native WebBrowser
private ConnectionPointCookie _cookie;
#if NETFX
private static SecurityCriticalDataForSet<RootBrowserWindow> _rbw;
#endif
private object _objectForScripting;
private Stream _documentStream;
......@@ -1240,6 +1105,9 @@ private static RootBrowserWindow RootBrowserWindow
/// the WebOC either in-process or in the browser process (when IsWebOCHostedInBrowserProcess==true).
/// This base class handles the in-process hosting.
/// </summary>
/// <remarks>
/// IsWebOCHostedInBrowserProcess property no longer exists since .NET Core 3.0
/// </remarks>
internal class WebOCHostingAdaptor
{
internal WebOCHostingAdaptor(WebBrowser webBrowser)
......@@ -1274,63 +1142,6 @@ internal virtual object CreateEventSink()
protected WebBrowser _webBrowser;
};
#if NETFX
/// <summary>
/// Used when WebBrowser.IsWebOCHostedInBrowserProcess.
/// </summary>
private class WebOCHostedInBrowserAdaptor : WebOCHostingAdaptor
{
internal WebOCHostedInBrowserAdaptor(WebBrowser webBrowser) : base(webBrowser) { }
static WebOCHostedInBrowserAdaptor()
{
// IDocHostUIHandler is not marshalable ... probably because no one has needed to use it
// cross-thread. PresentationHostProxy.dll is compiled with a clone of it and contains
// proxy-stub code for it. Registering the proxy-stub this way rather than in the registry
// is cleaner because it applies only to our scenarios.
// The same thing is done in the browser process, by our in-proc handler.
Guid iidDHUIH = typeof(UnsafeNativeMethods.IDocHostUIHandler).GUID;
Guid clsidPresHostProxy = new Guid("e302cb55-5f9d-41a3-9ef3-61827fb8b46d");
int hr = UnsafeNativeMethods.CoRegisterPSClsid(ref iidDHUIH, ref clsidPresHostProxy);
if (hr != NativeMethods.S_OK)
{
Marshal.ThrowExceptionForHR(hr);
}
}
internal override object ObjectForScripting
{
get
{
return _threadBoundObjectForScripting;
}
set
{
_threadBoundObjectForScripting =
value == null ? null : ActiveXHelper.CreateIDispatchSTAForwarder(value);
}
}
internal override object CreateWebOC()
{
IntPtr pWebOC = Application.Current.BrowserCallbackServices.CreateWebBrowserControlInBrowserProcess();
object webOC = Marshal.GetTypedObjectForIUnknown(pWebOC, typeof(UnsafeNativeMethods.IWebBrowser2));
Marshal.Release(pWebOC);
return webOC;
}
internal override object CreateEventSink()
{
return ActiveXHelper.CreateIDispatchSTAForwarder(
(UnsafeNativeMethods.DWebBrowserEvents2)base.CreateEventSink());
}
// This is a native object that wraps the ObjectForScripting provided by the application
// in order to ensure calls arrive on WebBrowser's thread.
object _threadBoundObjectForScripting;
};
#endif
#endregion Private Class
}
}
......@@ -33,7 +33,6 @@ public static class BrowserInteropHelper
{
static BrowserInteropHelper()
{
SetBrowserHosted(false);
IsInitialViewerNavigation = true;
}
......@@ -51,48 +50,20 @@ public static object ClientSite
object oleClientSite = null;
#if NETFX
if (IsBrowserHosted)
{
Application.Current.BrowserCallbackServices.GetOleClientSite(out oleClientSite);
}
#endif
return oleClientSite;
}
}
public static dynamic HostScript
{
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;
}
}
}
/// <summary>
/// Gets a script object that provides access to the HTML window object,
/// custom script functions, and global variables for the HTML page, if the XAML browser application (XBAP)
/// is hosted in a frame.
/// </summary>
/// <remarks>
/// Starting .NET Core 3.0, XBAP's are not supported - <see cref="HostScript"/> will always return <code>null</code>
/// </remarks>
public static dynamic HostScript => null;
/// <summary>
/// Returns true if the app is a browser hosted app.
......@@ -101,21 +72,7 @@ public static dynamic HostScript
/// 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.
/// </remarks>
public static bool IsBrowserHosted
{
get
{
return _isBrowserHosted.Value;
}
}
/// <remarks>
/// HostingFlags is set after this property.
/// </remarks>
internal static void SetBrowserHosted(bool value)
{
_isBrowserHosted.Value = value;
}
public static bool IsBrowserHosted => false;
internal static HostingFlags HostingFlags
{
......@@ -147,19 +104,6 @@ internal static bool IsViewer
}
}
/// <summary>
/// Returns true if avalon it top level.
/// Also returns true if not browser-hosted.
/// </summary>
internal static bool IsAvalonTopLevel
{
get
{
if (!IsBrowserHosted)
return true;
return (HostingFlags & HostingFlags.hfHostedInFrame) == 0;
}
}
/// <summary>
/// Returns true if the host browser is IE or the WebOC hosted in a standalone application.
......@@ -190,23 +134,6 @@ internal static bool IsInitialViewerNavigation
}
}
internal static IHostBrowser HostBrowser;
internal static void ReleaseBrowserInterfaces()
{
if (HostBrowser != null)
{
Marshal.ReleaseComObject(HostBrowser);
HostBrowser = null;
}
if (_hostHtmlDocumentServiceProvider.Value != null)
{
Marshal.ReleaseComObject(_hostHtmlDocumentServiceProvider.Value);
_hostHtmlDocumentServiceProvider.Value = null;
}
}
/// <summary>
/// Retrieves the IServiceProvider object for the browser we're hosted in.
/// This is used for IDispatchEx operations in the script interop feature.
......@@ -327,7 +254,6 @@ private static void EnsureScriptInteropAllowed()
}
}
private static SecurityCriticalDataForSet<bool> _isBrowserHosted;
private static SecurityCriticalDataForSet<HostingFlags> _hostingFlags;
private static SecurityCriticalDataForSet<bool> _isInitialViewerNavigation;
private static SecurityCriticalDataForSet<bool?> _isScriptInteropDisabled;
......
......@@ -385,13 +385,8 @@ internal unsafe bool TryFindMemberAndInvokeNonWrapped(string memberName, int fla
// by the CLR. Therefore we also check for the IsCOMObject property. It also seems
// COM interop special-cases DateTime as it's not revealed to be visible by any
// of the first two checks below.
if (
#if NETFX
!Marshal.IsTypeVisibleFromCom(argType)
#else
!MarshalLocal.IsTypeVisibleFromCom(argType)
#endif
&& !argType.IsCOMObject && argType != typeof(DateTime))
if (!MarshalLocal.IsTypeVisibleFromCom(argType) &&
!argType.IsCOMObject && argType != typeof(DateTime))
{
throw new ArgumentException(SR.Get(SRID.NeedToBeComVisible));
}
......
......@@ -205,28 +205,7 @@ private void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
}
else
{
#if NETFX
if (Application.InBrowserHostedApp())
{
LaunchResult launched = LaunchResult.NotLaunched;
if (SecurityHelper.AreStringTypesEqual(bpu.Scheme, BaseUriHelper.PackAppBaseUri.Scheme))
{
bpu = BaseUriHelper.ConvertPackUriToAbsoluteExternallyVisibleUri(bpu);
}
launched = AppSecurityManager.SafeLaunchBrowserOnlyIfPossible(CurrentSource, bpu, target, true /*IsTopLevelContainer*/);
if (launched == LaunchResult.NotLaunched)
{
throw new System.Exception(SR.Get(SRID.FailToNavigateUsingHyperlinkTarget));
}
}
else
#endif
{
throw new System.ArgumentException(SR.Get(SRID.HyperLinkTargetNotFound));
}
throw new System.ArgumentException(SR.Get(SRID.HyperLinkTargetNotFound));
}
}
......@@ -451,35 +430,6 @@ private JournalNavigationScope EnsureJournal()
return _journalScope;
}
private bool IsParentedByBrowserWindow()
{
// We want to update browser related state only if
//
// 1. There's no window associated with this NavigationService (meaning that this NavigationService)
// was created by Application) and if we're hosted in the Browser i.e BCBS is not null
//
// or
//
// 2. The window associated with this NavigationService is a RootBrowserWindow (meaning that we're
// hosted in the browser and RBW is navigated
// and
// we are not in a Frame with its own Journal.
//
#if NETFX
if (this.Application != null &&
this.Application.CheckAccess())
{
if ((JournalScope != null && JournalScope.NavigatorHost is RootBrowserWindow) ||
(JournalScope == null &&
this.Application.BrowserCallbackServices != null))
{
return true;
}
}
#endif
return false;
}
bool IsConsistent(NavigateInfo navInfo)
{
return navInfo == null
......@@ -523,58 +473,6 @@ private bool RestoreRootViewerState(CustomJournalStateInternal rvs)
return true;
}
#if NETFX
/// <summary>
/// When it is top level navigation away from loose XAML (not the intial navigation to the loose xaml,
/// nor a refresh), we want to delegate to the browser right away. There is no need to go through our
/// navigation process, because no matter what content type (xaml, html...) it is trying to navigate to,
/// we always let the browser handle it when it is top-level navigation from inside XamlViewer.
///
/// V3 SP1 Optimization:
/// We can avoid the cost of recycling the host process when:
/// 1) The new content is from the same site-of-origin. This way there is no danger of cross-domain
/// attacks made possible by poor cleanup. See SecurityNote below.
/// 2) We can update the address bar with the new URL, or there is no address bar, which is when
/// XamlViewer is hosted in an HTML frame.
/// </summary>
/// <remarks>
/// This function may return false and we still end up delegating to the browser. This will be the
/// case when the top-level navigation is to something other than XAML. GetObjectFromResponse()
/// handles this case.
/// </remarks>
private bool ShouldDelegateXamlViewerNavigationToBrowser(NavigateInfo navigateInfo, Uri resolvedUri)
{
bool shouldDelegate = false;
if (BrowserInteropHelper.IsViewer)
{
Invariant.Assert(resolvedUri != null && resolvedUri.IsAbsoluteUri);
shouldDelegate = !BrowserInteropHelper.IsInitialViewerNavigation &&
(navigateInfo == null || navigateInfo.NavigationMode != NavigationMode.Refresh) &&
IsTopLevelContainer &&
// except when we can update the address bar or we are in a frame:
!(!BrowserInteropHelper.IsAvalonTopLevel || HasTravelLogIntegration);
}
return shouldDelegate;
}
void UpdateAddressBarForLooseXaml()
{
if (BrowserInteropHelper.IsViewer && !BrowserInteropHelper.IsInitialViewerNavigation &&
IsTopLevelContainer)
{
Uri source = _currentSource;
if (PackUriHelper.IsPackUri(source))
{
source = BaseUriHelper.ConvertPackUriToAbsoluteExternallyVisibleUri(source);
}
Invariant.Assert(_navigatorHost != null && _navigatorHost == Application.MainWindow &&
source.IsAbsoluteUri && !PackUriHelper.IsPackUri(source));
SecurityHelper.DemandWebPermission(source);
this.Application.BrowserCallbackServices.UpdateAddressBar(source.ToString());
}
}
#endif
#endregion Private Methods
......@@ -1132,22 +1030,6 @@ private bool OnBeforeSwitchContent(Object newBP, NavigateInfo navInfo, Uri newUr
Debug.Assert(_navigateQueueItem == null);
#if NETFX
// Workaround for the reentrance problem from browser (bug 128689).
// Call into browser before we update journal. If there is another navigation waiting, e.g,
// user starts a new navigation using the browser back/forward button, it will
// re-enter with this call. We can detect whether a new navigation has started by checking
// _navigateQueueItem. The goal is to check for reentrance before we update journal. It should
// be safe to cancel the current navigation at this point (before any journal changes).
if (HasTravelLogIntegration)
{
DispatchPendingCallFromBrowser();
if (_navigateQueueItem != null)
{
return false;
}
}
#endif
if (navInfo == null)
{
......@@ -1158,8 +1040,6 @@ private bool OnBeforeSwitchContent(Object newBP, NavigateInfo navInfo, Uri newUr
UpdateJournal(navInfo.NavigationMode, JournalReason.NewContentNavigation, navInfo.JournalEntry);
}
// Check for reentrance again before we proceed. UpdateJournal calls CallUpdateTravelLog which calls
// into browser that can cause a new navigation to reenter.
// Future:
// The journal entry of the new page that is navigated to might be lost because the navigation is
// cancelled after the current page being added to jounral. E.g, The journal looks like:
......@@ -1199,14 +1079,6 @@ private bool OnBeforeSwitchContent(Object newBP, NavigateInfo navInfo, Uri newUr
return true;
}
#if NETFX
// Allow new navigations from browser to re-enter with this call.
private void DispatchPendingCallFromBrowser()
{
BrowserInteropHelper.HostBrowser.GetTop();
}
#endif
/// <summary>
/// Called when style is actually applied.
/// </summary>
......@@ -1748,24 +1620,8 @@ internal bool Navigate(Uri source, Object navigationState, bool sandboxExternalC
return true;
}
#if NETFX
if (ShouldDelegateXamlViewerNavigationToBrowser(navInfo, resolvedSource))
{
try
{
DelegateToBrowser(newRequest is PackWebRequest, resolvedSource);
}
finally
{
ResetPendingNavigationState(NavigationStatus.Idle);
}
}
else
#endif
{
// Post the navigate Dispatcher operation
_navigateQueueItem.PostNavigation();
}
// Post the navigate Dispatcher operation
_navigateQueueItem.PostNavigation();
return true;
}
......@@ -2408,9 +2264,6 @@ private void FireNavigated(object navState)
private void HandleNavigated(object navState, bool navigatedToNewContent)
{
Debug.Assert(_navStatus == NavigationStatus.Navigated);
#if NETFX
UpdateAddressBarForLooseXaml();
#endif
BrowserInteropHelper.IsInitialViewerNavigation = false;
NavigateInfo navInfo = navState as NavigateInfo;
......@@ -3090,13 +2943,6 @@ private void HandleWebResponse(IAsyncResult ar)
}
}
private bool CanUseTopLevelBrowserForHTMLRendering()
{
return (IsTopLevelContainer
&& IsParentedByBrowserWindow()
);
}
// Create Object from the return of WebResponse stream
private void GetObjectFromResponse(WebRequest request, WebResponse response, Uri destinationUri, Object navState)
{
......@@ -3134,14 +2980,12 @@ private void GetObjectFromResponse(WebRequest request, WebResponse response, Uri
_webResponse = response;
_asyncObjectConverter = null;
#if NETFX
Invariant.Assert(!ShouldDelegateXamlViewerNavigationToBrowser(navigateInfo, destinationUri),
"TopLevel navigation away from loose xaml is already delageted to browser. It should never reach here.");
#endif
// CanUseTopLevelBrowserForHTMLRendering() will be true for TopLevel navigation away from browser hosted app. If that is the case
// canUseTopLevelBrowserForHTMLRendering will be true for TopLevel navigation away from browser hosted app. If that is the case
// o will be null.
Object o = MimeObjectFactory.GetObjectAndCloseStream(bindStream, contentType, destinationUri, CanUseTopLevelBrowserForHTMLRendering(), sandBoxContent, true /*allowAsync*/, IsJournalNavigation(navigateInfo), out _asyncObjectConverter);
// We don't support browser hosting since .NET Core 3.0, so therefore canUseTopLevelBrowserForHTMLRendering = false
bool canUseTopLevelBrowserForHTMLRendering = false;
Object o = MimeObjectFactory.GetObjectAndCloseStream(bindStream, contentType, destinationUri, canUseTopLevelBrowserForHTMLRendering, sandBoxContent, true /*allowAsync*/, IsJournalNavigation(navigateInfo), out _asyncObjectConverter);
if (o != null)
{
......@@ -3366,10 +3210,6 @@ internal void DoNavigate(Object bp, NavigationMode navFlags, Object navState)
journalScope.Journal.UpdateCurrentEntry(journalEntry);
if (journalEntry.IsNavigable())
{
CallUpdateTravelLog(navigationMode == NavigationMode.New);
}
if (navigationMode == NavigationMode.New)
{
......@@ -3601,22 +3441,6 @@ internal void RequestCustomContentStateOnAppShutdown()
FireNavigating(null, null, null, null); // sets _customContentStateToSave
}
internal void CallUpdateTravelLog(bool addNewEntry)
{
#if NETFX
// Not explicitly checking IsSerializable here because we will be called back
// immediately via SaveHistory which will throw the serialization exception which
// will give us the same effect and without the overhead of an explicit
// GetType + type.IsSerializable check. But if the subclass has data members
// that are not serializable we will still throw an exception inspite of
// IsSerializable == true for the subclass.
if (HasTravelLogIntegration)
{
this.Application.BrowserCallbackServices.UpdateTravelLog(addNewEntry);
}
#endif
}
/// <summary>
/// Returns the current Application
......@@ -3703,18 +3527,6 @@ private FinishEventHandler FinishHandler
}
}
#if NETFX
private bool HasTravelLogIntegration
{
get
{
return IsParentedByBrowserWindow() &&
ApplicationProxyInternal.Current.RootBrowserWindow.HasTravelLogIntegration;
return false;
}
}
#endif
private bool IsTopLevelContainer
{
get
......
......@@ -59,51 +59,23 @@ internal bool PerformDefaultAction
private string[] GetCmdLineArgs()
{
string[] retValue = null;
string[] args = Environment.GetCommandLineArgs();
Invariant.Assert(args.Length >= 1);
if (!BrowserInteropHelper.IsBrowserHosted &&
( ( Application.Current.MimeType != MimeType.Application )
|| ! IsOnNetworkShareForDeployedApps() ))
{
string[] args = Environment.GetCommandLineArgs();
Invariant.Assert(args.Length >= 1);
int newLength = args.Length - 1;
newLength = (newLength >= 0 ? newLength : 0);
int newLength = args.Length - 1;
newLength = (newLength >=0 ? newLength : 0);
retValue = new string[newLength];
for (int i = 1; i < args.Length; i++)
{
retValue[i-1] = args[i];
}
}
else
string[] retValue = new string[newLength];
for (int i = 1; i < args.Length; i++)
{
retValue = new string[0];
retValue[i - 1] = args[i];
}
return retValue;
}
//
// Put this into a separate Method to avoid loading of this code at JIT time.
//
//
// Explicitly tell the compiler that we don't want to be inlined.
// This will prevent loading of system.deployment unless we are a click-once app.
//
[MethodImplAttribute (MethodImplOptions.NoInlining )]
private bool IsOnNetworkShareForDeployedApps()
{
#if NETFX
return System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed ;
#else
return false;
#endif
}
private String[] _args;
private bool _performDefaultAction;
}
......
......@@ -170,26 +170,6 @@ internal static WebBrowserPermission CachedWebBrowserPermission
}
static WebBrowserPermission _webBrowserPermission;
///<summary>
/// Check whether the call stack has the permissions needed for WebBrowser.
/// Optimization: false is returned if the AppDomain's permission grant does not include the
/// WebBrowserPermission. This preliminary check will defeat an Assert on the callstack, but it
/// avoids the SecurityException in PT when the full WB permission is not granted.
/// </summary>
internal static bool CallerAndAppDomainHaveUnrestrictedWebBrowserPermission()
{
if (!MS.Internal.SecurityHelper.AppDomainHasPermission(CachedWebBrowserPermission))
return false;
try
{
SecurityHelper.DemandWebBrowserPermission();
}
catch (SecurityException)
{
return false;
}
return true;
}
///<summary>
/// Check to see if we have User initiated navigation permission.
......@@ -288,49 +268,6 @@ internal static bool IsFullTrustCaller()
}
static PermissionSet _fullTrustPermissionSet = null;
///<summary>
/// Return true if the caller has the correct permission set to get a folder
/// path.
///</summary>
///<remarks>
/// This function exists solely as a an optimazation for the debugger scenario
///</remarks>
internal static bool CallerHasPermissionWithAppDomainOptimization(params IPermission[] permissionsToCheck)
{
#if NETFX
// in case of passing null return true
if (permissionsToCheck == null)
return true;
PermissionSet psToCheck = new PermissionSet(PermissionState.None);
for ( int i = 0 ; i < permissionsToCheck.Length ; i++ )
{
psToCheck.AddPermission(permissionsToCheck[i]);
}
PermissionSet permissionSetAppDomain = AppDomain.CurrentDomain.PermissionSet;
if (psToCheck.IsSubsetOf(permissionSetAppDomain))
{
return true;
}
return false;
#else
return true;
#endif
}
/// <summary> Enables an efficient check for a specific permisison in the AppDomain's permission grant
/// without having to catch a SecurityException in the case the permission is not granted.
/// <summary>
internal static bool AppDomainHasPermission(IPermission permissionToCheck)
{
#if NETFX
Invariant.Assert(permissionToCheck != null);
PermissionSet psToCheck = new PermissionSet(PermissionState.None);
psToCheck.AddPermission(permissionToCheck);
return psToCheck.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet);
#else
return true;
#endif
}
internal static Uri GetBaseDirectory(AppDomain domain)
{
......@@ -453,11 +390,7 @@ internal static void DemandFilePathDiscoveryWriteRead()
internal static PermissionSet ExtractAppDomainPermissionSetMinusSiteOfOrigin()
{
#if NETFX
PermissionSet permissionSetAppDomain = AppDomain.CurrentDomain.PermissionSet;
#else
PermissionSet permissionSetAppDomain = new PermissionSet(PermissionState.Unrestricted);
#endif
// Ensure we remove the FileIO read permission to site of origin.
// We choose to use unrestricted here because it does not matter
......@@ -853,23 +786,6 @@ internal static void DemandUnrestrictedUIPermission()
static UIPermission _unrestrictedUIPermission = null;
#endif
#if PRESENTATION_CORE
internal static bool AppDomainGrantedUnrestrictedUIPermission
{
get
{
if(!_appDomainGrantedUnrestrictedUIPermission.HasValue)
{
_appDomainGrantedUnrestrictedUIPermission = AppDomainHasPermission(new UIPermission(PermissionState.Unrestricted));
}
return _appDomainGrantedUnrestrictedUIPermission.Value;
}
}
private static bool? _appDomainGrantedUnrestrictedUIPermission;
#endif
#if PRESENTATION_CORE
internal static void DemandFileIOReadPermission(string fileName)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册