Skip to content

Commit

Permalink
Change IsolatedStorageFile path for mobile (#83380)
Browse files Browse the repository at this point in the history
 Updated isolated storage root path for mobile platforms
---------
Co-authored-by: Alexander Köplinger <alex.koeplinger@outlook.com>
  • Loading branch information
mkhamoyan authored May 11, 2023
1 parent 69ca02b commit 1ed1206
Show file tree
Hide file tree
Showing 18 changed files with 454 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<Compile Include="System\IO\IsolatedStorage\IsolatedStorage.cs" />
<Compile Include="System\IO\IsolatedStorage\IsolatedStorageScope.cs" />
<Compile Include="System\IO\IsolatedStorage\Helper.cs" />
<Compile Include="System\IO\IsolatedStorage\Helper.Win32Unix.cs" />
<Compile Include="System\IO\IsolatedStorage\INormalizeForIsolatedStorage.cs" />
<Compile Include="$(CommonPath)System\Security\IdentityHelper.cs"
Link="Common\System\Security\IdentityHelper.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,68 @@ namespace System.IO.IsolatedStorage
{
internal static partial class Helper
{
// we're using a different directory name for compatibility with legacy Xamarin
public const string IsolatedStorageDirectoryName = ".isolated-storage";

internal static string GetDataDirectory(IsolatedStorageScope scope)
{
// In legacy Xamarin for Roaming Scope we were using Environment.SpecialFolder.LocalApplicationData
// In .Net 7 for Roaming Scope we are using Environment.SpecialFolder.ApplicationData
// e.g. Android .Net 7 path = /data/user/0/{packageName}/files/.isolated-storage/{hash}/{hash}/AppFiles/
// e.g. Android Xamarin path = /data/user/0/{packageName}/files/.config/.isolated-storage/
// e.g. iOS .Net 7 path = /Users/userName/{packageName}/Documents/.isolated-storage/{hash}/{hash}/AppFiles/
// e.g. iOS Xamarin path = /Users/userName/{packageName}/Documents/.config/.isolated-storage/
//
// Since we shipped that behavior as part of .NET 7 we can't change this now or upgraded apps wouldn't find their files anymore.
// We need to look for an existing directory first before using the legacy Xamarin approach.

Environment.SpecialFolder specialFolder =
IsMachine(scope) ? Environment.SpecialFolder.CommonApplicationData : // e.g. /usr/share;
IsRoaming(scope) ? Environment.SpecialFolder.ApplicationData : // e.g. /data/user/0/{packageName}/files/.config;
Environment.SpecialFolder.LocalApplicationData; // e.g. /data/user/0/{packageName}/files;

string dataDirectory = Environment.GetFolderPath(specialFolder);
dataDirectory = Path.Combine(dataDirectory, IsolatedStorageDirectoryName);
if (Directory.Exists(dataDirectory))
{
return dataDirectory;
}
// Otherwise return legacy xamarin path
else
{
// In .Net 7 for Android SpecialFolder.LocalApplicationData returns "/data/user/0/{packageName}/files"
// while in Xamarin it was "/data/user/0/{packageName}/files/.local/share"
// For Android we need to hardcode Xamarin path for compatibility with legacy Xamarin
if (OperatingSystem.IsAndroid() && IsRoaming(scope))
{
dataDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + ".local/share";
Directory.CreateDirectory(dataDirectory);
}
else
{
specialFolder =
IsMachine(scope) ? Environment.SpecialFolder.CommonApplicationData :
IsRoaming(scope) ? Environment.SpecialFolder.LocalApplicationData :
Environment.SpecialFolder.ApplicationData;

dataDirectory = Environment.GetFolderPath(specialFolder, Environment.SpecialFolderOption.Create);
}

dataDirectory = Path.Combine(dataDirectory, IsolatedStorageDirectoryName);
}

return dataDirectory;
}

internal static string GetRandomDirectory(string rootDirectory, IsolatedStorageScope _)
{
// In legacy Xamarin we didn't have a random directory inside of the isolated storage root for each app,
// we tried to preserve that in https://github.com/dotnet/runtime/pull/75541 but the fix wasn't complete enough
// and we still created random directories when not using the Roaming scope.
//
// Since we shipped that behavior as part of .NET 7 we can't change this now or upgraded apps wouldn't find their files anymore.
// We need to look for an existing random directory first before using the plain root directory.
return GetExistingRandomDirectory(rootDirectory) ?? rootDirectory;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,68 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading;
using System.Security;

namespace System.IO.IsolatedStorage
{
internal static partial class Helper
{
public const string IsolatedStorageDirectoryName = "IsolatedStorage";

internal static string GetDataDirectory(IsolatedStorageScope scope)
{
// This is the relevant special folder for the given scope plus IsolatedStorageDirectoryName.
// It is meant to replicate the behavior of the VM ComIsolatedStorage::GetRootDir().

// (note that Silverlight used "CoreIsolatedStorage" for a directory name and did not support machine scope)

Environment.SpecialFolder specialFolder =
IsMachine(scope) ? Environment.SpecialFolder.CommonApplicationData : // e.g. C:\ProgramData
IsRoaming(scope) ? Environment.SpecialFolder.ApplicationData : // e.g. C:\Users\Joe\AppData\Roaming
Environment.SpecialFolder.LocalApplicationData; // e.g. C:\Users\Joe\AppData\Local

string dataDirectory = Environment.GetFolderPath(specialFolder, Environment.SpecialFolderOption.Create);
dataDirectory = Path.Combine(dataDirectory, IsolatedStorageDirectoryName);

return dataDirectory;
}

internal static string GetRandomDirectory(string rootDirectory, IsolatedStorageScope scope)
{
string? randomDirectory = GetExistingRandomDirectory(rootDirectory);
if (string.IsNullOrEmpty(randomDirectory))
{
using (Mutex m = CreateMutexNotOwned(rootDirectory))
{
if (!m.WaitOne())
{
throw new IsolatedStorageException(SR.IsolatedStorage_Init);
}

try
{
randomDirectory = GetExistingRandomDirectory(rootDirectory);
if (string.IsNullOrEmpty(randomDirectory))
{
// Someone else hasn't created the directory before we took the lock
randomDirectory = Path.Combine(rootDirectory, Path.GetRandomFileName(), Path.GetRandomFileName());
CreateDirectory(randomDirectory, scope);
}
}
finally
{
m.ReleaseMutex();
}
}
}

return randomDirectory;
}

private static Mutex CreateMutexNotOwned(string pathName)
{
return new Mutex(initiallyOwned: false, name: @"Global\" + IdentityHelper.GetStrongHashSuitableForObjectName(pathName));
}
}
}

This file was deleted.

Loading

0 comments on commit 1ed1206

Please sign in to comment.