This repository was archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[path_provider] Switch macOS to an internal method channel #4547
Merged
stuartmorgan-g
merged 5 commits into
flutter:master
from
stuartmorgan-g:path-provider-macos-dart
Dec 3, 2021
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
bfea9cf
Add an internal method channel implementation class
stuartmorgan-g d4fa795
version bump
stuartmorgan-g 2e2ae22
Add unit tests for Dart code
stuartmorgan-g 1b76a81
Move directory creation to the Dart side, and unit test it
stuartmorgan-g 4f3a5c7
Add meta
stuartmorgan-g File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
packages/path_provider/path_provider_macos/lib/path_provider_macos.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'dart:io'; | ||
|
||
import 'package:flutter/services.dart'; | ||
import 'package:meta/meta.dart'; | ||
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; | ||
|
||
/// The macOS implementation of [PathProviderPlatform]. | ||
class PathProviderMacOS extends PathProviderPlatform { | ||
/// The method channel used to interact with the native platform. | ||
@visibleForTesting | ||
MethodChannel methodChannel = | ||
const MethodChannel('plugins.flutter.io/path_provider_macos'); | ||
|
||
/// Registers this class as the default instance of [PathProviderPlatform] | ||
static void registerWith() { | ||
PathProviderPlatform.instance = PathProviderMacOS(); | ||
} | ||
|
||
@override | ||
Future<String?> getTemporaryPath() { | ||
return methodChannel.invokeMethod<String>('getTemporaryDirectory'); | ||
} | ||
|
||
@override | ||
Future<String?> getApplicationSupportPath() async { | ||
final String? path = await methodChannel | ||
.invokeMethod<String>('getApplicationSupportDirectory'); | ||
if (path != null) { | ||
// Ensure the directory exists before returning it, for consistency with | ||
// other platforms. | ||
await Directory(path).create(recursive: true); | ||
} | ||
return path; | ||
} | ||
|
||
@override | ||
Future<String?> getLibraryPath() { | ||
return methodChannel.invokeMethod<String>('getLibraryDirectory'); | ||
} | ||
|
||
@override | ||
Future<String?> getApplicationDocumentsPath() { | ||
return methodChannel | ||
.invokeMethod<String>('getApplicationDocumentsDirectory'); | ||
} | ||
|
||
@override | ||
Future<String?> getExternalStoragePath() async { | ||
throw UnsupportedError('getExternalStoragePath is not supported on macOS'); | ||
} | ||
|
||
@override | ||
Future<List<String>?> getExternalCachePaths() async { | ||
throw UnsupportedError('getExternalCachePaths is not supported on macOS'); | ||
} | ||
|
||
@override | ||
Future<List<String>?> getExternalStoragePaths({ | ||
StorageDirectory? type, | ||
}) async { | ||
throw UnsupportedError('getExternalStoragePaths is not supported on macOS'); | ||
} | ||
|
||
@override | ||
Future<String?> getDownloadsPath() { | ||
return methodChannel.invokeMethod<String>('getDownloadsDirectory'); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 137 additions & 0 deletions
137
packages/path_provider/path_provider_macos/test/path_provider_macos_test.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'dart:io'; | ||
|
||
import 'package:flutter/services.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
import 'package:path/path.dart' as p; | ||
import 'package:path_provider_macos/path_provider_macos.dart'; | ||
|
||
void main() { | ||
TestWidgetsFlutterBinding.ensureInitialized(); | ||
|
||
group('PathProviderMacOS', () { | ||
late PathProviderMacOS pathProvider; | ||
late List<MethodCall> log; | ||
// These unit tests use the actual filesystem, since an injectable | ||
// filesystem would add a runtime dependency to the package, so everything | ||
// is contained to a temporary directory. | ||
late Directory testRoot; | ||
|
||
late String temporaryPath; | ||
late String applicationSupportPath; | ||
late String libraryPath; | ||
late String applicationDocumentsPath; | ||
late String downloadsPath; | ||
|
||
setUp(() async { | ||
pathProvider = PathProviderMacOS(); | ||
|
||
testRoot = Directory.systemTemp.createTempSync(); | ||
final String basePath = testRoot.path; | ||
temporaryPath = p.join(basePath, 'temporary', 'path'); | ||
applicationSupportPath = | ||
p.join(basePath, 'application', 'support', 'path'); | ||
libraryPath = p.join(basePath, 'library', 'path'); | ||
applicationDocumentsPath = | ||
p.join(basePath, 'application', 'documents', 'path'); | ||
downloadsPath = p.join(basePath, 'downloads', 'path'); | ||
|
||
log = <MethodCall>[]; | ||
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger | ||
.setMockMethodCallHandler(pathProvider.methodChannel, | ||
(MethodCall methodCall) async { | ||
log.add(methodCall); | ||
switch (methodCall.method) { | ||
case 'getTemporaryDirectory': | ||
return temporaryPath; | ||
case 'getApplicationSupportDirectory': | ||
return applicationSupportPath; | ||
case 'getLibraryDirectory': | ||
return libraryPath; | ||
case 'getApplicationDocumentsDirectory': | ||
return applicationDocumentsPath; | ||
case 'getDownloadsDirectory': | ||
return downloadsPath; | ||
default: | ||
return null; | ||
} | ||
}); | ||
}); | ||
|
||
tearDown(() { | ||
testRoot.deleteSync(recursive: true); | ||
}); | ||
|
||
test('getTemporaryPath', () async { | ||
final String? path = await pathProvider.getTemporaryPath(); | ||
expect( | ||
log, | ||
<Matcher>[isMethodCall('getTemporaryDirectory', arguments: null)], | ||
); | ||
expect(path, temporaryPath); | ||
}); | ||
|
||
test('getApplicationSupportPath', () async { | ||
final String? path = await pathProvider.getApplicationSupportPath(); | ||
expect( | ||
log, | ||
<Matcher>[ | ||
isMethodCall('getApplicationSupportDirectory', arguments: null) | ||
], | ||
); | ||
expect(path, applicationSupportPath); | ||
}); | ||
|
||
test('getApplicationSupportPath creates the directory if necessary', | ||
() async { | ||
final String? path = await pathProvider.getApplicationSupportPath(); | ||
expect(Directory(path!).existsSync(), isTrue); | ||
}); | ||
|
||
test('getLibraryPath', () async { | ||
final String? path = await pathProvider.getLibraryPath(); | ||
expect( | ||
log, | ||
<Matcher>[isMethodCall('getLibraryDirectory', arguments: null)], | ||
); | ||
expect(path, libraryPath); | ||
}); | ||
|
||
test('getApplicationDocumentsPath', () async { | ||
final String? path = await pathProvider.getApplicationDocumentsPath(); | ||
expect( | ||
log, | ||
<Matcher>[ | ||
isMethodCall('getApplicationDocumentsDirectory', arguments: null) | ||
], | ||
); | ||
expect(path, applicationDocumentsPath); | ||
}); | ||
|
||
test('getDownloadsPath', () async { | ||
final String? result = await pathProvider.getDownloadsPath(); | ||
expect( | ||
log, | ||
<Matcher>[isMethodCall('getDownloadsDirectory', arguments: null)], | ||
); | ||
expect(result, downloadsPath); | ||
}); | ||
|
||
test('getExternalCachePaths throws', () async { | ||
expect(pathProvider.getExternalCachePaths(), throwsA(isUnsupportedError)); | ||
}); | ||
|
||
test('getExternalStoragePath throws', () async { | ||
expect( | ||
pathProvider.getExternalStoragePath(), throwsA(isUnsupportedError)); | ||
}); | ||
|
||
test('getExternalStoragePaths throws', () async { | ||
expect( | ||
pathProvider.getExternalStoragePaths(), throwsA(isUnsupportedError)); | ||
}); | ||
}); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worthwhile adding a note that the mix match of names is intentional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no reason method channels need to parallel platform interfaces, so I don't really consider it a mismatch; all that is expected (and required) to match is the Dart and native endpoints.
(Longer term this should probably be replaced with a single method+enum using Pigeon, to more closely mirror the OS API, but I just wanted to do the initial cleanup of using an internal method channel for now.)