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

Commit 6b91be1

Browse files
committed
[path_provider] Use the application ID in the application support path (#2845)
Use the existing executable named directory if it exists, to allow backwards compatibility to work.
1 parent a0d99ee commit 6b91be1

File tree

5 files changed

+132
-43
lines changed

5 files changed

+132
-43
lines changed

packages/path_provider/path_provider_linux/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.1
2+
3+
* Re-add change to getApplicationSupportPath from using executable name to application ID (if provided).
4+
15
## 2.0.0
26

37
* Migrate to null safety.
Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,9 @@
11
// Copyright 2020 The Chromium Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
import 'dart:io';
5-
import 'dart:async';
64

7-
import 'package:xdg_directories/xdg_directories.dart' as xdg;
8-
import 'package:path/path.dart' as path;
9-
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
10-
11-
/// The linux implementation of [PathProviderPlatform]
12-
///
13-
/// This class implements the `package:path_provider` functionality for linux
14-
class PathProviderLinux extends PathProviderPlatform {
15-
/// Registers this class as the default instance of [PathProviderPlatform]
16-
static void register() {
17-
PathProviderPlatform.instance = PathProviderLinux();
18-
}
19-
20-
@override
21-
Future<String?> getTemporaryPath() {
22-
return Future.value("/tmp");
23-
}
24-
25-
@override
26-
Future<String?> getApplicationSupportPath() async {
27-
final processName = path.basenameWithoutExtension(
28-
await File('/proc/self/exe').resolveSymbolicLinks());
29-
final directory = Directory(path.join(xdg.dataHome.path, processName));
30-
// Creating the directory if it doesn't exist, because mobile implementations assume the directory exists
31-
if (!await directory.exists()) {
32-
await directory.create(recursive: true);
33-
}
34-
return directory.path;
35-
}
36-
37-
@override
38-
Future<String?> getApplicationDocumentsPath() {
39-
return Future.value(xdg.getUserDirectory('DOCUMENTS')?.path);
40-
}
41-
42-
@override
43-
Future<String?> getDownloadsPath() {
44-
return Future.value(xdg.getUserDirectory('DOWNLOAD')?.path);
45-
}
46-
}
5+
// path_provider_linux is implemented using FFI; export a stub for platforms
6+
// that don't support FFI (e.g., web) to avoid having transitive dependencies
7+
// break web compilation.
8+
export 'src/path_provider_linux_stub.dart'
9+
if (dart.library.ffi) 'src/path_provider_linux_real.dart';
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2020 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
import 'dart:io';
5+
import 'dart:async';
6+
import 'dart:ffi';
7+
import 'package:ffi/ffi.dart';
8+
9+
import 'package:xdg_directories/xdg_directories.dart' as xdg;
10+
import 'package:path/path.dart' as path;
11+
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
12+
13+
// GApplication* g_application_get_default();
14+
typedef g_application_get_default_c = IntPtr Function();
15+
typedef g_application_get_default_dart = int Function();
16+
17+
// const gchar* g_application_get_application_id(GApplication* application);
18+
typedef g_application_get_application_id_c = Pointer<Utf8> Function(IntPtr);
19+
typedef g_application_get_application_id_dart = Pointer<Utf8> Function(int);
20+
21+
/// The linux implementation of [PathProviderPlatform]
22+
///
23+
/// This class implements the `package:path_provider` functionality for linux
24+
class PathProviderLinux extends PathProviderPlatform {
25+
/// Registers this class as the default instance of [PathProviderPlatform]
26+
static void register() {
27+
PathProviderPlatform.instance = PathProviderLinux();
28+
}
29+
30+
@override
31+
Future<String?> getTemporaryPath() {
32+
return Future.value("/tmp");
33+
}
34+
35+
// Gets the application ID set in GApplication.
36+
String? _getApplicationId() {
37+
DynamicLibrary gio;
38+
try {
39+
gio = DynamicLibrary.open('libgio-2.0.so');
40+
} on ArgumentError {
41+
return null;
42+
}
43+
var g_application_get_default = gio.lookupFunction<
44+
g_application_get_default_c,
45+
g_application_get_default_dart>('g_application_get_default');
46+
var app = g_application_get_default();
47+
if (app == 0) return null;
48+
49+
var g_application_get_application_id = gio.lookupFunction<
50+
g_application_get_application_id_c,
51+
g_application_get_application_id_dart>(
52+
'g_application_get_application_id');
53+
var app_id = g_application_get_application_id(app);
54+
if (app_id == null) return null;
55+
56+
return app_id.toDartString();
57+
}
58+
59+
// Gets the name of this executable.
60+
Future<String> _getExecutableName() async {
61+
return path.basenameWithoutExtension(
62+
await File('/proc/self/exe').resolveSymbolicLinks());
63+
}
64+
65+
// Gets the unique ID for this application.
66+
Future<String> _getId() async {
67+
var appId = _getApplicationId();
68+
if (appId != null) return appId;
69+
70+
// Fall back to using the executable name.
71+
return await _getExecutableName();
72+
}
73+
74+
@override
75+
Future<String?> getApplicationSupportPath() async {
76+
// This plugin originally used the executable name as a directory.
77+
// Use that if it exists for backwards compatibility.
78+
final legacyDirectory =
79+
Directory(path.join(xdg.dataHome.path, await _getExecutableName()));
80+
if (await legacyDirectory.exists()) {
81+
return legacyDirectory.path;
82+
}
83+
84+
final directory = Directory(path.join(xdg.dataHome.path, await _getId()));
85+
// Creating the directory if it doesn't exist, because mobile implementations assume the directory exists
86+
if (!await directory.exists()) {
87+
await directory.create(recursive: true);
88+
}
89+
return directory.path;
90+
}
91+
92+
@override
93+
Future<String?> getApplicationDocumentsPath() {
94+
return Future.value(xdg.getUserDirectory('DOCUMENTS')?.path);
95+
}
96+
97+
@override
98+
Future<String?> getDownloadsPath() {
99+
return Future.value(xdg.getUserDirectory('DOWNLOAD')?.path);
100+
}
101+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2020 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
6+
7+
/// A stub implementation to satisfy compilation of multi-platform packages that
8+
/// depend on path_provider_linux. This should never actually be created.
9+
///
10+
/// Notably, because path_provider needs to manually register
11+
/// path_provider_linux, anything with a transitive dependency on
12+
/// path_provider will also depend on path_provider_linux, not just at the
13+
/// pubspec level but the code level.
14+
class PathProviderLinux extends PathProviderPlatform {
15+
/// Errors on attempted instantiation of the stub. It exists only to satisfy
16+
/// compile-time dependencies, and should never actually be created.
17+
PathProviderLinux() {
18+
assert(false);
19+
}
20+
}

packages/path_provider/path_provider_linux/pubspec.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: path_provider_linux
22
description: linux implementation of the path_provider plugin
3-
version: 2.0.0
3+
version: 2.0.1
44
homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_linux
55

66
flutter:
@@ -15,6 +15,7 @@ environment:
1515
flutter: ">=1.20.0"
1616

1717
dependencies:
18+
ffi: ^1.0.0
1819
path: ^1.8.0
1920
xdg_directories: ^0.2.0
2021
path_provider_platform_interface: ^2.0.0

0 commit comments

Comments
 (0)