Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[path_provider] Switch to Pigeon for macOS #6635

Merged
merged 5 commits into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/path_provider/path_provider_macos/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 2.0.7

* Switches platform channel implementation to Pigeon.
* Updates minimum Flutter version to 2.10.

## 2.0.6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,12 @@

import FlutterMacOS
import XCTest
import path_provider_macos
@testable import path_provider_macos

class RunnerTests: XCTestCase {
func testGetTemporaryDirectory() throws {
let plugin = PathProviderPlugin()
var path: String?
plugin.handle(
FlutterMethodCall(methodName: "getTemporaryDirectory", arguments: nil),
result: { (result: Any?) -> Void in
path = result as? String

})
let path = plugin.getDirectoryPath(type: .temp)
XCTAssertEqual(
path,
NSSearchPathForDirectoriesInDomains(
Expand All @@ -27,13 +21,7 @@ class RunnerTests: XCTestCase {

func testGetApplicationDocumentsDirectory() throws {
let plugin = PathProviderPlugin()
var path: String?
plugin.handle(
FlutterMethodCall(methodName: "getApplicationDocumentsDirectory", arguments: nil),
result: { (result: Any?) -> Void in
path = result as? String

})
let path = plugin.getDirectoryPath(type: .applicationDocuments)
XCTAssertEqual(
path,
NSSearchPathForDirectoriesInDomains(
Expand All @@ -45,13 +33,7 @@ class RunnerTests: XCTestCase {

func testGetApplicationSupportDirectory() throws {
let plugin = PathProviderPlugin()
var path: String?
plugin.handle(
FlutterMethodCall(methodName: "getApplicationSupportDirectory", arguments: nil),
result: { (result: Any?) -> Void in
path = result as? String

})
let path = plugin.getDirectoryPath(type: .applicationSupport)
// The application support directory path should be the system application support
// path with an added subdirectory based on the app name.
XCTAssert(
Expand All @@ -66,13 +48,7 @@ class RunnerTests: XCTestCase {

func testGetLibraryDirectory() throws {
let plugin = PathProviderPlugin()
var path: String?
plugin.handle(
FlutterMethodCall(methodName: "getLibraryDirectory", arguments: nil),
result: { (result: Any?) -> Void in
path = result as? String

})
let path = plugin.getDirectoryPath(type: .library)
XCTAssertEqual(
path,
NSSearchPathForDirectoriesInDomains(
Expand All @@ -84,13 +60,7 @@ class RunnerTests: XCTestCase {

func testGetDownloadsDirectory() throws {
let plugin = PathProviderPlugin()
var path: String?
plugin.handle(
FlutterMethodCall(methodName: "getDownloadsDirectory", arguments: nil),
result: { (result: Any?) -> Void in
path = result as? String

})
let path = plugin.getDirectoryPath(type: .downloads)
XCTAssertEqual(
path,
NSSearchPathForDirectoriesInDomains(
Expand Down
52 changes: 52 additions & 0 deletions packages/path_provider/path_provider_macos/lib/messages.g.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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.
// Autogenerated from Pigeon (v5.0.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;

import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';

enum DirectoryType {
applicationDocuments,
applicationSupport,
downloads,
library,
temp,
}

class PathProviderApi {
/// Constructor for [PathProviderApi]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
PathProviderApi({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;

static const MessageCodec<Object?> codec = StandardMessageCodec();

Future<String?> getDirectoryPath(DirectoryType arg_type) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.PathProviderApi.getDirectoryPath', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_type.index]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else {
return (replyList[0] as String?);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@

import 'dart:io';

import 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:flutter/services.dart';
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';

import 'messages.g.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');
final PathProviderApi _pathProvider = PathProviderApi();

/// Registers this class as the default instance of [PathProviderPlatform]
static void registerWith() {
Expand All @@ -22,13 +19,13 @@ class PathProviderMacOS extends PathProviderPlatform {

@override
Future<String?> getTemporaryPath() {
return methodChannel.invokeMethod<String>('getTemporaryDirectory');
return _pathProvider.getDirectoryPath(DirectoryType.temp);
}

@override
Future<String?> getApplicationSupportPath() async {
final String? path = await methodChannel
.invokeMethod<String>('getApplicationSupportDirectory');
final String? path =
await _pathProvider.getDirectoryPath(DirectoryType.applicationSupport);
if (path != null) {
// Ensure the directory exists before returning it, for consistency with
// other platforms.
Expand All @@ -39,13 +36,12 @@ class PathProviderMacOS extends PathProviderPlatform {

@override
Future<String?> getLibraryPath() {
return methodChannel.invokeMethod<String>('getLibraryDirectory');
return _pathProvider.getDirectoryPath(DirectoryType.library);
}

@override
Future<String?> getApplicationDocumentsPath() {
return methodChannel
.invokeMethod<String>('getApplicationDocumentsDirectory');
return _pathProvider.getDirectoryPath(DirectoryType.applicationDocuments);
}

@override
Expand All @@ -67,6 +63,6 @@ class PathProviderMacOS extends PathProviderPlatform {

@override
Future<String?> getDownloadsPath() {
return methodChannel.invokeMethod<String>('getDownloadsDirectory');
return _pathProvider.getDirectoryPath(DirectoryType.downloads);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,41 @@
import FlutterMacOS
import Foundation

public class PathProviderPlugin: NSObject, FlutterPlugin {
public class PathProviderPlugin: NSObject, FlutterPlugin, PathProviderApi {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(
name: "plugins.flutter.io/path_provider_macos",
binaryMessenger: registrar.messenger)
let instance = PathProviderPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
PathProviderApiSetup.setUp(binaryMessenger: registrar.messenger, api: instance)
}

public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getTemporaryDirectory":
result(getDirectory(ofType: FileManager.SearchPathDirectory.cachesDirectory))
case "getApplicationDocumentsDirectory":
result(getDirectory(ofType: FileManager.SearchPathDirectory.documentDirectory))
case "getApplicationSupportDirectory":
var path = getDirectory(ofType: FileManager.SearchPathDirectory.applicationSupportDirectory)
func getDirectoryPath(type: DirectoryType) -> String? {
var path = getDirectory(ofType: fileManagerDirectoryForType(type))
if type == .applicationSupport {
if let basePath = path {
let basePathURL = URL.init(fileURLWithPath: basePath)
path = basePathURL.appendingPathComponent(Bundle.main.bundleIdentifier!).path
}
result(path)
case "getLibraryDirectory":
result(getDirectory(ofType: FileManager.SearchPathDirectory.libraryDirectory))
case "getDownloadsDirectory":
result(getDirectory(ofType: FileManager.SearchPathDirectory.downloadsDirectory))
default:
result(FlutterMethodNotImplemented)
}
return path
}
}

/// Returns the user-domain director of the given type.
/// Returns the FileManager constant corresponding to the given type.
private func fileManagerDirectoryForType(_ type: DirectoryType) -> FileManager.SearchPathDirectory {
switch type {
case .applicationDocuments:
return FileManager.SearchPathDirectory.documentDirectory
case .applicationSupport:
return FileManager.SearchPathDirectory.applicationSupportDirectory
case .downloads:
return FileManager.SearchPathDirectory.downloadsDirectory
case .library:
return FileManager.SearchPathDirectory.libraryDirectory
case .temp:
return FileManager.SearchPathDirectory.cachesDirectory
}
}

/// Returns the user-domain directory of the given type.
private func getDirectory(ofType directory: FileManager.SearchPathDirectory) -> String? {
let paths = NSSearchPathForDirectoriesInDomains(
directory,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// 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.
// Autogenerated from Pigeon (v5.0.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon

import Foundation
#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#else
#error("Unsupported platform.")
#endif


/// Generated class from Pigeon.

enum DirectoryType: Int {
case applicationDocuments = 0
case applicationSupport = 1
case downloads = 2
case library = 3
case temp = 4
}
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol PathProviderApi {
func getDirectoryPath(type: DirectoryType) -> String?
}

/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
class PathProviderApiSetup {
/// The codec used by PathProviderApi.
/// Sets up an instance of `PathProviderApi` to handle messages through the `binaryMessenger`.
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: PathProviderApi?) {
let getDirectoryPathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.PathProviderApi.getDirectoryPath", binaryMessenger: binaryMessenger)
if let api = api {
getDirectoryPathChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let typeArg = DirectoryType(rawValue: args[0] as! Int)!
let result = api.getDirectoryPath(type: typeArg)
reply(wrapResult(result))
}
} else {
getDirectoryPathChannel.setMessageHandler(nil)
}
}
}

private func wrapResult(_ result: Any?) -> [Any?] {
return [result]
}

private func wrapError(_ error: FlutterError) -> [Any?] {
return [
error.code,
error.message,
error.details
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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 'package:pigeon/pigeon.dart';

@ConfigurePigeon(PigeonOptions(
input: 'pigeons/messages.dart',
swiftOut: 'macos/Classes/messages.g.swift',
dartOut: 'lib/messages.g.dart',
dartTestOut: 'test/messages_test.g.dart',
copyrightHeader: 'pigeons/copyright.txt',
))
enum DirectoryType {
applicationDocuments,
applicationSupport,
downloads,
library,
temp,
}

@HostApi(dartHostTestHandler: 'TestPathProviderApi')
abstract class PathProviderApi {
String? getDirectoryPath(DirectoryType type);
}
5 changes: 4 additions & 1 deletion packages/path_provider/path_provider_macos/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: path_provider_macos
description: macOS implementation of the path_provider plugin
repository: https://github.com/flutter/plugins/tree/main/packages/path_provider/path_provider_macos
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22
version: 2.0.6
version: 2.0.7

environment:
sdk: ">=2.12.0 <3.0.0"
Expand All @@ -22,6 +22,9 @@ dependencies:
path_provider_platform_interface: ^2.0.1

dev_dependencies:
build_runner: ^2.3.2
flutter_test:
sdk: flutter
mockito: ^5.3.2
path: ^1.8.0
pigeon: ^5.0.0
Loading