From 7e018b9530499482d237830597e5ce0de1f4a4a4 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Wed, 3 Jun 2020 22:28:06 -0700 Subject: [PATCH 01/39] Initial Windows repo --- .../path_provider_windows/.gitignore | 3 + .../path_provider_windows/CHANGELOG.md | 3 + .../path_provider_windows/LICENSE | 27 ++++ .../path_provider_windows/README.md | 37 +++++ .../path_provider_windows/example/README.md | 8 + .../example/lib/main.dart | 149 ++++++++++++++++++ .../example/pubspec.yaml | 19 +++ .../test_driver/path_provider_e2e.dart | 51 ++++++ .../test_driver/path_provider_e2e_test.dart | 15 ++ .../lib/path_provider_windows.dart | 86 ++++++++++ .../path_provider_windows/pubspec.yaml | 26 +++ 11 files changed, 424 insertions(+) create mode 100644 packages/path_provider/path_provider_windows/.gitignore create mode 100644 packages/path_provider/path_provider_windows/CHANGELOG.md create mode 100644 packages/path_provider/path_provider_windows/LICENSE create mode 100644 packages/path_provider/path_provider_windows/README.md create mode 100644 packages/path_provider/path_provider_windows/example/README.md create mode 100644 packages/path_provider/path_provider_windows/example/lib/main.dart create mode 100644 packages/path_provider/path_provider_windows/example/pubspec.yaml create mode 100644 packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart create mode 100644 packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e_test.dart create mode 100644 packages/path_provider/path_provider_windows/lib/path_provider_windows.dart create mode 100644 packages/path_provider/path_provider_windows/pubspec.yaml diff --git a/packages/path_provider/path_provider_windows/.gitignore b/packages/path_provider/path_provider_windows/.gitignore new file mode 100644 index 000000000000..53e92cc4181f --- /dev/null +++ b/packages/path_provider/path_provider_windows/.gitignore @@ -0,0 +1,3 @@ +.packages +.flutter-plugins +pubspec.lock diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md new file mode 100644 index 000000000000..cbdbf72f5540 --- /dev/null +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* Initial open source release. diff --git a/packages/path_provider/path_provider_windows/LICENSE b/packages/path_provider/path_provider_windows/LICENSE new file mode 100644 index 000000000000..687fb4968920 --- /dev/null +++ b/packages/path_provider/path_provider_windows/LICENSE @@ -0,0 +1,27 @@ +Copyright 2020 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/path_provider/path_provider_windows/README.md b/packages/path_provider/path_provider_windows/README.md new file mode 100644 index 000000000000..3ac99f3f86c6 --- /dev/null +++ b/packages/path_provider/path_provider_windows/README.md @@ -0,0 +1,37 @@ +# path_provider_windows + +The Windows implementation of [`path_provider`]. + +**Please set your constraint to `path_provider_windows: '>=0.0.y+x <2.0.0'`** + +## Backward compatible 1.0.0 version is coming +The plugin has reached a stable API, we guarantee that version `1.0.0` will be backward compatible with `0.0.y+z`. +Please use `path_provider_windows: '>=0.0.y+x <2.0.0'` as your dependency constraint to allow a smoother ecosystem migration. +For more details see: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0 + +## Usage + +### Import the package + +To use this plugin in your Flutter Windows app, simply add it as a dependency in +your `pubspec.yaml` alongside the base `path_provider` plugin. + +_(This is only temporary: in the future we hope to make this package an +"endorsed" implementation of `path_provider`, so that it is automatically +included in your Flutter macos app when you depend on `package:path_provider`.)_ + +This is what the above means to your `pubspec.yaml`: + +```yaml +... +dependencies: + ... + path_provider: ^1.5.1 + path_provider_windows: ^0.0.1 + ... +``` + +### Use the plugin + +Once you have the `path_provider_windows` dependency in your pubspec, you should +be able to use `package:path_provider` as normal. diff --git a/packages/path_provider/path_provider_windows/example/README.md b/packages/path_provider/path_provider_windows/example/README.md new file mode 100644 index 000000000000..f3ca03ff37c3 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/README.md @@ -0,0 +1,8 @@ +# path_provider_windows_example + +Demonstrates how to use the path_provider_windows plugin. + +## Getting Started + +For help getting started with Flutter, view our online +[documentation](http://flutter.io/). diff --git a/packages/path_provider/path_provider_windows/example/lib/main.dart b/packages/path_provider/path_provider_windows/example/lib/main.dart new file mode 100644 index 000000000000..473a989914f6 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/lib/main.dart @@ -0,0 +1,149 @@ +// Copyright 2019 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. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:io' show Directory; + +import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; + +void main() { + runApp(MyApp()); +} + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Path Provider', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: MyHomePage(title: 'Path Provider'), + ); + } +} + +class MyHomePage extends StatefulWidget { + MyHomePage({Key key, this.title}) : super(key: key); + final String title; + + @override + _MyHomePageState createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + Future _tempDirectory; + Future _appSupportDirectory; + Future _appDocumentsDirectory; + Future _appLibraryDirectory; + Future _downloadsDirectory; + + void _requestTempDirectory() { + setState(() { + _tempDirectory = getTemporaryDirectory(); + }); + } + + Widget _buildDirectory( + BuildContext context, AsyncSnapshot snapshot) { + Text text = const Text(''); + if (snapshot.connectionState == ConnectionState.done) { + if (snapshot.hasError) { + text = Text('Error: ${snapshot.error}'); + } else if (snapshot.hasData) { + text = Text('path: ${snapshot.data.path}'); + } else { + text = const Text('path unavailable'); + } + } + return Padding(padding: const EdgeInsets.all(16.0), child: text); + } + + void _requestAppDocumentsDirectory() { + setState(() { + _appDocumentsDirectory = getApplicationDocumentsDirectory(); + }); + } + + void _requestAppSupportDirectory() { + setState(() { + _appSupportDirectory = getApplicationSupportDirectory(); + }); + } + + void _requestAppLibraryDirectory() { + setState(() { + _appLibraryDirectory = getLibraryDirectory(); + }); + } + + void _requestDownloadsDirectory() { + setState(() { + _downloadsDirectory = getDownloadsDirectory(); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Center( + child: ListView( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: RaisedButton( + child: const Text('Get Temporary Directory'), + onPressed: _requestTempDirectory, + ), + ), + FutureBuilder( + future: _tempDirectory, builder: _buildDirectory), + Padding( + padding: const EdgeInsets.all(16.0), + child: RaisedButton( + child: const Text('Get Application Documents Directory'), + onPressed: _requestAppDocumentsDirectory, + ), + ), + FutureBuilder( + future: _appDocumentsDirectory, builder: _buildDirectory), + Padding( + padding: const EdgeInsets.all(16.0), + child: RaisedButton( + child: const Text('Get Application Support Directory'), + onPressed: _requestAppSupportDirectory, + ), + ), + FutureBuilder( + future: _appSupportDirectory, builder: _buildDirectory), + Padding( + padding: const EdgeInsets.all(16.0), + child: RaisedButton( + child: const Text('Get Application Library Directory'), + onPressed: _requestAppLibraryDirectory, + ), + ), + FutureBuilder( + future: _appLibraryDirectory, builder: _buildDirectory), + Padding( + padding: const EdgeInsets.all(16.0), + child: RaisedButton( + child: const Text('Get Downlads Directory'), + onPressed: _requestDownloadsDirectory, + ), + ), + FutureBuilder( + future: _downloadsDirectory, builder: _buildDirectory), + ], + ), + ), + ); + } +} diff --git a/packages/path_provider/path_provider_windows/example/pubspec.yaml b/packages/path_provider/path_provider_windows/example/pubspec.yaml new file mode 100644 index 000000000000..cd272be76dff --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/pubspec.yaml @@ -0,0 +1,19 @@ +name: path_provider_example +description: Demonstrates how to use the path_provider plugin. + +dependencies: + flutter: + sdk: flutter + path_provider: any + path_provider_windows: + path: ../ + +dev_dependencies: + e2e: ^0.2.1 + flutter_driver: + sdk: flutter + test: any + pedantic: ^1.8.0 + +flutter: + uses-material-design: true diff --git a/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart b/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart new file mode 100644 index 000000000000..6cb8362b76d5 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart @@ -0,0 +1,51 @@ +// Copyright 2019, the Chromium project authors. Please see the AUTHORS file +// for details. 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_test/flutter_test.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:e2e/e2e.dart'; + +void main() { + E2EWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('getTemporaryDirectory', (WidgetTester tester) async { + final Directory result = await getTemporaryDirectory(); + _verifySampleFile(result, 'temporaryDirectory'); + }); + + testWidgets('getApplicationDocumentsDirectory', (WidgetTester tester) async { + final Directory result = await getApplicationDocumentsDirectory(); + _verifySampleFile(result, 'applicationDocuments'); + }); + + testWidgets('getApplicationSupportDirectory', (WidgetTester tester) async { + final Directory result = await getApplicationSupportDirectory(); + _verifySampleFile(result, 'applicationSupport'); + }); + + testWidgets('getLibraryDirectory', (WidgetTester tester) async { + if (!Platform.isMacOS) { + return; + } + final Directory result = await getLibraryDirectory(); + _verifySampleFile(result, 'library'); + }); +} + +/// Verify a file called [name] in [directory] by recreating it with test +/// contents when necessary. +void _verifySampleFile(Directory directory, String name) { + final File file = File('${directory.path}/$name'); + + if (file.existsSync()) { + file.deleteSync(); + expect(file.existsSync(), isFalse); + } + + file.writeAsStringSync('Hello world!'); + expect(file.readAsStringSync(), 'Hello world!'); + expect(directory.listSync(), isNotEmpty); + file.deleteSync(); +} diff --git a/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e_test.dart b/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e_test.dart new file mode 100644 index 000000000000..f3aa9e218d82 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e_test.dart @@ -0,0 +1,15 @@ +// Copyright 2019, the Chromium project authors. Please see the AUTHORS file +// for details. 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:async'; +import 'dart:io'; +import 'package:flutter_driver/flutter_driver.dart'; + +Future main() async { + final FlutterDriver driver = await FlutterDriver.connect(); + final String result = + await driver.requestData(null, timeout: const Duration(minutes: 1)); + await driver.close(); + exit(result == 'pass' ? 0 : 1); +} diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart new file mode 100644 index 000000000000..c9c965915737 --- /dev/null +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -0,0 +1,86 @@ +// Copyright 2020 The Chromium 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:async'; + +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; + +/// The Windows implementation of [PathProviderPlatform] +/// +/// This class implements the `package:path_provider` functionality for Windows +class PathProviderWindows extends PathProviderPlatform { + /// Registers this class as the default instance of [PathProviderPlatform] + static void register() { + PathProviderPlatform.instance = PathProviderWindows(); + } + + /// Path to the temporary directory on the device that is not backed up and is + /// suitable for storing caches of downloaded files. + @override + Future getTemporaryPath() { + throw UnimplementedError('getTemporaryPath() has not been implemented.'); + } + + /// Path to a directory where the application may place application support + /// files. + @override + Future getApplicationSupportPath() { + throw UnimplementedError( + 'getApplicationSupportPath() has not been implemented.'); + } + + /// Path to the directory where application can store files that are persistent, + /// backed up, and not visible to the user, such as sqlite.db. + @override + Future getLibraryPath() { + throw UnimplementedError('getLibraryPath() has not been implemented.'); + } + + /// Path to a directory where the application may place data that is + /// user-generated, or that cannot otherwise be recreated by your application. + @override + Future getApplicationDocumentsPath() { + throw UnimplementedError( + 'getApplicationDocumentsPath() has not been implemented.'); + } + + /// Path to a directory where the application may access top level storage. + /// The current operating system should be determined before issuing this + /// function call, as this functionality is only available on Android. + @override + Future getExternalStoragePath() { + throw UnimplementedError( + 'getExternalStoragePath() has not been implemented.'); + } + + /// Paths to directories where application specific external cache data can be + /// stored. These paths typically reside on external storage like separate + /// partitions or SD cards. Phones may have multiple storage directories + /// available. + @override + Future> getExternalCachePaths() { + throw UnimplementedError( + 'getExternalCachePaths() has not been implemented.'); + } + + /// Paths to directories where application specific data can be stored. + /// These paths typically reside on external storage like separate partitions + /// or SD cards. Phones may have multiple storage directories available. + @override + Future> getExternalStoragePaths({ + /// Optional parameter. See [StorageDirectory] for more informations on + /// how this type translates to Android storage directories. + StorageDirectory type, + }) { + throw UnimplementedError( + 'getExternalStoragePaths() has not been implemented.'); + } + + /// Path to the directory where downloaded files can be stored. + /// This is typically only relevant on desktop operating systems. + @override + Future getDownloadsPath() { + throw UnimplementedError('getDownloadsPath() has not been implemented.'); + } +} diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml new file mode 100644 index 000000000000..7c4280ddd79f --- /dev/null +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -0,0 +1,26 @@ +name: path_provider_windows +description: Windows implementation of the path_provider plugin +# 0.0.y+z is compatible with 1.0.0, if you land a breaking change bump +# the version to 2.0.0. +# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0 +version: 0.0.1+0 +homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows + +flutter: + plugin: + platforms: + windows: + dartPluginClass: PathProviderPlugin + +environment: + sdk: ">=2.1.0 <3.0.0" + flutter: ">=1.10.0 <2.0.0" + +dependencies: + flutter: + sdk: flutter + path_provider_platform_interface: ^1.0.1 + win32: ^1.5.0 + +dev_dependencies: + pedantic: ^1.8.0 From 712c0433865d754b333bce5eb550b70568063423 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Thu, 4 Jun 2020 15:05:31 -0700 Subject: [PATCH 02/39] Implementation for getTemporaryPath() and getDownloadsPath() --- .../lib/path_provider_windows.dart | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index c9c965915737..7600f76a62f0 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -3,7 +3,10 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:ffi'; +import 'package:ffi/ffi.dart'; +import 'package:win32/win32.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; /// The Windows implementation of [PathProviderPlatform] @@ -17,15 +20,35 @@ class PathProviderWindows extends PathProviderPlatform { /// Path to the temporary directory on the device that is not backed up and is /// suitable for storing caches of downloaded files. + /// + /// On Windows, this the path specified by the TMP environment variable, or + /// the TEMP environment variable, or the USERPROFILE environment variable, + /// or the Windows directory, in order of preference. Windows does not + /// guarantee that the path exists or is writeable to. @override Future getTemporaryPath() { - throw UnimplementedError('getTemporaryPath() has not been implemented.'); + final buffer = allocate(count: MAX_PATH + 1).cast(); + final length = GetTempPath(MAX_PATH, buffer); + + if (length == 0) { + final error = GetLastError(); + free(buffer); + throw WindowsException('$error'); + } else { + final path = buffer.unpackString(MAX_PATH); + free(buffer); + return Future.value(path); + } } + // FOLDERID_LocalAppData + // FOLDERID_ProgramData + /// Path to a directory where the application may place application support /// files. @override Future getApplicationSupportPath() { + // SHGetKnownFolderPath(); throw UnimplementedError( 'getApplicationSupportPath() has not been implemented.'); } @@ -77,10 +100,30 @@ class PathProviderWindows extends PathProviderPlatform { 'getExternalStoragePaths() has not been implemented.'); } - /// Path to the directory where downloaded files can be stored. - /// This is typically only relevant on desktop operating systems. + /// Path to the directory where downloaded files can be stored. This is + /// typically the same as %USERPROFILE%\Downloads. @override Future getDownloadsPath() { - throw UnimplementedError('getDownloadsPath() has not been implemented.'); + Pointer pathPtr; + + final hr = SHGetKnownFolderPath( + GUID.fromString(FOLDERID_Downloads).addressOf, + KF_FLAG_DEFAULT, + NULL, + pathPtr); + + if (FAILED(hr)) { + if (hr == E_INVALIDARG || hr == E_FAIL) { + return WindowsException('Invalid folder.') + } else { + throw WindowsException('Unknown error.'); + } + } + + final path = + Pointer.fromAddress(pathPtr.value).unpackString(MAX_PATH); + + CoTaskMemFree(pathPtr.cast()); + return Future.value(path); } } From 55429f6968efcffa085113d8f47a9e8b6b13ebd7 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Thu, 4 Jun 2020 16:02:10 -0700 Subject: [PATCH 03/39] Tidy up Windows plugin implementation --- .../example/lib/main.dart | 182 ++++++------------ .../test_driver/path_provider_e2e.dart | 4 +- .../path_provider_windows/lib/folders.dart | 145 ++++++++++++++ .../lib/path_provider_windows.dart | 85 +++----- .../path_provider_windows/pubspec.yaml | 2 +- .../test/path_provider_windows_test.dart | 20 ++ 6 files changed, 258 insertions(+), 180 deletions(-) create mode 100644 packages/path_provider/path_provider_windows/lib/folders.dart create mode 100644 packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart diff --git a/packages/path_provider/path_provider_windows/example/lib/main.dart b/packages/path_provider/path_provider_windows/example/lib/main.dart index 473a989914f6..f76b6c552113 100644 --- a/packages/path_provider/path_provider_windows/example/lib/main.dart +++ b/packages/path_provider/path_provider_windows/example/lib/main.dart @@ -1,147 +1,89 @@ -// Copyright 2019 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. - -// ignore_for_file: public_member_api_docs - +import 'package:flutter/material.dart'; import 'dart:async'; -import 'dart:io' show Directory; -import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:win32/win32.dart'; -void main() { +void main() async { runApp(MyApp()); } -class MyApp extends StatelessWidget { +/// Sample app +class MyApp extends StatefulWidget { @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Path Provider', - theme: ThemeData( - primarySwatch: Colors.blue, - ), - home: MyHomePage(title: 'Path Provider'), - ); - } + _MyAppState createState() => _MyAppState(); } -class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); - final String title; +class _MyAppState extends State { + String _tempDirectory = 'Unknown'; + String _downloadsDirectory = 'Unknown'; + String _appSupportDirectory = 'Unknown'; + String _documentsDirectory = 'Unknown'; @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - Future _tempDirectory; - Future _appSupportDirectory; - Future _appDocumentsDirectory; - Future _appLibraryDirectory; - Future _downloadsDirectory; - - void _requestTempDirectory() { - setState(() { - _tempDirectory = getTemporaryDirectory(); - }); + void initState() { + super.initState(); + initDirectories(); } - Widget _buildDirectory( - BuildContext context, AsyncSnapshot snapshot) { - Text text = const Text(''); - if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.hasError) { - text = Text('Error: ${snapshot.error}'); - } else if (snapshot.hasData) { - text = Text('path: ${snapshot.data.path}'); - } else { - text = const Text('path unavailable'); - } + // Platform messages are asynchronous, so we initialize in an async method. + Future initDirectories() async { + String tempDirectory; + String downloadsDirectory; + String appSupportDirectory; + String documentsDirectory; + // Platform messages may fail, so we use a try/catch PlatformException. + try { + tempDirectory = (await getTemporaryDirectory()).path; + } on WindowsException { + tempDirectory = 'Failed to get temp directory.'; + } + try { + downloadsDirectory = (await getDownloadsDirectory()).path; + } on WindowsException { + downloadsDirectory = 'Failed to get downloads directory.'; } - return Padding(padding: const EdgeInsets.all(16.0), child: text); - } - - void _requestAppDocumentsDirectory() { - setState(() { - _appDocumentsDirectory = getApplicationDocumentsDirectory(); - }); - } - void _requestAppSupportDirectory() { - setState(() { - _appSupportDirectory = getApplicationSupportDirectory(); - }); - } + try { + documentsDirectory = (await getApplicationDocumentsDirectory()).path; + } on WindowsException { + documentsDirectory = 'Failed to get documents directory.'; + } - void _requestAppLibraryDirectory() { - setState(() { - _appLibraryDirectory = getLibraryDirectory(); - }); - } + try { + appSupportDirectory = (await getApplicationSupportDirectory()).path; + } on WindowsException { + appSupportDirectory = 'Failed to get documents directory.'; + } + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) return; - void _requestDownloadsDirectory() { setState(() { - _downloadsDirectory = getDownloadsDirectory(); + _tempDirectory = tempDirectory; + _downloadsDirectory = downloadsDirectory; + _appSupportDirectory = appSupportDirectory; + _documentsDirectory = documentsDirectory; }); } @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: ListView( - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: RaisedButton( - child: const Text('Get Temporary Directory'), - onPressed: _requestTempDirectory, - ), - ), - FutureBuilder( - future: _tempDirectory, builder: _buildDirectory), - Padding( - padding: const EdgeInsets.all(16.0), - child: RaisedButton( - child: const Text('Get Application Documents Directory'), - onPressed: _requestAppDocumentsDirectory, - ), - ), - FutureBuilder( - future: _appDocumentsDirectory, builder: _buildDirectory), - Padding( - padding: const EdgeInsets.all(16.0), - child: RaisedButton( - child: const Text('Get Application Support Directory'), - onPressed: _requestAppSupportDirectory, - ), - ), - FutureBuilder( - future: _appSupportDirectory, builder: _buildDirectory), - Padding( - padding: const EdgeInsets.all(16.0), - child: RaisedButton( - child: const Text('Get Application Library Directory'), - onPressed: _requestAppLibraryDirectory, - ), - ), - FutureBuilder( - future: _appLibraryDirectory, builder: _buildDirectory), - Padding( - padding: const EdgeInsets.all(16.0), - child: RaisedButton( - child: const Text('Get Downlads Directory'), - onPressed: _requestDownloadsDirectory, - ), - ), - FutureBuilder( - future: _downloadsDirectory, builder: _buildDirectory), - ], + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Path Provider Windows example app'), + ), + body: Center( + child: Column( + children: [ + Text('Temp Directory: $_tempDirectory\n'), + Text('Documents Directory: $_documentsDirectory\n'), + Text('Downloads Directory: $_downloadsDirectory\n'), + Text('Application Support Directory: $_appSupportDirectory\n'), + ], + ), ), ), ); diff --git a/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart b/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart index 6cb8362b76d5..4201afb90cb2 100644 --- a/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart +++ b/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart @@ -26,7 +26,7 @@ void main() { }); testWidgets('getLibraryDirectory', (WidgetTester tester) async { - if (!Platform.isMacOS) { + if (!Platform.isWindows) { return; } final Directory result = await getLibraryDirectory(); @@ -37,7 +37,7 @@ void main() { /// Verify a file called [name] in [directory] by recreating it with test /// contents when necessary. void _verifySampleFile(Directory directory, String name) { - final File file = File('${directory.path}/$name'); + final File file = File('${directory.path}${Platform.pathSeparator}$name'); if (file.existsSync()) { file.deleteSync(); diff --git a/packages/path_provider/path_provider_windows/lib/folders.dart b/packages/path_provider/path_provider_windows/lib/folders.dart new file mode 100644 index 000000000000..0efc4d7e33d9 --- /dev/null +++ b/packages/path_provider/path_provider_windows/lib/folders.dart @@ -0,0 +1,145 @@ +import 'package:win32/win32.dart'; + +class WindowsKnownFolder { + static String get AccountPictures => FOLDERID_AccountPictures; + static String get AddNewPrograms => FOLDERID_AddNewPrograms; + static String get AdminTools => FOLDERID_AdminTools; + static String get AllAppMods => FOLDERID_AllAppMods; + static String get AppCaptures => FOLDERID_AppCaptures; + static String get AppDataDesktop => FOLDERID_AppDataDesktop; + static String get AppDataDocuments => FOLDERID_AppDataDocuments; + static String get AppDataFavorites => FOLDERID_AppDataFavorites; + static String get AppDataProgramData => FOLDERID_AppDataProgramData; + static String get AppUpdates => FOLDERID_AppUpdates; + static String get ApplicationShortcuts => FOLDERID_ApplicationShortcuts; + static String get AppsFolder => FOLDERID_AppsFolder; + static String get CDBurning => FOLDERID_CDBurning; + static String get CameraRoll => FOLDERID_CameraRoll; + static String get CameraRollLibrary => FOLDERID_CameraRollLibrary; + static String get ChangeRemovePrograms => FOLDERID_ChangeRemovePrograms; + static String get CommonAdminTools => FOLDERID_CommonAdminTools; + static String get CommonOEMLinks => FOLDERID_CommonOEMLinks; + static String get CommonPrograms => FOLDERID_CommonPrograms; + static String get CommonStartMenu => FOLDERID_CommonStartMenu; + static String get CommonStartMenuPlaces => FOLDERID_CommonStartMenuPlaces; + static String get CommonStartup => FOLDERID_CommonStartup; + static String get CommonTemplates => FOLDERID_CommonTemplates; + static String get ComputerFolder => FOLDERID_ComputerFolder; + static String get ConflictFolder => FOLDERID_ConflictFolder; + static String get ConnectionsFolder => FOLDERID_ConnectionsFolder; + static String get Contacts => FOLDERID_Contacts; + static String get ControlPanelFolder => FOLDERID_ControlPanelFolder; + static String get Cookies => FOLDERID_Cookies; + static String get CurrentAppMods => FOLDERID_CurrentAppMods; + static String get Desktop => FOLDERID_Desktop; + static String get DevelopmentFiles => FOLDERID_DevelopmentFiles; + static String get Device => FOLDERID_Device; + static String get DeviceMetadataStore => FOLDERID_DeviceMetadataStore; + static String get Documents => FOLDERID_Documents; + static String get DocumentsLibrary => FOLDERID_DocumentsLibrary; + static String get Downloads => FOLDERID_Downloads; + static String get Favorites => FOLDERID_Favorites; + static String get Fonts => FOLDERID_Fonts; + static String get GameTasks => FOLDERID_GameTasks; + static String get Games => FOLDERID_Games; + static String get History => FOLDERID_History; + static String get HomeGroup => FOLDERID_HomeGroup; + static String get HomeGroupCurrentUser => FOLDERID_HomeGroupCurrentUser; + static String get ImplicitAppShortcuts => FOLDERID_ImplicitAppShortcuts; + static String get InternetCache => FOLDERID_InternetCache; + static String get InternetFolder => FOLDERID_InternetFolder; + static String get Libraries => FOLDERID_Libraries; + static String get Links => FOLDERID_Links; + static String get LocalAppData => FOLDERID_LocalAppData; + static String get LocalAppDataLow => FOLDERID_LocalAppDataLow; + static String get LocalDocuments => FOLDERID_LocalDocuments; + static String get LocalDownloads => FOLDERID_LocalDownloads; + static String get LocalMusic => FOLDERID_LocalMusic; + static String get LocalPictures => FOLDERID_LocalPictures; + static String get LocalVideos => FOLDERID_LocalVideos; + static String get LocalizedResourcesDir => FOLDERID_LocalizedResourcesDir; + static String get Music => FOLDERID_Music; + static String get MusicLibrary => FOLDERID_MusicLibrary; + static String get NetHood => FOLDERID_NetHood; + static String get NetworkFolder => FOLDERID_NetworkFolder; + static String get Objects3D => FOLDERID_Objects3D; + static String get OneDrive => FOLDERID_OneDrive; + static String get OriginalImages => FOLDERID_OriginalImages; + static String get PhotoAlbums => FOLDERID_PhotoAlbums; + static String get Pictures => FOLDERID_Pictures; + static String get PicturesLibrary => FOLDERID_PicturesLibrary; + static String get Playlists => FOLDERID_Playlists; + static String get PrintHood => FOLDERID_PrintHood; + static String get PrintersFolder => FOLDERID_PrintersFolder; + static String get Profile => FOLDERID_Profile; + static String get ProgramData => FOLDERID_ProgramData; + static String get ProgramFiles => FOLDERID_ProgramFiles; + static String get ProgramFilesCommon => FOLDERID_ProgramFilesCommon; + static String get ProgramFilesCommonX64 => FOLDERID_ProgramFilesCommonX64; + static String get ProgramFilesCommonX86 => FOLDERID_ProgramFilesCommonX86; + static String get ProgramFilesX64 => FOLDERID_ProgramFilesX64; + static String get ProgramFilesX86 => FOLDERID_ProgramFilesX86; + static String get Programs => FOLDERID_Programs; + static String get Public => FOLDERID_Public; + static String get PublicDesktop => FOLDERID_PublicDesktop; + static String get PublicDocuments => FOLDERID_PublicDocuments; + static String get PublicDownloads => FOLDERID_PublicDownloads; + static String get PublicGameTasks => FOLDERID_PublicGameTasks; + static String get PublicLibraries => FOLDERID_PublicLibraries; + static String get PublicMusic => FOLDERID_PublicMusic; + static String get PublicPictures => FOLDERID_PublicPictures; + static String get PublicRingtones => FOLDERID_PublicRingtones; + static String get PublicUserTiles => FOLDERID_PublicUserTiles; + static String get PublicVideos => FOLDERID_PublicVideos; + static String get QuickLaunch => FOLDERID_QuickLaunch; + static String get Recent => FOLDERID_Recent; + static String get RecordedCalls => FOLDERID_RecordedCalls; + static String get RecordedTVLibrary => FOLDERID_RecordedTVLibrary; + static String get RecycleBinFolder => FOLDERID_RecycleBinFolder; + static String get ResourceDir => FOLDERID_ResourceDir; + static String get RetailDemo => FOLDERID_RetailDemo; + static String get Ringtones => FOLDERID_Ringtones; + static String get RoamedTileImages => FOLDERID_RoamedTileImages; + static String get RoamingAppData => FOLDERID_RoamingAppData; + static String get RoamingTiles => FOLDERID_RoamingTiles; + static String get SEARCH_CSC => FOLDERID_SEARCH_CSC; + static String get SEARCH_MAPI => FOLDERID_SEARCH_MAPI; + static String get SampleMusic => FOLDERID_SampleMusic; + static String get SamplePictures => FOLDERID_SamplePictures; + static String get SamplePlaylists => FOLDERID_SamplePlaylists; + static String get SampleVideos => FOLDERID_SampleVideos; + static String get SavedGames => FOLDERID_SavedGames; + static String get SavedPictures => FOLDERID_SavedPictures; + static String get SavedPicturesLibrary => FOLDERID_SavedPicturesLibrary; + static String get SavedSearches => FOLDERID_SavedSearches; + static String get Screenshots => FOLDERID_Screenshots; + static String get SearchHistory => FOLDERID_SearchHistory; + static String get SearchHome => FOLDERID_SearchHome; + static String get SearchTemplates => FOLDERID_SearchTemplates; + static String get SendTo => FOLDERID_SendTo; + static String get SidebarDefaultParts => FOLDERID_SidebarDefaultParts; + static String get SidebarParts => FOLDERID_SidebarParts; + static String get SkyDrive => FOLDERID_SkyDrive; + static String get SkyDriveCameraRoll => FOLDERID_SkyDriveCameraRoll; + static String get SkyDriveDocuments => FOLDERID_SkyDriveDocuments; + static String get SkyDriveMusic => FOLDERID_SkyDriveMusic; + static String get SkyDrivePictures => FOLDERID_SkyDrivePictures; + static String get StartMenu => FOLDERID_StartMenu; + static String get StartMenuAllPrograms => FOLDERID_StartMenuAllPrograms; + static String get Startup => FOLDERID_Startup; + static String get SyncManagerFolder => FOLDERID_SyncManagerFolder; + static String get SyncResultsFolder => FOLDERID_SyncResultsFolder; + static String get SyncSetupFolder => FOLDERID_SyncSetupFolder; + static String get System => FOLDERID_System; + static String get SystemX86 => FOLDERID_SystemX86; + static String get Templates => FOLDERID_Templates; + static String get UserPinned => FOLDERID_UserPinned; + static String get UserProfiles => FOLDERID_UserProfiles; + static String get UserProgramFiles => FOLDERID_UserProgramFiles; + static String get UserProgramFilesCommon => FOLDERID_UserProgramFilesCommon; + static String get UsersFiles => FOLDERID_UsersFiles; + static String get UsersLibraries => FOLDERID_UsersLibraries; + static String get Videos => FOLDERID_Videos; + static String get VideosLibrary => FOLDERID_VideosLibrary; + static String get Windows => FOLDERID_Windows; +} diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 7600f76a62f0..8dfe8ec0ddec 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -8,6 +8,7 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'package:win32/win32.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; +import 'package:path_provider_windows/folders.dart'; /// The Windows implementation of [PathProviderPlatform] /// @@ -35,95 +36,65 @@ class PathProviderWindows extends PathProviderPlatform { free(buffer); throw WindowsException('$error'); } else { - final path = buffer.unpackString(MAX_PATH); + var path = buffer.unpackString(MAX_PATH); + + // GetTempPath adds a trailing backslash, but SHGetKnownFolderPath does not. + // Strip off trailing backslash for consistency with other methods here. + if (path[path.length - 1] == '\\') { + path = path.substring(0, path.length - 1); + } free(buffer); return Future.value(path); } } - // FOLDERID_LocalAppData - // FOLDERID_ProgramData - /// Path to a directory where the application may place application support /// files. @override - Future getApplicationSupportPath() { - // SHGetKnownFolderPath(); - throw UnimplementedError( - 'getApplicationSupportPath() has not been implemented.'); - } + Future getApplicationSupportPath() => + getPath(WindowsKnownFolder.ProgramData); /// Path to the directory where application can store files that are persistent, /// backed up, and not visible to the user, such as sqlite.db. @override - Future getLibraryPath() { - throw UnimplementedError('getLibraryPath() has not been implemented.'); - } + Future getLibraryPath() => getPath(WindowsKnownFolder.LocalAppData); /// Path to a directory where the application may place data that is /// user-generated, or that cannot otherwise be recreated by your application. @override - Future getApplicationDocumentsPath() { - throw UnimplementedError( - 'getApplicationDocumentsPath() has not been implemented.'); - } - - /// Path to a directory where the application may access top level storage. - /// The current operating system should be determined before issuing this - /// function call, as this functionality is only available on Android. - @override - Future getExternalStoragePath() { - throw UnimplementedError( - 'getExternalStoragePath() has not been implemented.'); - } - - /// Paths to directories where application specific external cache data can be - /// stored. These paths typically reside on external storage like separate - /// partitions or SD cards. Phones may have multiple storage directories - /// available. - @override - Future> getExternalCachePaths() { - throw UnimplementedError( - 'getExternalCachePaths() has not been implemented.'); - } - - /// Paths to directories where application specific data can be stored. - /// These paths typically reside on external storage like separate partitions - /// or SD cards. Phones may have multiple storage directories available. - @override - Future> getExternalStoragePaths({ - /// Optional parameter. See [StorageDirectory] for more informations on - /// how this type translates to Android storage directories. - StorageDirectory type, - }) { - throw UnimplementedError( - 'getExternalStoragePaths() has not been implemented.'); - } + Future getApplicationDocumentsPath() => + getPath(WindowsKnownFolder.DocumentsLibrary); /// Path to the directory where downloaded files can be stored. This is /// typically the same as %USERPROFILE%\Downloads. @override - Future getDownloadsPath() { - Pointer pathPtr; + Future getDownloadsPath() => getPath(WindowsKnownFolder.Downloads); + + /// Retrieve any known folder from Windows. + /// + /// folderID is a GUID that represents a specific known folder ID, drawn from + /// [WindowsKnownFolder]. + Future getPath(String folderID) { + GUID knownFolderID = GUID.fromString(folderID); + Pointer pathPtrPtr = allocate(); final hr = SHGetKnownFolderPath( - GUID.fromString(FOLDERID_Downloads).addressOf, - KF_FLAG_DEFAULT, - NULL, - pathPtr); + knownFolderID.addressOf, KF_FLAG_DEFAULT, NULL, pathPtrPtr); if (FAILED(hr)) { if (hr == E_INVALIDARG || hr == E_FAIL) { - return WindowsException('Invalid folder.') + throw WindowsException('Invalid folder.'); } else { throw WindowsException('Unknown error.'); } } - final path = - Pointer.fromAddress(pathPtr.value).unpackString(MAX_PATH); + final pathPtr = Pointer.fromAddress(pathPtrPtr.value); + final path = pathPtr.unpackString(MAX_PATH); CoTaskMemFree(pathPtr.cast()); + free(pathPtrPtr); + return Future.value(path); } } diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 7c4280ddd79f..c4cc3e522831 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: flutter: sdk: flutter path_provider_platform_interface: ^1.0.1 - win32: ^1.5.0 + win32: ^1.5.1 dev_dependencies: pedantic: ^1.8.0 diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart new file mode 100644 index 000000000000..dba82250376e --- /dev/null +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -0,0 +1,20 @@ +// Copyright 2020 The Chromium 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:flutter_test/flutter_test.dart'; +import 'package:path_provider_windows/path_provider_windows.dart'; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + PathProviderWindows.register(); + + setUp(() {}); + + tearDown(() {}); + + test('getTemporaryPath', () async { + final plugin = PathProviderPlatform.instance; + expect(await plugin.getTemporaryPath(), contains('C:\\')); + }); +} From 52d5b0dc0635e897057a05a6844337bd0749a35a Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 5 Jun 2020 11:42:06 -0700 Subject: [PATCH 04/39] Add folder documentation comments. --- .../path_provider_windows/lib/folders.dart | 269 ++++++++++++------ 1 file changed, 180 insertions(+), 89 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/folders.dart b/packages/path_provider/path_provider_windows/lib/folders.dart index 0efc4d7e33d9..c60e74efa23f 100644 --- a/packages/path_provider/path_provider_windows/lib/folders.dart +++ b/packages/path_provider/path_provider_windows/lib/folders.dart @@ -1,145 +1,236 @@ import 'package:win32/win32.dart'; +/// A class containing the GUID references for each of the documented Windows +/// known folders. A property of this class may be passed to the `getPath` +/// method in the [PathProvidersWindows] class to retrieve a known folder from +/// Windows. class WindowsKnownFolder { - static String get AccountPictures => FOLDERID_AccountPictures; - static String get AddNewPrograms => FOLDERID_AddNewPrograms; + /// The file system directory that is used to store administrative tools for + /// an individual user. The MMC will save customized consoles to this + /// directory, and it will roam with the user. static String get AdminTools => FOLDERID_AdminTools; - static String get AllAppMods => FOLDERID_AllAppMods; - static String get AppCaptures => FOLDERID_AppCaptures; - static String get AppDataDesktop => FOLDERID_AppDataDesktop; - static String get AppDataDocuments => FOLDERID_AppDataDocuments; - static String get AppDataFavorites => FOLDERID_AppDataFavorites; - static String get AppDataProgramData => FOLDERID_AppDataProgramData; - static String get AppUpdates => FOLDERID_AppUpdates; - static String get ApplicationShortcuts => FOLDERID_ApplicationShortcuts; - static String get AppsFolder => FOLDERID_AppsFolder; + + /// The file system directory that acts as a staging area for files waiting to + /// be written to a CD. A typical path is C:\Documents and + /// Settings\username\Local Settings\Application Data\Microsoft\CD Burning. static String get CDBurning => FOLDERID_CDBurning; - static String get CameraRoll => FOLDERID_CameraRoll; - static String get CameraRollLibrary => FOLDERID_CameraRollLibrary; - static String get ChangeRemovePrograms => FOLDERID_ChangeRemovePrograms; + + /// The file system directory that contains administrative tools for all users + /// of the computer. static String get CommonAdminTools => FOLDERID_CommonAdminTools; - static String get CommonOEMLinks => FOLDERID_CommonOEMLinks; + + /// The file system directory that contains the directories for the common + /// program groups that appear on the Start menu for all users. A typical path + /// is C:\Documents and Settings\All Users\Start Menu\Programs. static String get CommonPrograms => FOLDERID_CommonPrograms; + + /// The file system directory that contains the programs and folders that + /// appear on the Start menu for all users. A typical path is C:\Documents and + /// Settings\All Users\Start Menu. static String get CommonStartMenu => FOLDERID_CommonStartMenu; - static String get CommonStartMenuPlaces => FOLDERID_CommonStartMenuPlaces; + + /// The file system directory that contains the programs that appear in the + /// Startup folder for all users. A typical path is C:\Documents and + /// Settings\All Users\Start Menu\Programs\Startup. static String get CommonStartup => FOLDERID_CommonStartup; + + /// The file system directory that contains the templates that are available + /// to all users. A typical path is C:\Documents and Settings\All + /// Users\Templates. static String get CommonTemplates => FOLDERID_CommonTemplates; + + /// The virtual folder that represents My Computer, containing everything on + /// the local computer: storage devices, printers, and Control Panel. The + /// folder can also contain mapped network drives. static String get ComputerFolder => FOLDERID_ComputerFolder; - static String get ConflictFolder => FOLDERID_ConflictFolder; + + /// The virtual folder that represents Network Connections, that contains + /// network and dial-up connections. static String get ConnectionsFolder => FOLDERID_ConnectionsFolder; - static String get Contacts => FOLDERID_Contacts; + + /// The virtual folder that contains icons for the Control Panel applications. static String get ControlPanelFolder => FOLDERID_ControlPanelFolder; + + /// The file system directory that serves as a common repository for Internet + /// cookies. A typical path is C:\Documents and Settings\username\Cookies. static String get Cookies => FOLDERID_Cookies; - static String get CurrentAppMods => FOLDERID_CurrentAppMods; + + /// The virtual folder that represents the Windows desktop, the root of the + /// namespace. static String get Desktop => FOLDERID_Desktop; - static String get DevelopmentFiles => FOLDERID_DevelopmentFiles; - static String get Device => FOLDERID_Device; - static String get DeviceMetadataStore => FOLDERID_DeviceMetadataStore; + + /// The virtual folder that represents the My Documents desktop item. static String get Documents => FOLDERID_Documents; - static String get DocumentsLibrary => FOLDERID_DocumentsLibrary; + + /// The file system directory that serves as a repository for Internet + /// downloads. static String get Downloads => FOLDERID_Downloads; + + /// The file system directory that serves as a common repository for the + /// user's favorite items. A typical path is C:\Documents and + /// Settings\username\Favorites. static String get Favorites => FOLDERID_Favorites; + + /// A virtual folder that contains fonts. A typical path is C:\Windows\Fonts. static String get Fonts => FOLDERID_Fonts; - static String get GameTasks => FOLDERID_GameTasks; - static String get Games => FOLDERID_Games; + + /// The file system directory that serves as a common repository for Internet + /// history items. static String get History => FOLDERID_History; - static String get HomeGroup => FOLDERID_HomeGroup; - static String get HomeGroupCurrentUser => FOLDERID_HomeGroupCurrentUser; - static String get ImplicitAppShortcuts => FOLDERID_ImplicitAppShortcuts; + + /// The file system directory that serves as a common repository for temporary + /// Internet files. A typical path is C:\Documents and Settings\username\Local + /// Settings\Temporary Internet Files. static String get InternetCache => FOLDERID_InternetCache; + + /// A virtual folder for Internet Explorer. static String get InternetFolder => FOLDERID_InternetFolder; - static String get Libraries => FOLDERID_Libraries; - static String get Links => FOLDERID_Links; + + /// The file system directory that serves as a data repository for local + /// (nonroaming) applications. A typical path is C:\Documents and + /// Settings\username\Local Settings\Application Data. static String get LocalAppData => FOLDERID_LocalAppData; - static String get LocalAppDataLow => FOLDERID_LocalAppDataLow; - static String get LocalDocuments => FOLDERID_LocalDocuments; - static String get LocalDownloads => FOLDERID_LocalDownloads; - static String get LocalMusic => FOLDERID_LocalMusic; - static String get LocalPictures => FOLDERID_LocalPictures; - static String get LocalVideos => FOLDERID_LocalVideos; - static String get LocalizedResourcesDir => FOLDERID_LocalizedResourcesDir; + + /// The file system directory that serves as a common repository for music + /// files. A typical path is C:\Documents and Settings\User\My Documents\My + /// Music. static String get Music => FOLDERID_Music; - static String get MusicLibrary => FOLDERID_MusicLibrary; + + /// A file system directory that contains the link objects that may exist in + /// the My Network Places virtual folder. A typical path is C:\Documents and + /// Settings\username\NetHood. static String get NetHood => FOLDERID_NetHood; + + /// The folder that represents other computers in your workgroup. static String get NetworkFolder => FOLDERID_NetworkFolder; - static String get Objects3D => FOLDERID_Objects3D; - static String get OneDrive => FOLDERID_OneDrive; - static String get OriginalImages => FOLDERID_OriginalImages; - static String get PhotoAlbums => FOLDERID_PhotoAlbums; + + /// The file system directory that serves as a common repository for image + /// files. A typical path is C:\Documents and Settings\username\My + /// Documents\My Pictures. static String get Pictures => FOLDERID_Pictures; - static String get PicturesLibrary => FOLDERID_PicturesLibrary; - static String get Playlists => FOLDERID_Playlists; + + /// The file system directory that contains the link objects that can exist in + /// the Printers virtual folder. A typical path is C:\Documents and + /// Settings\username\PrintHood. static String get PrintHood => FOLDERID_PrintHood; + + /// The virtual folder that contains installed printers. static String get PrintersFolder => FOLDERID_PrintersFolder; + + /// The user's profile folder. A typical path is C:\Users\username. + /// Applications should not create files or folders at this level. static String get Profile => FOLDERID_Profile; + + /// The file system directory that contains application data for all users. A + /// typical path is C:\Documents and Settings\All Users\Application Data. This + /// folder is used for application data that is not user specific. For + /// example, an application can store a spell-check dictionary, a database of + /// clip art, or a log file in the CSIDL_COMMON_APPDATA folder. This + /// information will not roam and is available to anyone using the computer. static String get ProgramData => FOLDERID_ProgramData; + + /// The Program Files folder. A typical path is C:\Program Files. static String get ProgramFiles => FOLDERID_ProgramFiles; + + /// The common Program Files folder. A typical path is C:\Program + /// Files\Common. static String get ProgramFilesCommon => FOLDERID_ProgramFilesCommon; + + /// On 64-bit systems, a link to the common Program Files folder. A typical path is + /// C:\Program Files\Common Files. static String get ProgramFilesCommonX64 => FOLDERID_ProgramFilesCommonX64; + + /// On 64-bit systems, a link to the 32-bit common Program Files folder. A + /// typical path is C:\Program Files (x86)\Common Files. On 32-bit systems, a + /// link to the Common Program Files folder. static String get ProgramFilesCommonX86 => FOLDERID_ProgramFilesCommonX86; + + /// On 64-bit systems, a link to the Program Files folder. A typical path is + /// C:\Program Files. static String get ProgramFilesX64 => FOLDERID_ProgramFilesX64; + + /// On 64-bit systems, a link to the 32-bit Program Files folder. A typical + /// path is C:\Program Files (x86). On 32-bit systems, a link to the Common + /// Program Files folder. static String get ProgramFilesX86 => FOLDERID_ProgramFilesX86; + + /// The file system directory that contains the user's program groups (which + /// are themselves file system directories). static String get Programs => FOLDERID_Programs; - static String get Public => FOLDERID_Public; + + /// The file system directory that contains files and folders that appear on + /// the desktop for all users. A typical path is C:\Documents and Settings\All + /// Users\Desktop. static String get PublicDesktop => FOLDERID_PublicDesktop; + + /// The file system directory that contains documents that are common to all + /// users. A typical path is C:\Documents and Settings\All Users\Documents. static String get PublicDocuments => FOLDERID_PublicDocuments; - static String get PublicDownloads => FOLDERID_PublicDownloads; - static String get PublicGameTasks => FOLDERID_PublicGameTasks; - static String get PublicLibraries => FOLDERID_PublicLibraries; + + /// The file system directory that serves as a repository for music files + /// common to all users. A typical path is C:\Documents and Settings\All + /// Users\Documents\My Music. static String get PublicMusic => FOLDERID_PublicMusic; + + /// The file system directory that serves as a repository for image files + /// common to all users. A typical path is C:\Documents and Settings\All + /// Users\Documents\My Pictures. static String get PublicPictures => FOLDERID_PublicPictures; - static String get PublicRingtones => FOLDERID_PublicRingtones; - static String get PublicUserTiles => FOLDERID_PublicUserTiles; + + /// The file system directory that serves as a repository for video files + /// common to all users. A typical path is C:\Documents and Settings\All + /// Users\Documents\My Videos. static String get PublicVideos => FOLDERID_PublicVideos; - static String get QuickLaunch => FOLDERID_QuickLaunch; + + /// The file system directory that contains shortcuts to the user's most + /// recently used documents. A typical path is C:\Documents and + /// Settings\username\My Recent Documents. static String get Recent => FOLDERID_Recent; - static String get RecordedCalls => FOLDERID_RecordedCalls; - static String get RecordedTVLibrary => FOLDERID_RecordedTVLibrary; + + /// The virtual folder that contains the objects in the user's Recycle Bin. static String get RecycleBinFolder => FOLDERID_RecycleBinFolder; + + /// The file system directory that contains resource data. A typical path is + /// C:\Windows\Resources. static String get ResourceDir => FOLDERID_ResourceDir; - static String get RetailDemo => FOLDERID_RetailDemo; - static String get Ringtones => FOLDERID_Ringtones; - static String get RoamedTileImages => FOLDERID_RoamedTileImages; + + /// The file system directory that serves as a common repository for + /// application-specific data. A typical path is C:\Documents and + /// Settings\username\Application Data. static String get RoamingAppData => FOLDERID_RoamingAppData; - static String get RoamingTiles => FOLDERID_RoamingTiles; - static String get SEARCH_CSC => FOLDERID_SEARCH_CSC; - static String get SEARCH_MAPI => FOLDERID_SEARCH_MAPI; - static String get SampleMusic => FOLDERID_SampleMusic; - static String get SamplePictures => FOLDERID_SamplePictures; - static String get SamplePlaylists => FOLDERID_SamplePlaylists; - static String get SampleVideos => FOLDERID_SampleVideos; - static String get SavedGames => FOLDERID_SavedGames; - static String get SavedPictures => FOLDERID_SavedPictures; - static String get SavedPicturesLibrary => FOLDERID_SavedPicturesLibrary; - static String get SavedSearches => FOLDERID_SavedSearches; - static String get Screenshots => FOLDERID_Screenshots; - static String get SearchHistory => FOLDERID_SearchHistory; - static String get SearchHome => FOLDERID_SearchHome; - static String get SearchTemplates => FOLDERID_SearchTemplates; + + /// The file system directory that contains Send To menu items. A typical path + /// is C:\Documents and Settings\username\SendTo. static String get SendTo => FOLDERID_SendTo; - static String get SidebarDefaultParts => FOLDERID_SidebarDefaultParts; - static String get SidebarParts => FOLDERID_SidebarParts; - static String get SkyDrive => FOLDERID_SkyDrive; - static String get SkyDriveCameraRoll => FOLDERID_SkyDriveCameraRoll; - static String get SkyDriveDocuments => FOLDERID_SkyDriveDocuments; - static String get SkyDriveMusic => FOLDERID_SkyDriveMusic; - static String get SkyDrivePictures => FOLDERID_SkyDrivePictures; + + /// The file system directory that contains Start menu items. A typical path + /// is C:\Documents and Settings\username\Start Menu. static String get StartMenu => FOLDERID_StartMenu; - static String get StartMenuAllPrograms => FOLDERID_StartMenuAllPrograms; + + /// The file system directory that corresponds to the user's Startup program + /// group. The system starts these programs whenever the associated user logs + /// on. A typical path is C:\Documents and Settings\username\Start + /// Menu\Programs\Startup. static String get Startup => FOLDERID_Startup; - static String get SyncManagerFolder => FOLDERID_SyncManagerFolder; - static String get SyncResultsFolder => FOLDERID_SyncResultsFolder; - static String get SyncSetupFolder => FOLDERID_SyncSetupFolder; + + /// The Windows System folder. A typical path is C:\Windows\System32. static String get System => FOLDERID_System; + + // The 32-bit Windows System folder. On 32-bit systems, this is typically + // C:\Windows\system32. On 64-bit systems, this is typically + // C:\Windows\syswow64. static String get SystemX86 => FOLDERID_SystemX86; + + /// The file system directory that serves as a common repository for document + /// templates. A typical path is C:\Documents and Settings\username\Templates. static String get Templates => FOLDERID_Templates; - static String get UserPinned => FOLDERID_UserPinned; - static String get UserProfiles => FOLDERID_UserProfiles; - static String get UserProgramFiles => FOLDERID_UserProgramFiles; - static String get UserProgramFilesCommon => FOLDERID_UserProgramFilesCommon; - static String get UsersFiles => FOLDERID_UsersFiles; - static String get UsersLibraries => FOLDERID_UsersLibraries; + + /// The file system directory that serves as a common repository for video + /// files. A typical path is C:\Documents and Settings\username\My + /// Documents\My Videos. static String get Videos => FOLDERID_Videos; - static String get VideosLibrary => FOLDERID_VideosLibrary; + + /// The Windows directory or SYSROOT. This corresponds to the %windir% or + /// %SYSTEMROOT% environment variables. A typical path is C:\Windows. static String get Windows => FOLDERID_Windows; } From aea6a4c1cf0cc84c98175e684022f3d12dbff83a Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 5 Jun 2020 11:47:04 -0700 Subject: [PATCH 05/39] Add Windows runner --- .../path_provider_windows/example/.gitignore | 44 +++ .../path_provider_windows/example/.metadata | 10 + .../example/windows/.gitignore | 17 ++ .../example/windows/AppConfiguration.props | 6 + .../example/windows/FlutterBuild.vcxproj | 50 ++++ .../example/windows/Runner.sln | 43 +++ .../example/windows/Runner.vcxproj | 262 ++++++++++++++++++ .../example/windows/Runner.vcxproj.filters | 88 ++++++ .../example/windows/flutter/.template_version | 1 + .../windows/flutter/GeneratedPlugins.props | 8 + .../flutter/generated_plugin_registrant.cc | 9 + .../flutter/generated_plugin_registrant.h | 13 + .../example/windows/runner/Runner.rc | 70 +++++ .../example/windows/runner/flutter_window.cpp | 29 ++ .../example/windows/runner/flutter_window.h | 37 +++ .../example/windows/runner/main.cpp | 37 +++ .../example/windows/runner/resource.h | 16 ++ .../windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes .../example/windows/runner/run_loop.cpp | 70 +++++ .../example/windows/runner/run_loop.h | 40 +++ .../windows/runner/runner.exe.manifest | 20 ++ .../example/windows/runner/utils.cpp | 22 ++ .../example/windows/runner/utils.h | 8 + .../example/windows/runner/win32_window.cpp | 249 +++++++++++++++++ .../example/windows/runner/win32_window.h | 96 +++++++ .../windows/runner/window_configuration.cpp | 7 + .../windows/runner/window_configuration.h | 18 ++ .../scripts/bundle_assets_and_deps.bat | 44 +++ .../windows/scripts/prepare_dependencies.bat | 5 + .../lib/path_provider_windows.dart | 2 +- 30 files changed, 1320 insertions(+), 1 deletion(-) create mode 100644 packages/path_provider/path_provider_windows/example/.gitignore create mode 100644 packages/path_provider/path_provider_windows/example/.metadata create mode 100644 packages/path_provider/path_provider_windows/example/windows/.gitignore create mode 100644 packages/path_provider/path_provider_windows/example/windows/AppConfiguration.props create mode 100644 packages/path_provider/path_provider_windows/example/windows/FlutterBuild.vcxproj create mode 100644 packages/path_provider/path_provider_windows/example/windows/Runner.sln create mode 100644 packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj create mode 100644 packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj.filters create mode 100644 packages/path_provider/path_provider_windows/example/windows/flutter/.template_version create mode 100644 packages/path_provider/path_provider_windows/example/windows/flutter/GeneratedPlugins.props create mode 100644 packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.cc create mode 100644 packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.h create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/Runner.rc create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.cpp create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.h create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/main.cpp create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/resource.h create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/resources/app_icon.ico create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/run_loop.cpp create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/run_loop.h create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/runner.exe.manifest create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/utils.cpp create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/utils.h create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/win32_window.cpp create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/win32_window.h create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.cpp create mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.h create mode 100644 packages/path_provider/path_provider_windows/example/windows/scripts/bundle_assets_and_deps.bat create mode 100644 packages/path_provider/path_provider_windows/example/windows/scripts/prepare_dependencies.bat diff --git a/packages/path_provider/path_provider_windows/example/.gitignore b/packages/path_provider/path_provider_windows/example/.gitignore new file mode 100644 index 000000000000..f3c205341e7d --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Exceptions to above rules. +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/packages/path_provider/path_provider_windows/example/.metadata b/packages/path_provider/path_provider_windows/example/.metadata new file mode 100644 index 000000000000..bc654e753a99 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f2320c3b7a42bc27e7f038212eed1b01f4269641 + channel: master + +project_type: app diff --git a/packages/path_provider/path_provider_windows/example/windows/.gitignore b/packages/path_provider/path_provider_windows/example/windows/.gitignore new file mode 100644 index 000000000000..d492d0d98c8f --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/packages/path_provider/path_provider_windows/example/windows/AppConfiguration.props b/packages/path_provider/path_provider_windows/example/windows/AppConfiguration.props new file mode 100644 index 000000000000..42b257ad7116 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/AppConfiguration.props @@ -0,0 +1,6 @@ + + + + example + + diff --git a/packages/path_provider/path_provider_windows/example/windows/FlutterBuild.vcxproj b/packages/path_provider/path_provider_windows/example/windows/FlutterBuild.vcxproj new file mode 100644 index 000000000000..8ef93f9e7af8 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/FlutterBuild.vcxproj @@ -0,0 +1,50 @@ + + + + + Debug + x64 + + + Profile + x64 + + + Release + x64 + + + + 15.0 + {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} + Flutter Build + 10.0 + + + + v141 + v142 + + + + + + + + + + + + + + "$(ProjectDir)scripts\prepare_dependencies" $(Configuration) + Running Flutter backend build + force_to_run_every_time + + + + + + + + diff --git a/packages/path_provider/path_provider_windows/example/windows/Runner.sln b/packages/path_provider/path_provider_windows/example/windows/Runner.sln new file mode 100644 index 000000000000..7bfc8e03b3a8 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/Runner.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Runner", "Runner.vcxproj", "{5A827760-CF8B-408A-99A3-B6C0AD2271E7}" + ProjectSection(ProjectDependencies) = postProject + {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} = {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Flutter Build", "FlutterBuild.vcxproj", "{6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Flutter Plugins", "Flutter Plugins", "{5C2E738A-1DD3-445A-AAC8-EEB9648DD07C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Profile|x64 = Profile|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Debug|x64.ActiveCfg = Debug|x64 + {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Debug|x64.Build.0 = Debug|x64 + {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Profile|x64.ActiveCfg = Profile|x64 + {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Profile|x64.Build.0 = Profile|x64 + {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Release|x64.ActiveCfg = Release|x64 + {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Release|x64.Build.0 = Release|x64 + {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Debug|x64.ActiveCfg = Debug|x64 + {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Debug|x64.Build.0 = Debug|x64 + {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Profile|x64.ActiveCfg = Profile|x64 + {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Profile|x64.Build.0 = Profile|x64 + {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Release|x64.ActiveCfg = Release|x64 + {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B8A69CB0-A974-4774-9EBD-1E5EECACD186} + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj b/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj new file mode 100644 index 000000000000..af25405c44e4 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj @@ -0,0 +1,262 @@ + + + + + Debug + x64 + + + Profile + x64 + + + Release + x64 + + + + 15.0 + {5A827760-CF8B-408A-99A3-B6C0AD2271E7} + example + 10.0 + + + + Application + true + v141 + v142 + Unicode + + + Application + false + v141 + v142 + true + Unicode + + + Application + false + v141 + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ + + + $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ + + + $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ + + + + Level4 + Disabled + true + true + $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) + _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) + true + 4100 + + + flutter_windows.dll.lib;%(AdditionalDependencies) + $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)" + + + Bundling dependencies + Dummy_Run_Always + + + + + + + Level4 + MaxSpeed + true + true + true + true + $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) + _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) + true + 4100 + + + true + true + flutter_windows.dll.lib;%(AdditionalDependencies) + $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)" + + + Bundling dependencies + Dummy_Run_Always + + + + + + + Level4 + MaxSpeed + true + true + true + true + $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) + _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) + true + 4100 + + + true + true + flutter_windows.dll.lib;%(AdditionalDependencies) + $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)" + + + Bundling dependencies + Dummy_Run_Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir) + + diff --git a/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj.filters b/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj.filters new file mode 100644 index 000000000000..761db86287a2 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj.filters @@ -0,0 +1,88 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {2761a4b5-57b2-4d50-a677-d20ddc17a7f1} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Client Wrapper + + + Source Files\Client Wrapper + + + Source Files\Client Wrapper + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + + + + Resource Files + + + + + Resource Files + + + diff --git a/packages/path_provider/path_provider_windows/example/windows/flutter/.template_version b/packages/path_provider/path_provider_windows/example/windows/flutter/.template_version new file mode 100644 index 000000000000..00750edc07d6 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/flutter/.template_version @@ -0,0 +1 @@ +3 diff --git a/packages/path_provider/path_provider_windows/example/windows/flutter/GeneratedPlugins.props b/packages/path_provider/path_provider_windows/example/windows/flutter/GeneratedPlugins.props new file mode 100644 index 000000000000..d3d26c72fbc5 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/flutter/GeneratedPlugins.props @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.cc b/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000000..4bfa0f3a3a75 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,9 @@ +// +// Generated file. Do not edit. +// + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.h b/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000000..9846246b4dac --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,13 @@ +// +// Generated file. Do not edit. +// + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/Runner.rc b/packages/path_provider/path_provider_windows/example/windows/runner/Runner.rc new file mode 100644 index 000000000000..5b41a82a4074 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/Runner.rc @@ -0,0 +1,70 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.cpp new file mode 100644 index 000000000000..fe980cf8d12b --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.cpp @@ -0,0 +1,29 @@ +#include "flutter_window.h" + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop* run_loop, + const flutter::DartProject& project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +void FlutterWindow::OnCreate() { + Win32Window::OnCreate(); + + // The size here is arbitrary since SetChildContent will resize it. + flutter_controller_ = + std::make_unique(100, 100, project_); + RegisterPlugins(flutter_controller_.get()); + run_loop_->RegisterFlutterInstance(flutter_controller_.get()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_.get()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.h b/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.h new file mode 100644 index 000000000000..4f41e16f1c95 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.h @@ -0,0 +1,37 @@ +#ifndef FLUTTER_WINDOW_H_ +#define FLUTTER_WINDOW_H_ + +#include +#include + +#include "run_loop.h" +#include "win32_window.h" + +#include + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop* run_loop, + const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + void OnCreate() override; + void OnDestroy() override; + + private: + // The run loop driving events for this window. + RunLoop* run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // FLUTTER_WINDOW_H_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/main.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/main.cpp new file mode 100644 index 000000000000..11b48e95738b --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/main.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" +#include "window_configuration.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(kFlutterWindowOriginX, kFlutterWindowOriginY); + Win32Window::Size size(kFlutterWindowWidth, kFlutterWindowHeight); + if (!window.CreateAndShow(kFlutterWindowTitle, origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/resource.h b/packages/path_provider/path_provider_windows/example/windows/runner/resource.h new file mode 100644 index 000000000000..66a65d1e4a79 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/resources/app_icon.ico b/packages/path_provider/path_provider_windows/example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 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 literal 0 HcmV?d00001 diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.cpp new file mode 100644 index 000000000000..f91d6d4cb91b --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.cpp @@ -0,0 +1,70 @@ +#include "run_loop.h" + +#include +// Don't stomp std::min/std::max +#undef max +#undef min + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterViewController* flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterViewController* flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto flutter_controller : flutter_instances_) { + std::chrono::nanoseconds wait_duration = + flutter_controller->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.h b/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.h new file mode 100644 index 000000000000..442a58e5622b --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.h @@ -0,0 +1,40 @@ +#ifndef RUN_LOOP_H_ +#define RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { + public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const&) = delete; + RunLoop& operator=(RunLoop const&) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance( + flutter::FlutterViewController* flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance( + flutter::FlutterViewController* flutter_instance); + + private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUN_LOOP_H_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/runner.exe.manifest b/packages/path_provider/path_provider_windows/example/windows/runner/runner.exe.manifest new file mode 100644 index 000000000000..c977c4a42589 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/utils.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/utils.cpp new file mode 100644 index 000000000000..37501e5db777 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/utils.cpp @@ -0,0 +1,22 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/utils.h b/packages/path_provider/path_provider_windows/example/windows/runner/utils.h new file mode 100644 index 000000000000..d247a66308b4 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/utils.h @@ -0,0 +1,8 @@ +#ifndef CONSOLE_UTILS_H_ +#define CONSOLE_UTILS_H_ + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +#endif // CONSOLE_UTILS_H_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.cpp new file mode 100644 index 000000000000..677a9a6cca8e --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.cpp @@ -0,0 +1,249 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + OnCreate(); + + return window != nullptr; +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + auto window = + reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + + if (window == nullptr) { + return 0; + } + + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: + RECT rect; + GetClientRect(hwnd, &rect); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + // Messages that are directly forwarded to embedding. + case WM_FONTCHANGE: + SendMessage(child_content_, WM_FONTCHANGE, NULL, NULL); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame; + GetClientRect(window_handle_, &frame); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +void Win32Window::OnCreate() { + // No-op; provided for subclasses. +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.h b/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.h new file mode 100644 index 000000000000..5cbb5d594d69 --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.h @@ -0,0 +1,96 @@ +#ifndef WIN32_WINDOW_H_ +#define WIN32_WINDOW_H_ + +#include +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. + virtual void OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // WIN32_WINDOW_H_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.cpp new file mode 100644 index 000000000000..c56ede18175e --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.cpp @@ -0,0 +1,7 @@ +#include "window_configuration.h" + +const wchar_t* kFlutterWindowTitle = L"example"; +const unsigned int kFlutterWindowOriginX = 10; +const unsigned int kFlutterWindowOriginY = 10; +const unsigned int kFlutterWindowWidth = 1280; +const unsigned int kFlutterWindowHeight = 720; diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.h b/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.h new file mode 100644 index 000000000000..ea5cead43c4b --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.h @@ -0,0 +1,18 @@ +#ifndef WINDOW_CONFIGURATION_ +#define WINDOW_CONFIGURATION_ + +// This is a temporary approach to isolate changes that people are likely to +// make to main.cpp, where the APIs are still in flux. This will reduce the +// need to resolve conflicts or re-create changes slightly differently every +// time the Windows Flutter API surface changes. +// +// Longer term there should be simpler configuration options for common +// customizations like this, without requiring native code changes. + +extern const wchar_t* kFlutterWindowTitle; +extern const unsigned int kFlutterWindowOriginX; +extern const unsigned int kFlutterWindowOriginY; +extern const unsigned int kFlutterWindowWidth; +extern const unsigned int kFlutterWindowHeight; + +#endif // WINDOW_CONFIGURATION_ diff --git a/packages/path_provider/path_provider_windows/example/windows/scripts/bundle_assets_and_deps.bat b/packages/path_provider/path_provider_windows/example/windows/scripts/bundle_assets_and_deps.bat new file mode 100644 index 000000000000..9efa28f8e72a --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/scripts/bundle_assets_and_deps.bat @@ -0,0 +1,44 @@ +@echo off + +set FLUTTER_CACHE_DIR=%~1 +set BUNDLE_DIR=%~2 +set PLUGIN_DIR=%~3 +set EXE_NAME=%~4 +set BUILD_MODE=%~5 + +set DATA_DIR=%BUNDLE_DIR%data + +if not exist "%DATA_DIR%" call mkdir "%DATA_DIR%" +if %errorlevel% neq 0 exit /b %errorlevel% + +:: Write the executable name to the location expected by the Flutter tool. +echo %EXE_NAME%>"%FLUTTER_CACHE_DIR%exe_filename" + +:: Copy the Flutter assets to the data directory. +set FLUTTER_BUILD_DIR=%~dp0..\..\build\ +set ASSET_DIR_NAME=flutter_assets +set TARGET_ASSET_DIR=%DATA_DIR%\%ASSET_DIR_NAME% +if exist "%TARGET_ASSET_DIR%" call rmdir /s /q "%TARGET_ASSET_DIR%" +if %errorlevel% neq 0 exit /b %errorlevel% +call xcopy /s /e /i /q "%FLUTTER_BUILD_DIR%%ASSET_DIR_NAME%" "%TARGET_ASSET_DIR%" +if %errorlevel% neq 0 exit /b %errorlevel% + +:: Copy the icudtl.dat file from the Flutter tree to the data directory. +call xcopy /y /d /q "%FLUTTER_CACHE_DIR%icudtl.dat" "%DATA_DIR%" +if %errorlevel% neq 0 exit /b %errorlevel% + +:: For non-debug modes, copy app.so into the data directory. +if not %BUILD_MODE% == "Debug" ( + call xcopy /y /d /q "%FLUTTER_BUILD_DIR%windows\app.so" "%DATA_DIR%" + if %errorlevel% neq 0 exit /b %errorlevel% +) + +:: Copy the Flutter DLL to the target location. +call xcopy /y /d /q "%FLUTTER_CACHE_DIR%flutter_windows.dll" "%BUNDLE_DIR%" +if %errorlevel% neq 0 exit /b %errorlevel% + +:: Copy any Plugin DLLs to the target location. +if exist "%PLUGIN_DIR%" ( + call xcopy /y /d /q "%PLUGIN_DIR%"*.dll "%BUNDLE_DIR%" + if %errorlevel% neq 0 exit /b %errorlevel% +) diff --git a/packages/path_provider/path_provider_windows/example/windows/scripts/prepare_dependencies.bat b/packages/path_provider/path_provider_windows/example/windows/scripts/prepare_dependencies.bat new file mode 100644 index 000000000000..d05238be3fcb --- /dev/null +++ b/packages/path_provider/path_provider_windows/example/windows/scripts/prepare_dependencies.bat @@ -0,0 +1,5 @@ +@echo off + +:: Run flutter tool backend. +set BUILD_MODE=%~1 +"%FLUTTER_ROOT%\packages\flutter_tools\bin\tool_backend" windows-x64 %BUILD_MODE% diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 8dfe8ec0ddec..d231515b73e2 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -63,7 +63,7 @@ class PathProviderWindows extends PathProviderPlatform { /// user-generated, or that cannot otherwise be recreated by your application. @override Future getApplicationDocumentsPath() => - getPath(WindowsKnownFolder.DocumentsLibrary); + getPath(WindowsKnownFolder.Documents); /// Path to the directory where downloaded files can be stored. This is /// typically the same as %USERPROFILE%\Downloads. From f20a00e3896f9d3de0d25cc2d633ea2638f536ff Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 5 Jun 2020 11:59:33 -0700 Subject: [PATCH 06/39] Fix doc comment nit --- .../path_provider/path_provider_windows/lib/folders.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/folders.dart b/packages/path_provider/path_provider_windows/lib/folders.dart index c60e74efa23f..f0d0e4bbae4b 100644 --- a/packages/path_provider/path_provider_windows/lib/folders.dart +++ b/packages/path_provider/path_provider_windows/lib/folders.dart @@ -216,9 +216,9 @@ class WindowsKnownFolder { /// The Windows System folder. A typical path is C:\Windows\System32. static String get System => FOLDERID_System; - // The 32-bit Windows System folder. On 32-bit systems, this is typically - // C:\Windows\system32. On 64-bit systems, this is typically - // C:\Windows\syswow64. + /// The 32-bit Windows System folder. On 32-bit systems, this is typically + /// C:\Windows\system32. On 64-bit systems, this is typically + /// C:\Windows\syswow64. static String get SystemX86 => FOLDERID_SystemX86; /// The file system directory that serves as a common repository for document From 1be04d779ea2e8e571250226c4a2559bca0dc738 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 5 Jun 2020 11:59:48 -0700 Subject: [PATCH 07/39] Set pubspec version --- packages/path_provider/path_provider/pubspec.yaml | 3 +++ packages/path_provider/path_provider_windows/CHANGELOG.md | 4 +++- packages/path_provider/path_provider_windows/pubspec.yaml | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/path_provider/pubspec.yaml b/packages/path_provider/path_provider/pubspec.yaml index 98059e148140..9fe9dce869c6 100644 --- a/packages/path_provider/path_provider/pubspec.yaml +++ b/packages/path_provider/path_provider/pubspec.yaml @@ -16,6 +16,8 @@ flutter: default_package: path_provider_macos linux: default_package: path_provider_linux + windows: + default_package: path_provider_windows dependencies: flutter: @@ -23,6 +25,7 @@ dependencies: path_provider_platform_interface: ^1.0.1 path_provider_macos: ^0.0.4 path_provider_linux: ^0.0.1 + path_provider_windows: ^0.0.1 dev_dependencies: e2e: ^0.2.1 diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md index cbdbf72f5540..b65e3aa46c99 100644 --- a/packages/path_provider/path_provider_windows/CHANGELOG.md +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -1,3 +1,5 @@ ## 0.0.1 -* Initial open source release. +* The initial implementation of path_provider for Windows + * Implements getTemporaryPath, getApplicationSupportPath, getLibraryPath, + getApplicationDocumentsPath and getDownloadsPath. diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index c4cc3e522831..c88ba72cdc50 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -3,7 +3,7 @@ description: Windows implementation of the path_provider plugin # 0.0.y+z is compatible with 1.0.0, if you land a breaking change bump # the version to 2.0.0. # See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0 -version: 0.0.1+0 +version: 0.0.1 homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows flutter: @@ -24,3 +24,5 @@ dependencies: dev_dependencies: pedantic: ^1.8.0 + flutter_test: + sdk: flutter From 306868e44bed2ddfb4a4d296e5482746c8408f8c Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 5 Jun 2020 12:16:34 -0700 Subject: [PATCH 08/39] Add manual registration of Windows plug-in --- packages/path_provider/path_provider/lib/path_provider.dart | 3 +++ packages/path_provider/path_provider_windows/pubspec.yaml | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/path_provider/path_provider/lib/path_provider.dart b/packages/path_provider/path_provider/lib/path_provider.dart index ae959b133094..e64163b0ba76 100644 --- a/packages/path_provider/path_provider/lib/path_provider.dart +++ b/packages/path_provider/path_provider/lib/path_provider.dart @@ -7,6 +7,7 @@ import 'dart:io' show Directory, Platform; import 'package:flutter/foundation.dart' show kIsWeb, visibleForTesting; import 'package:path_provider_linux/path_provider_linux.dart'; +import 'package:path_provider_windows/path_provider_windows.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; export 'package:path_provider_platform_interface/path_provider_platform_interface.dart' @@ -39,6 +40,8 @@ PathProviderPlatform get _platform { } if (!kIsWeb && Platform.isLinux && !_disablePlatformOverride) { __platform = PathProviderLinux(); + } else if (!kIsWeb && Platform.isWindows && !_disablePlatformOverride) { + __platform = PathProviderWindows(); } else { __platform = PathProviderPlatform.instance; } diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index c88ba72cdc50..dbc116688ad9 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -1,8 +1,5 @@ name: path_provider_windows description: Windows implementation of the path_provider plugin -# 0.0.y+z is compatible with 1.0.0, if you land a breaking change bump -# the version to 2.0.0. -# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0 version: 0.0.1 homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows @@ -11,6 +8,7 @@ flutter: platforms: windows: dartPluginClass: PathProviderPlugin + pluginClass: none environment: sdk: ">=2.1.0 <3.0.0" From cd0ea88d3072673e418bbd30c02859e8376db8dd Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 5 Jun 2020 19:29:55 -0700 Subject: [PATCH 09/39] Fix bug in pubspec --- packages/path_provider/path_provider_windows/pubspec.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index dbc116688ad9..bb4eed139e59 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -7,18 +7,19 @@ flutter: plugin: platforms: windows: - dartPluginClass: PathProviderPlugin + dartPluginClass: PathProviderWindows pluginClass: none environment: sdk: ">=2.1.0 <3.0.0" - flutter: ">=1.10.0 <2.0.0" + flutter: ">=1.12.13+hotfix.4 <2.0.0" dependencies: flutter: sdk: flutter path_provider_platform_interface: ^1.0.1 win32: ^1.5.1 + ffi: ^0.1.3 dev_dependencies: pedantic: ^1.8.0 From 0eba35662fe11eb44a8da80ebf618412aaf89f5a Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Sat, 6 Jun 2020 14:43:57 -0700 Subject: [PATCH 10/39] Tweaks --- .../path_provider/path_provider/pubspec.yaml | 8 ++--- .../path_provider_windows/LICENSE | 2 +- .../path_provider_windows/README.md | 17 +++------- .../example/lib/main.dart | 33 ++++++++++--------- .../lib/path_provider_windows.dart | 7 +--- .../path_provider_windows/pubspec.yaml | 16 ++++----- .../test/path_provider_windows_test.dart | 14 ++++---- 7 files changed, 42 insertions(+), 55 deletions(-) diff --git a/packages/path_provider/path_provider/pubspec.yaml b/packages/path_provider/path_provider/pubspec.yaml index 9fe9dce869c6..537cfb73c5d5 100644 --- a/packages/path_provider/path_provider/pubspec.yaml +++ b/packages/path_provider/path_provider/pubspec.yaml @@ -1,6 +1,5 @@ name: path_provider -description: Flutter plugin for getting commonly used locations on the Android & - iOS file systems, such as the temp and app data directories. +description: Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories. homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider version: 1.6.10 @@ -16,8 +15,6 @@ flutter: default_package: path_provider_macos linux: default_package: path_provider_linux - windows: - default_package: path_provider_windows dependencies: flutter: @@ -25,7 +22,8 @@ dependencies: path_provider_platform_interface: ^1.0.1 path_provider_macos: ^0.0.4 path_provider_linux: ^0.0.1 - path_provider_windows: ^0.0.1 + path_provider_windows: + path: ../path_provider_windows dev_dependencies: e2e: ^0.2.1 diff --git a/packages/path_provider/path_provider_windows/LICENSE b/packages/path_provider/path_provider_windows/LICENSE index 687fb4968920..7b995420294b 100644 --- a/packages/path_provider/path_provider_windows/LICENSE +++ b/packages/path_provider/path_provider_windows/LICENSE @@ -1,4 +1,4 @@ -Copyright 2020 The Chromium Authors. All rights reserved. +Copyright 2017 The Chromium Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/packages/path_provider/path_provider_windows/README.md b/packages/path_provider/path_provider_windows/README.md index 3ac99f3f86c6..2546d44663ef 100644 --- a/packages/path_provider/path_provider_windows/README.md +++ b/packages/path_provider/path_provider_windows/README.md @@ -1,6 +1,6 @@ # path_provider_windows -The Windows implementation of [`path_provider`]. +The Windows implementation of [`path_provider`][1]. **Please set your constraint to `path_provider_windows: '>=0.0.y+x <2.0.0'`** @@ -13,12 +13,9 @@ For more details see: https://github.com/flutter/flutter/wiki/Package-migration- ### Import the package -To use this plugin in your Flutter Windows app, simply add it as a dependency in -your `pubspec.yaml` alongside the base `path_provider` plugin. - -_(This is only temporary: in the future we hope to make this package an -"endorsed" implementation of `path_provider`, so that it is automatically -included in your Flutter macos app when you depend on `package:path_provider`.)_ +This package has been endorsed, meaning that you only need to add `path_provider` +as a dependency in your `pubspec.yaml`. It will be automatically included in your app +when you depend on `package:path_provider`. This is what the above means to your `pubspec.yaml`: @@ -27,11 +24,7 @@ This is what the above means to your `pubspec.yaml`: dependencies: ... path_provider: ^1.5.1 - path_provider_windows: ^0.0.1 ... ``` -### Use the plugin - -Once you have the `path_provider_windows` dependency in your pubspec, you should -be able to use `package:path_provider` as normal. +[1]:../ \ No newline at end of file diff --git a/packages/path_provider/path_provider_windows/example/lib/main.dart b/packages/path_provider/path_provider_windows/example/lib/main.dart index f76b6c552113..890b096bfe92 100644 --- a/packages/path_provider/path_provider_windows/example/lib/main.dart +++ b/packages/path_provider/path_provider_windows/example/lib/main.dart @@ -1,8 +1,13 @@ -import 'package:flutter/material.dart'; +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + import 'dart:async'; +import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:win32/win32.dart'; void main() async { runApp(MyApp()); @@ -32,33 +37,29 @@ class _MyAppState extends State { String downloadsDirectory; String appSupportDirectory; String documentsDirectory; - // Platform messages may fail, so we use a try/catch PlatformException. + try { tempDirectory = (await getTemporaryDirectory()).path; - } on WindowsException { - tempDirectory = 'Failed to get temp directory.'; + } catch (exception) { + tempDirectory = 'Failed to get temp directory: $exception'; } try { downloadsDirectory = (await getDownloadsDirectory()).path; - } on WindowsException { - downloadsDirectory = 'Failed to get downloads directory.'; + } catch (exception) { + downloadsDirectory = 'Failed to get downloads directory: $exception'; } try { documentsDirectory = (await getApplicationDocumentsDirectory()).path; - } on WindowsException { - documentsDirectory = 'Failed to get documents directory.'; + } catch (exception) { + documentsDirectory = 'Failed to get documents directory: $exception'; } try { appSupportDirectory = (await getApplicationSupportDirectory()).path; - } on WindowsException { - appSupportDirectory = 'Failed to get documents directory.'; + } catch (exception) { + appSupportDirectory = 'Failed to get app support directory: $exception'; } - // If the widget was removed from the tree while the asynchronous platform - // message was in flight, we want to discard the reply rather than calling - // setState to update our non-existent appearance. - if (!mounted) return; setState(() { _tempDirectory = tempDirectory; @@ -73,7 +74,7 @@ class _MyAppState extends State { return MaterialApp( home: Scaffold( appBar: AppBar( - title: const Text('Path Provider Windows example app'), + title: const Text('Path Provider example app'), ), body: Center( child: Column( diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index d231515b73e2..716985292aa2 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -14,11 +14,6 @@ import 'package:path_provider_windows/folders.dart'; /// /// This class implements the `package:path_provider` functionality for Windows class PathProviderWindows extends PathProviderPlatform { - /// Registers this class as the default instance of [PathProviderPlatform] - static void register() { - PathProviderPlatform.instance = PathProviderWindows(); - } - /// Path to the temporary directory on the device that is not backed up and is /// suitable for storing caches of downloaded files. /// @@ -36,7 +31,7 @@ class PathProviderWindows extends PathProviderPlatform { free(buffer); throw WindowsException('$error'); } else { - var path = buffer.unpackString(MAX_PATH); + var path = buffer.unpackString(length); // GetTempPath adds a trailing backslash, but SHGetKnownFolderPath does not. // Strip off trailing backslash for consistency with other methods here. diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index bb4eed139e59..bbc06c18d8f9 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -1,27 +1,27 @@ name: path_provider_windows description: Windows implementation of the path_provider plugin -version: 0.0.1 homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows +version: 0.0.1 flutter: plugin: platforms: windows: dartPluginClass: PathProviderWindows - pluginClass: none -environment: - sdk: ">=2.1.0 <3.0.0" - flutter: ">=1.12.13+hotfix.4 <2.0.0" dependencies: + path_provider_platform_interface: ^1.0.1 flutter: sdk: flutter - path_provider_platform_interface: ^1.0.1 - win32: ^1.5.1 ffi: ^0.1.3 + win32: ^1.5.1 dev_dependencies: - pedantic: ^1.8.0 flutter_test: sdk: flutter + pedantic: ^1.8.0 + +environment: + sdk: ">=2.1.0 <3.0.0" + flutter: ">=1.12.13+hotfix.4 <2.0.0" \ No newline at end of file diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index dba82250376e..7cbdd5e8901a 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -1,20 +1,20 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. +// Copyright 2017 The Chromium 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:flutter_test/flutter_test.dart'; import 'package:path_provider_windows/path_provider_windows.dart'; -import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - PathProviderWindows.register(); + PathProviderWindows pathProvider; - setUp(() {}); + setUp(() { + pathProvider = PathProviderWindows(); + }); tearDown(() {}); test('getTemporaryPath', () async { - final plugin = PathProviderPlatform.instance; - expect(await plugin.getTemporaryPath(), contains('C:\\')); + expect(await pathProvider.getTemporaryPath(), contains('C:\\')); }); } From 06bd98f9c83258f800c8ca3bcfb9a47e93f5ec28 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Sat, 6 Jun 2020 18:39:02 -0700 Subject: [PATCH 11/39] Remove windows folder --- .../path_provider_windows/CHANGELOG.md | 2 +- .../example/windows/.gitignore | 17 -- .../example/windows/AppConfiguration.props | 6 - .../example/windows/FlutterBuild.vcxproj | 50 ---- .../example/windows/Runner.sln | 43 --- .../example/windows/Runner.vcxproj | 262 ------------------ .../example/windows/Runner.vcxproj.filters | 88 ------ .../example/windows/flutter/.template_version | 1 - .../windows/flutter/GeneratedPlugins.props | 8 - .../flutter/generated_plugin_registrant.cc | 9 - .../flutter/generated_plugin_registrant.h | 13 - .../example/windows/runner/Runner.rc | 70 ----- .../example/windows/runner/flutter_window.cpp | 29 -- .../example/windows/runner/flutter_window.h | 37 --- .../example/windows/runner/main.cpp | 37 --- .../example/windows/runner/resource.h | 16 -- .../windows/runner/resources/app_icon.ico | Bin 33772 -> 0 bytes .../example/windows/runner/run_loop.cpp | 70 ----- .../example/windows/runner/run_loop.h | 40 --- .../windows/runner/runner.exe.manifest | 20 -- .../example/windows/runner/utils.cpp | 22 -- .../example/windows/runner/utils.h | 8 - .../example/windows/runner/win32_window.cpp | 249 ----------------- .../example/windows/runner/win32_window.h | 96 ------- .../windows/runner/window_configuration.cpp | 7 - .../windows/runner/window_configuration.h | 18 -- .../scripts/bundle_assets_and_deps.bat | 44 --- .../windows/scripts/prepare_dependencies.bat | 5 - .../path_provider_windows/pubspec.yaml | 2 +- 29 files changed, 2 insertions(+), 1267 deletions(-) delete mode 100644 packages/path_provider/path_provider_windows/example/windows/.gitignore delete mode 100644 packages/path_provider/path_provider_windows/example/windows/AppConfiguration.props delete mode 100644 packages/path_provider/path_provider_windows/example/windows/FlutterBuild.vcxproj delete mode 100644 packages/path_provider/path_provider_windows/example/windows/Runner.sln delete mode 100644 packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj delete mode 100644 packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj.filters delete mode 100644 packages/path_provider/path_provider_windows/example/windows/flutter/.template_version delete mode 100644 packages/path_provider/path_provider_windows/example/windows/flutter/GeneratedPlugins.props delete mode 100644 packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.cc delete mode 100644 packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.h delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/Runner.rc delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.cpp delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.h delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/main.cpp delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/resource.h delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/resources/app_icon.ico delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/run_loop.cpp delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/run_loop.h delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/runner.exe.manifest delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/utils.cpp delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/utils.h delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/win32_window.cpp delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/win32_window.h delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.cpp delete mode 100644 packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.h delete mode 100644 packages/path_provider/path_provider_windows/example/windows/scripts/bundle_assets_and_deps.bat delete mode 100644 packages/path_provider/path_provider_windows/example/windows/scripts/prepare_dependencies.bat diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md index b65e3aa46c99..0ff1ff86fb0f 100644 --- a/packages/path_provider/path_provider_windows/CHANGELOG.md +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.0.1 +## 0.0.1+1 * The initial implementation of path_provider for Windows * Implements getTemporaryPath, getApplicationSupportPath, getLibraryPath, diff --git a/packages/path_provider/path_provider_windows/example/windows/.gitignore b/packages/path_provider/path_provider_windows/example/windows/.gitignore deleted file mode 100644 index d492d0d98c8f..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -flutter/ephemeral/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ diff --git a/packages/path_provider/path_provider_windows/example/windows/AppConfiguration.props b/packages/path_provider/path_provider_windows/example/windows/AppConfiguration.props deleted file mode 100644 index 42b257ad7116..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/AppConfiguration.props +++ /dev/null @@ -1,6 +0,0 @@ - - - - example - - diff --git a/packages/path_provider/path_provider_windows/example/windows/FlutterBuild.vcxproj b/packages/path_provider/path_provider_windows/example/windows/FlutterBuild.vcxproj deleted file mode 100644 index 8ef93f9e7af8..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/FlutterBuild.vcxproj +++ /dev/null @@ -1,50 +0,0 @@ - - - - - Debug - x64 - - - Profile - x64 - - - Release - x64 - - - - 15.0 - {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} - Flutter Build - 10.0 - - - - v141 - v142 - - - - - - - - - - - - - - "$(ProjectDir)scripts\prepare_dependencies" $(Configuration) - Running Flutter backend build - force_to_run_every_time - - - - - - - - diff --git a/packages/path_provider/path_provider_windows/example/windows/Runner.sln b/packages/path_provider/path_provider_windows/example/windows/Runner.sln deleted file mode 100644 index 7bfc8e03b3a8..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/Runner.sln +++ /dev/null @@ -1,43 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29709.97 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Runner", "Runner.vcxproj", "{5A827760-CF8B-408A-99A3-B6C0AD2271E7}" - ProjectSection(ProjectDependencies) = postProject - {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} = {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Flutter Build", "FlutterBuild.vcxproj", "{6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Flutter Plugins", "Flutter Plugins", "{5C2E738A-1DD3-445A-AAC8-EEB9648DD07C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Profile|x64 = Profile|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Debug|x64.ActiveCfg = Debug|x64 - {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Debug|x64.Build.0 = Debug|x64 - {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Profile|x64.ActiveCfg = Profile|x64 - {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Profile|x64.Build.0 = Profile|x64 - {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Release|x64.ActiveCfg = Release|x64 - {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Release|x64.Build.0 = Release|x64 - {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Debug|x64.ActiveCfg = Debug|x64 - {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Debug|x64.Build.0 = Debug|x64 - {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Profile|x64.ActiveCfg = Profile|x64 - {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Profile|x64.Build.0 = Profile|x64 - {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Release|x64.ActiveCfg = Release|x64 - {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {B8A69CB0-A974-4774-9EBD-1E5EECACD186} - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - EndGlobalSection -EndGlobal \ No newline at end of file diff --git a/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj b/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj deleted file mode 100644 index af25405c44e4..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj +++ /dev/null @@ -1,262 +0,0 @@ - - - - - Debug - x64 - - - Profile - x64 - - - Release - x64 - - - - 15.0 - {5A827760-CF8B-408A-99A3-B6C0AD2271E7} - example - 10.0 - - - - Application - true - v141 - v142 - Unicode - - - Application - false - v141 - v142 - true - Unicode - - - Application - false - v141 - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\ - $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ - - - $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\ - $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ - - - $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\ - $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ - - - - Level4 - Disabled - true - true - $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) - _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) - true - 4100 - - - flutter_windows.dll.lib;%(AdditionalDependencies) - $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)" - - - Bundling dependencies - Dummy_Run_Always - - - - - - - Level4 - MaxSpeed - true - true - true - true - $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) - _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) - true - 4100 - - - true - true - flutter_windows.dll.lib;%(AdditionalDependencies) - $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)" - - - Bundling dependencies - Dummy_Run_Always - - - - - - - Level4 - MaxSpeed - true - true - true - true - $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) - _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) - true - 4100 - - - true - true - flutter_windows.dll.lib;%(AdditionalDependencies) - $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)" - - - Bundling dependencies - Dummy_Run_Always - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(SolutionDir) - - diff --git a/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj.filters b/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj.filters deleted file mode 100644 index 761db86287a2..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/Runner.vcxproj.filters +++ /dev/null @@ -1,88 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {2761a4b5-57b2-4d50-a677-d20ddc17a7f1} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\Client Wrapper - - - Source Files\Client Wrapper - - - Source Files\Client Wrapper - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - - - - Resource Files - - - - - Resource Files - - - diff --git a/packages/path_provider/path_provider_windows/example/windows/flutter/.template_version b/packages/path_provider/path_provider_windows/example/windows/flutter/.template_version deleted file mode 100644 index 00750edc07d6..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/flutter/.template_version +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/packages/path_provider/path_provider_windows/example/windows/flutter/GeneratedPlugins.props b/packages/path_provider/path_provider_windows/example/windows/flutter/GeneratedPlugins.props deleted file mode 100644 index d3d26c72fbc5..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/flutter/GeneratedPlugins.props +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.cc b/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 4bfa0f3a3a75..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,9 +0,0 @@ -// -// Generated file. Do not edit. -// - -#include "generated_plugin_registrant.h" - - -void RegisterPlugins(flutter::PluginRegistry* registry) { -} diff --git a/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.h b/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index 9846246b4dac..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// Generated file. Do not edit. -// - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/Runner.rc b/packages/path_provider/path_provider_windows/example/windows/runner/Runner.rc deleted file mode 100644 index 5b41a82a4074..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/Runner.rc +++ /dev/null @@ -1,70 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.cpp deleted file mode 100644 index fe980cf8d12b..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "flutter_window.h" - -#include "flutter/generated_plugin_registrant.h" - -FlutterWindow::FlutterWindow(RunLoop* run_loop, - const flutter::DartProject& project) - : run_loop_(run_loop), project_(project) {} - -FlutterWindow::~FlutterWindow() {} - -void FlutterWindow::OnCreate() { - Win32Window::OnCreate(); - - // The size here is arbitrary since SetChildContent will resize it. - flutter_controller_ = - std::make_unique(100, 100, project_); - RegisterPlugins(flutter_controller_.get()); - run_loop_->RegisterFlutterInstance(flutter_controller_.get()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); -} - -void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - run_loop_->UnregisterFlutterInstance(flutter_controller_.get()); - flutter_controller_ = nullptr; - } - - Win32Window::OnDestroy(); -} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.h b/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.h deleted file mode 100644 index 4f41e16f1c95..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/flutter_window.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef FLUTTER_WINDOW_H_ -#define FLUTTER_WINDOW_H_ - -#include -#include - -#include "run_loop.h" -#include "win32_window.h" - -#include - -// A window that does nothing but host a Flutter view. -class FlutterWindow : public Win32Window { - public: - // Creates a new FlutterWindow driven by the |run_loop|, hosting a - // Flutter view running |project|. - explicit FlutterWindow(RunLoop* run_loop, - const flutter::DartProject& project); - virtual ~FlutterWindow(); - - protected: - // Win32Window: - void OnCreate() override; - void OnDestroy() override; - - private: - // The run loop driving events for this window. - RunLoop* run_loop_; - - // The project to run. - flutter::DartProject project_; - - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; -}; - -#endif // FLUTTER_WINDOW_H_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/main.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/main.cpp deleted file mode 100644 index 11b48e95738b..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/main.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -#include "flutter_window.h" -#include "run_loop.h" -#include "utils.h" -#include "window_configuration.h" - -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - RunLoop run_loop; - - flutter::DartProject project(L"data"); - FlutterWindow window(&run_loop, project); - Win32Window::Point origin(kFlutterWindowOriginX, kFlutterWindowOriginY); - Win32Window::Size size(kFlutterWindowWidth, kFlutterWindowHeight); - if (!window.CreateAndShow(kFlutterWindowTitle, origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - run_loop.Run(); - - ::CoUninitialize(); - return EXIT_SUCCESS; -} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/resource.h b/packages/path_provider/path_provider_windows/example/windows/runner/resource.h deleted file mode 100644 index 66a65d1e4a79..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Runner.rc -// -#define IDI_APP_ICON 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/resources/app_icon.ico b/packages/path_provider/path_provider_windows/example/windows/runner/resources/app_icon.ico deleted file mode 100644 index c04e20caf6370ebb9253ad831cc31de4a9c965f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33772 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 diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.cpp deleted file mode 100644 index f91d6d4cb91b..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "run_loop.h" - -#include -// Don't stomp std::min/std::max -#undef max -#undef min - -#include - -RunLoop::RunLoop() {} - -RunLoop::~RunLoop() {} - -void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - } -} - -void RunLoop::RegisterFlutterInstance( - flutter::FlutterViewController* flutter_instance) { - flutter_instances_.insert(flutter_instance); -} - -void RunLoop::UnregisterFlutterInstance( - flutter::FlutterViewController* flutter_instance) { - flutter_instances_.erase(flutter_instance); -} - -RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { - TimePoint next_event_time = TimePoint::max(); - for (auto flutter_controller : flutter_instances_) { - std::chrono::nanoseconds wait_duration = - flutter_controller->ProcessMessages(); - if (wait_duration != std::chrono::nanoseconds::max()) { - next_event_time = - std::min(next_event_time, TimePoint::clock::now() + wait_duration); - } - } - return next_event_time; -} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.h b/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.h deleted file mode 100644 index 442a58e5622b..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/run_loop.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef RUN_LOOP_H_ -#define RUN_LOOP_H_ - -#include - -#include -#include - -// A runloop that will service events for Flutter instances as well -// as native messages. -class RunLoop { - public: - RunLoop(); - ~RunLoop(); - - // Prevent copying - RunLoop(RunLoop const&) = delete; - RunLoop& operator=(RunLoop const&) = delete; - - // Runs the run loop until the application quits. - void Run(); - - // Registers the given Flutter instance for event servicing. - void RegisterFlutterInstance( - flutter::FlutterViewController* flutter_instance); - - // Unregisters the given Flutter instance from event servicing. - void UnregisterFlutterInstance( - flutter::FlutterViewController* flutter_instance); - - private: - using TimePoint = std::chrono::steady_clock::time_point; - - // Processes all currently pending messages for registered Flutter instances. - TimePoint ProcessFlutterMessages(); - - std::set flutter_instances_; -}; - -#endif // RUN_LOOP_H_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/runner.exe.manifest b/packages/path_provider/path_provider_windows/example/windows/runner/runner.exe.manifest deleted file mode 100644 index c977c4a42589..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/runner.exe.manifest +++ /dev/null @@ -1,20 +0,0 @@ - - - - - PerMonitorV2 - - - - - - - - - - - - - - - diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/utils.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/utils.cpp deleted file mode 100644 index 37501e5db777..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/utils.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include - -void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); - } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } -} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/utils.h b/packages/path_provider/path_provider_windows/example/windows/runner/utils.h deleted file mode 100644 index d247a66308b4..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/utils.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CONSOLE_UTILS_H_ -#define CONSOLE_UTILS_H_ - -// Creates a console for the process, and redirects stdout and stderr to -// it for both the runner and the Flutter library. -void CreateAndAttachConsole(); - -#endif // CONSOLE_UTILS_H_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.cpp deleted file mode 100644 index 677a9a6cca8e..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.cpp +++ /dev/null @@ -1,249 +0,0 @@ -#include "win32_window.h" - -#include - -#include "resource.h" - -namespace { - -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; - -// The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; - -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); - -// Scale helper to convert logical scaler values to physical using passed in -// scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} - -// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. -// This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { - return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); - } -} - -} // namespace - -// Manages the Win32Window's window class registration. -class WindowClassRegistrar { - public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registar instance. - static WindowClassRegistrar* GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); - } - return instance_; - } - - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t* GetWindowClass(); - - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); - - private: - WindowClassRegistrar() = default; - - static WindowClassRegistrar* instance_; - - bool class_registered_ = false; -}; - -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; - -const wchar_t* WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; -} - -void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; -} - -Win32Window::Win32Window() { - ++g_active_window_count; -} - -Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); -} - -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { - Destroy(); - - const wchar_t* window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); - - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; - - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); - - OnCreate(); - - return window != nullptr; -} - -// static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - auto window = - reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); - - if (window == nullptr) { - return 0; - } - - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: - RECT rect; - GetClientRect(hwnd, &rect); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - - // Messages that are directly forwarded to embedding. - case WM_FONTCHANGE: - SendMessage(child_content_, WM_FONTCHANGE, NULL, NULL); - return 0; - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -void Win32Window::Destroy() { - OnDestroy(); - - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame; - GetClientRect(window_handle_, &frame); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); - - SetFocus(child_content_); -} - -HWND Win32Window::GetHandle() { - return window_handle_; -} - -void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; -} - -void Win32Window::OnCreate() { - // No-op; provided for subclasses. -} - -void Win32Window::OnDestroy() { - // No-op; provided for subclasses. -} diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.h b/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.h deleted file mode 100644 index 5cbb5d594d69..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/win32_window.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef WIN32_WINDOW_H_ -#define WIN32_WINDOW_H_ - -#include -#include - -#include -#include -#include - -// A class abstraction for a high DPI-aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling -class Win32Window { - public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates and shows a win32 window with |title| and position and size using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Called when CreateAndShow is called, allowing subclass window-related - // setup. - virtual void OnCreate(); - - // Called when Destroy is called. - virtual void OnDestroy(); - - private: - friend class WindowClassRegistrar; - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - - bool quit_on_close_ = false; - - // window handle for top level window. - HWND window_handle_ = nullptr; - - // window handle for hosted content. - HWND child_content_ = nullptr; -}; - -#endif // WIN32_WINDOW_H_ diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.cpp b/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.cpp deleted file mode 100644 index c56ede18175e..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "window_configuration.h" - -const wchar_t* kFlutterWindowTitle = L"example"; -const unsigned int kFlutterWindowOriginX = 10; -const unsigned int kFlutterWindowOriginY = 10; -const unsigned int kFlutterWindowWidth = 1280; -const unsigned int kFlutterWindowHeight = 720; diff --git a/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.h b/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.h deleted file mode 100644 index ea5cead43c4b..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/runner/window_configuration.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef WINDOW_CONFIGURATION_ -#define WINDOW_CONFIGURATION_ - -// This is a temporary approach to isolate changes that people are likely to -// make to main.cpp, where the APIs are still in flux. This will reduce the -// need to resolve conflicts or re-create changes slightly differently every -// time the Windows Flutter API surface changes. -// -// Longer term there should be simpler configuration options for common -// customizations like this, without requiring native code changes. - -extern const wchar_t* kFlutterWindowTitle; -extern const unsigned int kFlutterWindowOriginX; -extern const unsigned int kFlutterWindowOriginY; -extern const unsigned int kFlutterWindowWidth; -extern const unsigned int kFlutterWindowHeight; - -#endif // WINDOW_CONFIGURATION_ diff --git a/packages/path_provider/path_provider_windows/example/windows/scripts/bundle_assets_and_deps.bat b/packages/path_provider/path_provider_windows/example/windows/scripts/bundle_assets_and_deps.bat deleted file mode 100644 index 9efa28f8e72a..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/scripts/bundle_assets_and_deps.bat +++ /dev/null @@ -1,44 +0,0 @@ -@echo off - -set FLUTTER_CACHE_DIR=%~1 -set BUNDLE_DIR=%~2 -set PLUGIN_DIR=%~3 -set EXE_NAME=%~4 -set BUILD_MODE=%~5 - -set DATA_DIR=%BUNDLE_DIR%data - -if not exist "%DATA_DIR%" call mkdir "%DATA_DIR%" -if %errorlevel% neq 0 exit /b %errorlevel% - -:: Write the executable name to the location expected by the Flutter tool. -echo %EXE_NAME%>"%FLUTTER_CACHE_DIR%exe_filename" - -:: Copy the Flutter assets to the data directory. -set FLUTTER_BUILD_DIR=%~dp0..\..\build\ -set ASSET_DIR_NAME=flutter_assets -set TARGET_ASSET_DIR=%DATA_DIR%\%ASSET_DIR_NAME% -if exist "%TARGET_ASSET_DIR%" call rmdir /s /q "%TARGET_ASSET_DIR%" -if %errorlevel% neq 0 exit /b %errorlevel% -call xcopy /s /e /i /q "%FLUTTER_BUILD_DIR%%ASSET_DIR_NAME%" "%TARGET_ASSET_DIR%" -if %errorlevel% neq 0 exit /b %errorlevel% - -:: Copy the icudtl.dat file from the Flutter tree to the data directory. -call xcopy /y /d /q "%FLUTTER_CACHE_DIR%icudtl.dat" "%DATA_DIR%" -if %errorlevel% neq 0 exit /b %errorlevel% - -:: For non-debug modes, copy app.so into the data directory. -if not %BUILD_MODE% == "Debug" ( - call xcopy /y /d /q "%FLUTTER_BUILD_DIR%windows\app.so" "%DATA_DIR%" - if %errorlevel% neq 0 exit /b %errorlevel% -) - -:: Copy the Flutter DLL to the target location. -call xcopy /y /d /q "%FLUTTER_CACHE_DIR%flutter_windows.dll" "%BUNDLE_DIR%" -if %errorlevel% neq 0 exit /b %errorlevel% - -:: Copy any Plugin DLLs to the target location. -if exist "%PLUGIN_DIR%" ( - call xcopy /y /d /q "%PLUGIN_DIR%"*.dll "%BUNDLE_DIR%" - if %errorlevel% neq 0 exit /b %errorlevel% -) diff --git a/packages/path_provider/path_provider_windows/example/windows/scripts/prepare_dependencies.bat b/packages/path_provider/path_provider_windows/example/windows/scripts/prepare_dependencies.bat deleted file mode 100644 index d05238be3fcb..000000000000 --- a/packages/path_provider/path_provider_windows/example/windows/scripts/prepare_dependencies.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -:: Run flutter tool backend. -set BUILD_MODE=%~1 -"%FLUTTER_ROOT%\packages\flutter_tools\bin\tool_backend" windows-x64 %BUILD_MODE% diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index bbc06c18d8f9..1b97c248835c 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -1,7 +1,7 @@ name: path_provider_windows description: Windows implementation of the path_provider plugin homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows -version: 0.0.1 +version: 0.0.1+1 flutter: plugin: From 383ef8fcbc1b9e030d10f1db1661f23ab8360d0c Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Sat, 6 Jun 2020 18:41:31 -0700 Subject: [PATCH 12/39] Add missing copyright comment --- .../path_provider/path_provider_windows/example/lib/main.dart | 2 +- packages/path_provider/path_provider_windows/lib/folders.dart | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/path_provider/path_provider_windows/example/lib/main.dart b/packages/path_provider/path_provider_windows/example/lib/main.dart index 890b096bfe92..5f0881bef2bb 100644 --- a/packages/path_provider/path_provider_windows/example/lib/main.dart +++ b/packages/path_provider/path_provider_windows/example/lib/main.dart @@ -1,4 +1,4 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/packages/path_provider/path_provider_windows/lib/folders.dart b/packages/path_provider/path_provider_windows/lib/folders.dart index f0d0e4bbae4b..fc2ea8351476 100644 --- a/packages/path_provider/path_provider_windows/lib/folders.dart +++ b/packages/path_provider/path_provider_windows/lib/folders.dart @@ -1,3 +1,7 @@ +// Copyright 2020 The Chromium 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:win32/win32.dart'; /// A class containing the GUID references for each of the documented Windows From ad0c2b935eb7eb8756aec4cb5c6f90b359d96924 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Sat, 6 Jun 2020 18:44:41 -0700 Subject: [PATCH 13/39] More minor copyright tweaks --- packages/path_provider/path_provider_windows/pubspec.yaml | 3 ++- .../path_provider_windows/test/path_provider_windows_test.dart | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 1b97c248835c..2280b057b368 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -24,4 +24,5 @@ dev_dependencies: environment: sdk: ">=2.1.0 <3.0.0" - flutter: ">=1.12.13+hotfix.4 <2.0.0" \ No newline at end of file + flutter: ">=1.12.13+hotfix.4 <2.0.0" + \ No newline at end of file diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index 7cbdd5e8901a..ab3c1f6438e1 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -1,4 +1,4 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. From f264046ba77f3430999d41f24be97dc04b036a16 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Tue, 16 Jun 2020 21:57:52 -0700 Subject: [PATCH 14/39] Add warning --- packages/path_provider/path_provider_windows/README.md | 2 ++ .../path_provider_windows/lib/path_provider_windows.dart | 6 ++---- packages/path_provider/path_provider_windows/pubspec.yaml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/path_provider/path_provider_windows/README.md b/packages/path_provider/path_provider_windows/README.md index 2546d44663ef..488d2998c9d1 100644 --- a/packages/path_provider/path_provider_windows/README.md +++ b/packages/path_provider/path_provider_windows/README.md @@ -2,6 +2,8 @@ The Windows implementation of [`path_provider`][1]. +*This is not an official package, and is not ready for use!* + **Please set your constraint to `path_provider_windows: '>=0.0.y+x <2.0.0'`** ## Backward compatible 1.0.0 version is coming diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 716985292aa2..65815674a6e0 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -29,7 +29,7 @@ class PathProviderWindows extends PathProviderPlatform { if (length == 0) { final error = GetLastError(); free(buffer); - throw WindowsException('$error'); + throw WindowsException(error); } else { var path = buffer.unpackString(length); @@ -78,9 +78,7 @@ class PathProviderWindows extends PathProviderPlatform { if (FAILED(hr)) { if (hr == E_INVALIDARG || hr == E_FAIL) { - throw WindowsException('Invalid folder.'); - } else { - throw WindowsException('Unknown error.'); + throw WindowsException(hr); } } diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 2280b057b368..ab19271231b0 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -1,7 +1,7 @@ name: path_provider_windows description: Windows implementation of the path_provider plugin homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows -version: 0.0.1+1 +version: 0.0.1+2 flutter: plugin: @@ -15,7 +15,7 @@ dependencies: flutter: sdk: flutter ffi: ^0.1.3 - win32: ^1.5.1 + win32: ^1.6.2 dev_dependencies: flutter_test: From 03a126e30a0c79a3af748277042b6f3c286d890e Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Tue, 16 Jun 2020 21:58:26 -0700 Subject: [PATCH 15/39] Bump changelog --- packages/path_provider/path_provider_windows/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md index 0ff1ff86fb0f..b0eca64fc4ed 100644 --- a/packages/path_provider/path_provider_windows/CHANGELOG.md +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.0.1+1 +## 0.0.1+2 * The initial implementation of path_provider for Windows * Implements getTemporaryPath, getApplicationSupportPath, getLibraryPath, From 5057d4784dbd47cf5610fd2bc1725334d0d5f6f4 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 4 Sep 2020 14:21:19 -0700 Subject: [PATCH 16/39] Wrap pointer allocation in try/free --- .../path_provider_windows/README.md | 3 +- .../lib/path_provider_windows.dart | 62 +++++++++++-------- .../path_provider_windows/pubspec.yaml | 4 +- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/packages/path_provider/path_provider_windows/README.md b/packages/path_provider/path_provider_windows/README.md index 488d2998c9d1..fc9b9eba8956 100644 --- a/packages/path_provider/path_provider_windows/README.md +++ b/packages/path_provider/path_provider_windows/README.md @@ -2,11 +2,10 @@ The Windows implementation of [`path_provider`][1]. -*This is not an official package, and is not ready for use!* - **Please set your constraint to `path_provider_windows: '>=0.0.y+x <2.0.0'`** ## Backward compatible 1.0.0 version is coming + The plugin has reached a stable API, we guarantee that version `1.0.0` will be backward compatible with `0.0.y+z`. Please use `path_provider_windows: '>=0.0.y+x <2.0.0'` as your dependency constraint to allow a smoother ecosystem migration. For more details see: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0 diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 65815674a6e0..3e5307a251d5 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -24,22 +24,27 @@ class PathProviderWindows extends PathProviderPlatform { @override Future getTemporaryPath() { final buffer = allocate(count: MAX_PATH + 1).cast(); - final length = GetTempPath(MAX_PATH, buffer); + String path; - if (length == 0) { - final error = GetLastError(); - free(buffer); - throw WindowsException(error); - } else { - var path = buffer.unpackString(length); + try { + final length = GetTempPath(MAX_PATH, buffer); + + if (length == 0) { + final error = GetLastError(); + free(buffer); + throw WindowsException(error); + } else { + path = buffer.unpackString(length); - // GetTempPath adds a trailing backslash, but SHGetKnownFolderPath does not. - // Strip off trailing backslash for consistency with other methods here. - if (path[path.length - 1] == '\\') { - path = path.substring(0, path.length - 1); + // GetTempPath adds a trailing backslash, but SHGetKnownFolderPath does not. + // Strip off trailing backslash for consistency with other methods here. + if (path[path.length - 1] == '\\') { + path = path.substring(0, path.length - 1); + } } - free(buffer); return Future.value(path); + } finally { + free(buffer); } } @@ -70,24 +75,27 @@ class PathProviderWindows extends PathProviderPlatform { /// folderID is a GUID that represents a specific known folder ID, drawn from /// [WindowsKnownFolder]. Future getPath(String folderID) { - GUID knownFolderID = GUID.fromString(folderID); - Pointer pathPtrPtr = allocate(); - - final hr = SHGetKnownFolderPath( - knownFolderID.addressOf, KF_FLAG_DEFAULT, NULL, pathPtrPtr); + final pathPtrPtr = allocate(); + Pointer pathPtr; - if (FAILED(hr)) { - if (hr == E_INVALIDARG || hr == E_FAIL) { - throw WindowsException(hr); - } - } + try { + GUID knownFolderID = GUID.fromString(folderID); - final pathPtr = Pointer.fromAddress(pathPtrPtr.value); - final path = pathPtr.unpackString(MAX_PATH); + final hr = SHGetKnownFolderPath( + knownFolderID.addressOf, KF_FLAG_DEFAULT, NULL, pathPtrPtr); - CoTaskMemFree(pathPtr.cast()); - free(pathPtrPtr); + if (FAILED(hr)) { + if (hr == E_INVALIDARG || hr == E_FAIL) { + throw WindowsException(hr); + } + } - return Future.value(path); + pathPtr = Pointer.fromAddress(pathPtrPtr.value); + final path = pathPtr.unpackString(MAX_PATH); + return Future.value(path); + } finally { + CoTaskMemFree(pathPtr.cast()); + free(pathPtrPtr); + } } } diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index ab19271231b0..1fada0e039fd 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -11,11 +11,11 @@ flutter: dependencies: - path_provider_platform_interface: ^1.0.1 + path_provider_platform_interface: ^1.0.3 flutter: sdk: flutter ffi: ^0.1.3 - win32: ^1.6.2 + win32: ^1.6.10 dev_dependencies: flutter_test: From 37eba73999d5538214482f81c8905f1266cf0d36 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 4 Sep 2020 14:25:28 -0700 Subject: [PATCH 17/39] path endsWith --- .../path_provider_windows/lib/path_provider_windows.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 3e5307a251d5..f5eb675ed54c 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -38,7 +38,7 @@ class PathProviderWindows extends PathProviderPlatform { // GetTempPath adds a trailing backslash, but SHGetKnownFolderPath does not. // Strip off trailing backslash for consistency with other methods here. - if (path[path.length - 1] == '\\') { + if (path.endsWith('\\')) { path = path.substring(0, path.length - 1); } } From a3a2d41f88a3e77fc86b2d3f231b5ae30b9a842a Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Fri, 4 Sep 2020 14:46:50 -0700 Subject: [PATCH 18/39] Trim back comment on TEMP environment variable --- .../path_provider_windows/lib/path_provider_windows.dart | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index f5eb675ed54c..65004cbfabce 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -15,12 +15,8 @@ import 'package:path_provider_windows/folders.dart'; /// This class implements the `package:path_provider` functionality for Windows class PathProviderWindows extends PathProviderPlatform { /// Path to the temporary directory on the device that is not backed up and is - /// suitable for storing caches of downloaded files. - /// - /// On Windows, this the path specified by the TMP environment variable, or - /// the TEMP environment variable, or the USERPROFILE environment variable, - /// or the Windows directory, in order of preference. Windows does not - /// guarantee that the path exists or is writeable to. + /// suitable for storing caches of downloaded files. This is typically the + /// same as the TMP environment variable. @override Future getTemporaryPath() { final buffer = allocate(count: MAX_PATH + 1).cast(); From 6048f43f69881c964d088d1b5ab1226db6717ce5 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 07:02:18 -0700 Subject: [PATCH 19/39] Switch to the improved manual Dart registration used in shared_preferences --- .../path_provider/path_provider/README.md | 9 +--- .../path_provider/lib/path_provider.dart | 49 ++++++++----------- .../test/path_provider_test.dart | 4 -- 3 files changed, 22 insertions(+), 40 deletions(-) diff --git a/packages/path_provider/path_provider/README.md b/packages/path_provider/path_provider/README.md index 982a9f49cae5..e8d97e0106a3 100644 --- a/packages/path_provider/path_provider/README.md +++ b/packages/path_provider/path_provider/README.md @@ -23,14 +23,7 @@ Please see the example app of this plugin for a full example. ### Usage in tests -`path_provider` now uses a `PlatformInterface`, meaning that not all platforms share the a single `PlatformChannel`-based implementation. +`path_provider` now uses a `PlatformInterface`, meaning that not all platforms share the a single `PlatformChannel`-based implementation. With that change, tests should be updated to mock `PathProviderPlatform` rather than `PlatformChannel`. See this `path_provider` [test](https://github.com/flutter/plugins/blob/master/packages/path_provider/path_provider/test/path_provider_test.dart) for an example. - -You will also have to temporarily add the following line to the setup of your test. -```dart -disablePathProviderPlatformOverride = true; -``` - -See this [issue](https://github.com/flutter/flutter/issues/52267), for more details on why this is needed. \ No newline at end of file diff --git a/packages/path_provider/path_provider/lib/path_provider.dart b/packages/path_provider/path_provider/lib/path_provider.dart index e64163b0ba76..9c44f063c4ef 100644 --- a/packages/path_provider/path_provider/lib/path_provider.dart +++ b/packages/path_provider/path_provider/lib/path_provider.dart @@ -9,43 +9,36 @@ import 'package:flutter/foundation.dart' show kIsWeb, visibleForTesting; import 'package:path_provider_linux/path_provider_linux.dart'; import 'package:path_provider_windows/path_provider_windows.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; +import 'package:path_provider_platform_interface/src/method_channel_path_provider.dart'; export 'package:path_provider_platform_interface/path_provider_platform_interface.dart' show StorageDirectory; -/// Disables platform override in order to use a manually registered [PathProviderPlatform], only for testing right now -/// -/// Make sure to disable the override before using any of the `path_provider` methods -/// To use your own [PathProviderPlatform], make sure to include the following lines -/// ``` -/// PathProviderPlatform.instance = YourPathProviderPlatform(); -/// disablePathProviderPlatformOverride = true; -/// // Use the `path_provider` methods: -/// final dir = await getTemporaryDirectory(); -/// ``` -/// See this issue https://github.com/flutter/flutter/issues/52267 for why this is required @visibleForTesting -set disablePathProviderPlatformOverride(bool override) { - _disablePlatformOverride = override; -} +@Deprecated('This is no longer necessary, and is now a no-op') +set disablePathProviderPlatformOverride(bool override) {} -bool _disablePlatformOverride = false; -PathProviderPlatform __platform; +bool _manualDartRegistrationNeeded = true; -// This is to manually endorse the linux path provider until automatic registration of dart plugins is implemented. -// See this issue https://github.com/flutter/flutter/issues/52267 for details PathProviderPlatform get _platform { - if (__platform != null) { - return __platform; - } - if (!kIsWeb && Platform.isLinux && !_disablePlatformOverride) { - __platform = PathProviderLinux(); - } else if (!kIsWeb && Platform.isWindows && !_disablePlatformOverride) { - __platform = PathProviderWindows(); - } else { - __platform = PathProviderPlatform.instance; + // This is to manually endorse Dart implementations until automatic + // registration of Dart plugins is implemented. For details see + // https://github.com/flutter/flutter/issues/52267. + if (_manualDartRegistrationNeeded) { + // Only do the initial registration if it hasn't already been overridden + // with a non-default instance. + if (!kIsWeb && + PathProviderPlatform.instance is MethodChannelPathProvider) { + if (Platform.isLinux) { + PathProviderPlatform.instance = PathProviderLinux(); + } else if (Platform.isWindows) { + PathProviderPlatform.instance = PathProviderWindows(); + } + } + _manualDartRegistrationNeeded = false; } - return __platform; + + return PathProviderPlatform.instance; } /// Path to the temporary directory on the device that is not backed up and is diff --git a/packages/path_provider/path_provider/test/path_provider_test.dart b/packages/path_provider/path_provider/test/path_provider_test.dart index 90a996fd68c8..eb17178b9975 100644 --- a/packages/path_provider/path_provider/test/path_provider_test.dart +++ b/packages/path_provider/path_provider/test/path_provider_test.dart @@ -25,10 +25,6 @@ void main() { setUp(() async { PathProviderPlatform.instance = MockPathProviderPlatform(); - // This is required because we manually register the Linux path provider when on the Linux platform. - // Will be removed when automatic registration of dart plugins is implemented. - // See this issue https://github.com/flutter/flutter/issues/52267 for details - disablePathProviderPlatformOverride = true; }); test('getTemporaryDirectory', () async { From 30ef5379fa0cb741e1873938e98a0c2e22ad02a4 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 07:04:15 -0700 Subject: [PATCH 20/39] Fix endorsement --- packages/path_provider/path_provider/pubspec.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/path_provider/pubspec.yaml b/packages/path_provider/path_provider/pubspec.yaml index 6c265da31acf..bb727c080963 100644 --- a/packages/path_provider/path_provider/pubspec.yaml +++ b/packages/path_provider/path_provider/pubspec.yaml @@ -15,6 +15,8 @@ flutter: default_package: path_provider_macos linux: default_package: path_provider_linux + windows: + default_package: path_provider_windows dependencies: flutter: @@ -22,8 +24,7 @@ dependencies: path_provider_platform_interface: ^1.0.1 path_provider_macos: ^0.0.4 path_provider_linux: ^0.0.1 - path_provider_windows: - path: ../path_provider_windows + path_provider_windows: ^0.0.1 dev_dependencies: integration_test: From ca07f04b2d574cf7cefee92960813d4c802974de Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 07:05:48 -0700 Subject: [PATCH 21/39] Version bump for endorsement --- packages/path_provider/path_provider/CHANGELOG.md | 4 ++++ packages/path_provider/path_provider/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/path_provider/path_provider/CHANGELOG.md b/packages/path_provider/path_provider/CHANGELOG.md index 07778d5ccef3..e66228f5bc96 100644 --- a/packages/path_provider/path_provider/CHANGELOG.md +++ b/packages/path_provider/path_provider/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.15 + +* Endorse Windows implementation. + ## 1.6.14 * Update package:e2e -> package:integration_test diff --git a/packages/path_provider/path_provider/pubspec.yaml b/packages/path_provider/path_provider/pubspec.yaml index bb727c080963..982186a5354c 100644 --- a/packages/path_provider/path_provider/pubspec.yaml +++ b/packages/path_provider/path_provider/pubspec.yaml @@ -1,7 +1,7 @@ name: path_provider description: Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories. homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider -version: 1.6.14 +version: 1.6.15 flutter: plugin: From 41c704e91b9482d90e2e1cfa46ec56f9bab200dd Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 07:07:34 -0700 Subject: [PATCH 22/39] Use newer format license --- .../path_provider_windows/LICENSE | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/packages/path_provider/path_provider_windows/LICENSE b/packages/path_provider/path_provider_windows/LICENSE index 7b995420294b..a6d6c0749818 100644 --- a/packages/path_provider/path_provider_windows/LICENSE +++ b/packages/path_provider/path_provider_windows/LICENSE @@ -1,27 +1,25 @@ Copyright 2017 The Chromium Authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From d017a2049a1e3f5596afaaa7716da288131f8a34 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 07:10:30 -0700 Subject: [PATCH 23/39] Update README for path_provider_windows to have correct path_provider version --- packages/path_provider/path_provider_windows/CHANGELOG.md | 4 ++++ packages/path_provider/path_provider_windows/pubspec.yaml | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md index b0eca64fc4ed..f1fef36649e3 100644 --- a/packages/path_provider/path_provider_windows/CHANGELOG.md +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.1+3 + +* README update for endorsement. + ## 0.0.1+2 * The initial implementation of path_provider for Windows diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 1fada0e039fd..e8111bc08ea2 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -1,7 +1,7 @@ name: path_provider_windows description: Windows implementation of the path_provider plugin homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows -version: 0.0.1+2 +version: 0.0.1+3 flutter: plugin: @@ -25,4 +25,3 @@ dev_dependencies: environment: sdk: ">=2.1.0 <3.0.0" flutter: ">=1.12.13+hotfix.4 <2.0.0" - \ No newline at end of file From 22afc788d9660d64b593e8adf8b0884c5adf9722 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 07:13:44 -0700 Subject: [PATCH 24/39] Dependency fixes in example --- .../path_provider/path_provider_windows/example/pubspec.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/path_provider/path_provider_windows/example/pubspec.yaml b/packages/path_provider/path_provider_windows/example/pubspec.yaml index cd272be76dff..68b7d44a3a1b 100644 --- a/packages/path_provider/path_provider_windows/example/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/example/pubspec.yaml @@ -5,6 +5,8 @@ dependencies: flutter: sdk: flutter path_provider: any + +dependency_overrides: path_provider_windows: path: ../ From bd11efc157929b431e8628d3598ac347743a47e8 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 08:05:34 -0700 Subject: [PATCH 25/39] Comment cleanup, remove getLibraryPath, make applitionSupportPath consistent with FDE (with temp placeholder for needed win32 API --- .../path_provider/path_provider/CHANGELOG.md | 1 + .../lib/path_provider_windows.dart | 39 +++++++++---------- .../path_provider_windows/pubspec.yaml | 1 + 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/path_provider/path_provider/CHANGELOG.md b/packages/path_provider/path_provider/CHANGELOG.md index e66228f5bc96..31f7fa005adb 100644 --- a/packages/path_provider/path_provider/CHANGELOG.md +++ b/packages/path_provider/path_provider/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.6.15 * Endorse Windows implementation. +* Remove the need to call disablePathProviderPlatformOverride in tests ## 1.6.14 diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 65004cbfabce..d935b45e1782 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -3,20 +3,19 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:io'; import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'package:win32/win32.dart'; +import 'package:path/path.dart' as path; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; import 'package:path_provider_windows/folders.dart'; /// The Windows implementation of [PathProviderPlatform] /// -/// This class implements the `package:path_provider` functionality for Windows +/// This class implements the `package:path_provider` functionality for Windows. class PathProviderWindows extends PathProviderPlatform { - /// Path to the temporary directory on the device that is not backed up and is - /// suitable for storing caches of downloaded files. This is typically the - /// same as the TMP environment variable. @override Future getTemporaryPath() { final buffer = allocate(count: MAX_PATH + 1).cast(); @@ -27,13 +26,13 @@ class PathProviderWindows extends PathProviderPlatform { if (length == 0) { final error = GetLastError(); - free(buffer); throw WindowsException(error); } else { path = buffer.unpackString(length); - // GetTempPath adds a trailing backslash, but SHGetKnownFolderPath does not. - // Strip off trailing backslash for consistency with other methods here. + // GetTempPath adds a trailing backslash, but SHGetKnownFolderPath does + // not. Strip off trailing backslash for consistency with other methods + // here. if (path.endsWith('\\')) { path = path.substring(0, path.length - 1); } @@ -44,25 +43,25 @@ class PathProviderWindows extends PathProviderPlatform { } } - /// Path to a directory where the application may place application support - /// files. @override - Future getApplicationSupportPath() => - getPath(WindowsKnownFolder.ProgramData); - - /// Path to the directory where application can store files that are persistent, - /// backed up, and not visible to the user, such as sqlite.db. - @override - Future getLibraryPath() => getPath(WindowsKnownFolder.LocalAppData); + Future getApplicationSupportPath() async { + final appDataRoot = await getPath(WindowsKnownFolder.RoamingAppData); + // DO NOT LAND. Use GetModuleFileName here once it's available in win32. + final exePath = 'path/to/app.exe'; + final directory = Directory( + path.join(appDataRoot, path.basenameWithoutExtension(exePath))); + // Ensure that the returned directory exists, since it will on other + // platforms. + if (!directory.existsSync()) { + await directory.create(recursive: true); + } + return directory.path; + } - /// Path to a directory where the application may place data that is - /// user-generated, or that cannot otherwise be recreated by your application. @override Future getApplicationDocumentsPath() => getPath(WindowsKnownFolder.Documents); - /// Path to the directory where downloaded files can be stored. This is - /// typically the same as %USERPROFILE%\Downloads. @override Future getDownloadsPath() => getPath(WindowsKnownFolder.Downloads); diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index e8111bc08ea2..677fee7cfb5e 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -12,6 +12,7 @@ flutter: dependencies: path_provider_platform_interface: ^1.0.3 + path: ^1.6.4 flutter: sdk: flutter ffi: ^0.1.3 From 3cd2f983839317ce4e0d94c57d370c21861f99ef Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 08:36:30 -0700 Subject: [PATCH 26/39] Improve unit test coverage; skip on non-Windows --- .../path_provider_windows/README.md | 4 ++-- .../test/path_provider_windows_test.dart | 23 +++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/path_provider/path_provider_windows/README.md b/packages/path_provider/path_provider_windows/README.md index fc9b9eba8956..66a05f9e7347 100644 --- a/packages/path_provider/path_provider_windows/README.md +++ b/packages/path_provider/path_provider_windows/README.md @@ -24,8 +24,8 @@ This is what the above means to your `pubspec.yaml`: ... dependencies: ... - path_provider: ^1.5.1 + path_provider: ^1.6.15 ... ``` -[1]:../ \ No newline at end of file +[1]:../ diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index ab3c1f6438e1..7cba3735d081 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -1,6 +1,7 @@ // Copyright 2020 The Chromium 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_test/flutter_test.dart'; import 'package:path_provider_windows/path_provider_windows.dart'; @@ -15,6 +16,24 @@ void main() { tearDown(() {}); test('getTemporaryPath', () async { - expect(await pathProvider.getTemporaryPath(), contains('C:\\')); - }); + expect(await pathProvider.getTemporaryPath(), contains(r'C:\')); + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath', () async { + final path = await pathProvider.getApplicationSupportPath(); + expect(path, contains(r'C:\')); + expect(path, contains(r'AppData')); + }, skip: !Platform.isWindows); + + test('getApplicationDocumentsPath', () async { + final path = await pathProvider.getApplicationDocumentsPath(); + expect(path, contains(r'C:\')); + expect(path, contains(r'Documents')); + }, skip: !Platform.isWindows); + + test('getDownloadsPath', () async { + final path = await pathProvider.getDownloadsPath(); + expect(path, contains(r'C:\')); + expect(path, contains(r'Downloads')); + }, skip: !Platform.isWindows); } From 3d49b16d38bb3c181b3faa295a3f65d83c3318ca Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 09:14:01 -0700 Subject: [PATCH 27/39] Make example self-contained --- .../example/lib/main.dart | 11 ++++---- .../example/pubspec.yaml | 2 +- .../test_driver/path_provider_e2e.dart | 26 ++++++++++--------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/path_provider/path_provider_windows/example/lib/main.dart b/packages/path_provider/path_provider_windows/example/lib/main.dart index 5f0881bef2bb..4fbb1decf2f4 100644 --- a/packages/path_provider/path_provider_windows/example/lib/main.dart +++ b/packages/path_provider/path_provider_windows/example/lib/main.dart @@ -7,7 +7,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:path_provider/path_provider.dart'; +import 'package:path_provider_windows/path_provider_windows.dart'; void main() async { runApp(MyApp()); @@ -37,26 +37,27 @@ class _MyAppState extends State { String downloadsDirectory; String appSupportDirectory; String documentsDirectory; + final PathProviderWindows provider = PathProviderWindows(); try { - tempDirectory = (await getTemporaryDirectory()).path; + tempDirectory = await provider.getTemporaryPath(); } catch (exception) { tempDirectory = 'Failed to get temp directory: $exception'; } try { - downloadsDirectory = (await getDownloadsDirectory()).path; + downloadsDirectory = await provider.getDownloadsPath(); } catch (exception) { downloadsDirectory = 'Failed to get downloads directory: $exception'; } try { - documentsDirectory = (await getApplicationDocumentsDirectory()).path; + documentsDirectory = await provider.getApplicationDocumentsPath(); } catch (exception) { documentsDirectory = 'Failed to get documents directory: $exception'; } try { - appSupportDirectory = (await getApplicationSupportDirectory()).path; + appSupportDirectory = await provider.getApplicationSupportPath(); } catch (exception) { appSupportDirectory = 'Failed to get app support directory: $exception'; } diff --git a/packages/path_provider/path_provider_windows/example/pubspec.yaml b/packages/path_provider/path_provider_windows/example/pubspec.yaml index 68b7d44a3a1b..8dbe6e020906 100644 --- a/packages/path_provider/path_provider_windows/example/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/example/pubspec.yaml @@ -4,7 +4,7 @@ description: Demonstrates how to use the path_provider plugin. dependencies: flutter: sdk: flutter - path_provider: any + path_provider_windows: any dependency_overrides: path_provider_windows: diff --git a/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart b/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart index 4201afb90cb2..ee9427686026 100644 --- a/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart +++ b/packages/path_provider/path_provider_windows/example/test_driver/path_provider_e2e.dart @@ -4,39 +4,41 @@ import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; -import 'package:path_provider/path_provider.dart'; +import 'package:path_provider_windows/path_provider_windows.dart'; import 'package:e2e/e2e.dart'; void main() { E2EWidgetsFlutterBinding.ensureInitialized(); testWidgets('getTemporaryDirectory', (WidgetTester tester) async { - final Directory result = await getTemporaryDirectory(); + final PathProviderWindows provider = PathProviderWindows(); + final String result = await provider.getTemporaryPath(); _verifySampleFile(result, 'temporaryDirectory'); }); testWidgets('getApplicationDocumentsDirectory', (WidgetTester tester) async { - final Directory result = await getApplicationDocumentsDirectory(); + final PathProviderWindows provider = PathProviderWindows(); + final String result = await provider.getApplicationDocumentsPath(); _verifySampleFile(result, 'applicationDocuments'); }); testWidgets('getApplicationSupportDirectory', (WidgetTester tester) async { - final Directory result = await getApplicationSupportDirectory(); + final PathProviderWindows provider = PathProviderWindows(); + final String result = await provider.getApplicationSupportPath(); _verifySampleFile(result, 'applicationSupport'); }); - testWidgets('getLibraryDirectory', (WidgetTester tester) async { - if (!Platform.isWindows) { - return; - } - final Directory result = await getLibraryDirectory(); - _verifySampleFile(result, 'library'); + testWidgets('getDownloadsDirectory', (WidgetTester tester) async { + final PathProviderWindows provider = PathProviderWindows(); + final String result = await provider.getDownloadsPath(); + _verifySampleFile(result, 'downloads'); }); } -/// Verify a file called [name] in [directory] by recreating it with test +/// Verify a file called [name] in [directoryPath] by recreating it with test /// contents when necessary. -void _verifySampleFile(Directory directory, String name) { +void _verifySampleFile(String directoryPath, String name) { + final Directory directory = Directory(directoryPath); final File file = File('${directory.path}${Platform.pathSeparator}$name'); if (file.existsSync()) { From 845074f552ce37bea20bdea4763aad374f157296 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 09:54:49 -0700 Subject: [PATCH 28/39] Ensure that temp directory exists before returning it --- .../lib/path_provider_windows.dart | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index d935b45e1782..93dc802da0bd 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -16,8 +16,9 @@ import 'package:path_provider_windows/folders.dart'; /// /// This class implements the `package:path_provider` functionality for Windows. class PathProviderWindows extends PathProviderPlatform { + /// This is typically the same as the TMP environment variable. @override - Future getTemporaryPath() { + Future getTemporaryPath() async { final buffer = allocate(count: MAX_PATH + 1).cast(); String path; @@ -37,6 +38,13 @@ class PathProviderWindows extends PathProviderPlatform { path = path.substring(0, path.length - 1); } } + + // Ensure that the directory exists, since GetTempPath doesn't. + final directory = Directory(path); + if (!directory.existsSync()) { + await directory.create(recursive: true); + } + return Future.value(path); } finally { free(buffer); From a3c2bf22e102b5edcddaa784fbf09eea2ca06a96 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 10:03:21 -0700 Subject: [PATCH 29/39] Dart format --- packages/path_provider/path_provider/lib/path_provider.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/path_provider/path_provider/lib/path_provider.dart b/packages/path_provider/path_provider/lib/path_provider.dart index 9c44f063c4ef..0fbab57700be 100644 --- a/packages/path_provider/path_provider/lib/path_provider.dart +++ b/packages/path_provider/path_provider/lib/path_provider.dart @@ -27,8 +27,7 @@ PathProviderPlatform get _platform { if (_manualDartRegistrationNeeded) { // Only do the initial registration if it hasn't already been overridden // with a non-default instance. - if (!kIsWeb && - PathProviderPlatform.instance is MethodChannelPathProvider) { + if (!kIsWeb && PathProviderPlatform.instance is MethodChannelPathProvider) { if (Platform.isLinux) { PathProviderPlatform.instance = PathProviderLinux(); } else if (Platform.isWindows) { From 676fd02a18107b47eefe884aa9152313a63bf1e3 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 15 Sep 2020 16:49:09 -0700 Subject: [PATCH 30/39] Use actual executable name --- .../lib/path_provider_windows.dart | 24 +++++++++++++++---- .../path_provider_windows/pubspec.yaml | 2 +- .../test/path_provider_windows_test.dart | 2 ++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 93dc802da0bd..20156c3280ee 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -54,10 +54,7 @@ class PathProviderWindows extends PathProviderPlatform { @override Future getApplicationSupportPath() async { final appDataRoot = await getPath(WindowsKnownFolder.RoamingAppData); - // DO NOT LAND. Use GetModuleFileName here once it's available in win32. - final exePath = 'path/to/app.exe'; - final directory = Directory( - path.join(appDataRoot, path.basenameWithoutExtension(exePath))); + final directory = Directory(path.join(appDataRoot, _getExeName())); // Ensure that the returned directory exists, since it will on other // platforms. if (!directory.existsSync()) { @@ -101,4 +98,23 @@ class PathProviderWindows extends PathProviderPlatform { free(pathPtrPtr); } } + + /// Returns the name of the executable running this code, without the + /// extension. + String _getExeName() { + final buffer = allocate(count: MAX_PATH + 1).cast(); + try { + final length = GetModuleFileName(0, buffer, MAX_PATH); + String exePath; + if (length == 0) { + final error = GetLastError(); + throw WindowsException(error); + } else { + exePath = buffer.unpackString(length); + } + return path.basenameWithoutExtension(exePath); + } finally { + free(buffer); + } + } } diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 677fee7cfb5e..3643acab086c 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: flutter: sdk: flutter ffi: ^0.1.3 - win32: ^1.6.10 + win32: ^1.7.0 dev_dependencies: flutter_test: diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index 7cba3735d081..c9306e04d285 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -23,6 +23,8 @@ void main() { final path = await pathProvider.getApplicationSupportPath(); expect(path, contains(r'C:\')); expect(path, contains(r'AppData')); + // The last path component should be the executable name. + expect(path, endsWith(r'example')); }, skip: !Platform.isWindows); test('getApplicationDocumentsPath', () async { From cd2f366d5b0ed02e5b0a057da958679b1ca92c13 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 16 Sep 2020 06:45:50 -0700 Subject: [PATCH 31/39] Use 0.0.2, since there were code changes --- packages/path_provider/path_provider_windows/CHANGELOG.md | 4 +++- packages/path_provider/path_provider_windows/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md index f1fef36649e3..982602c3ae1a 100644 --- a/packages/path_provider/path_provider_windows/CHANGELOG.md +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -1,6 +1,8 @@ -## 0.0.1+3 +## 0.0.2 * README update for endorsement. +* Changed getApplicationSupportPath location. +* Removed getLibraryPath. ## 0.0.1+2 diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 3643acab086c..f89a28b32e1e 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -1,7 +1,7 @@ name: path_provider_windows description: Windows implementation of the path_provider plugin homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_windows -version: 0.0.1+3 +version: 0.0.2 flutter: plugin: From 7d46f6362c3063e0b3cfd6aef8b34c712e3d2aec Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 17 Sep 2020 13:29:42 -0700 Subject: [PATCH 32/39] Use VERSIONINFO to figure out the appdata subdir Follows the full convention of company-name\app-name\ as the subdirectory, using the VERSIONINFO resource if there. --- .../lib/path_provider_windows.dart | 120 ++++++++++++++++-- .../path_provider_windows/pubspec.yaml | 3 +- .../test/path_provider_windows_test.dart | 67 ++++++++-- 3 files changed, 168 insertions(+), 22 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 20156c3280ee..7b2831e19b39 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -7,15 +7,49 @@ import 'dart:io'; import 'dart:ffi'; import 'package:ffi/ffi.dart'; -import 'package:win32/win32.dart'; +import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; import 'package:path_provider_windows/folders.dart'; +import 'package:win32/win32.dart'; + +/// Wraps the Win32 VerQueryValue API call. +/// +/// This class exists to allow injecting alternate metadata in tests without +/// building multiple custom test binaries. +@visibleForTesting +class VersionInfoQuerier { + /// Returns the value for [key] in [versionInfo]s English strings section, or + /// null if there is no such entry, or if versionInfo is null. + getStringValue(Pointer versionInfo, key) { + if (versionInfo == null) { + return null; + } + final keyPath = TEXT('\\StringFileInfo\\040904e4\\$key'); + final length = allocate(); + final valueAddress = allocate(); + try { + if (VerQueryValue(versionInfo, keyPath, valueAddress, length) == 0) { + return null; + } + return Pointer.fromAddress(valueAddress.value) + .unpackString(length.value); + } finally { + free(keyPath); + free(length); + free(valueAddress); + } + } +} /// The Windows implementation of [PathProviderPlatform] /// /// This class implements the `package:path_provider` functionality for Windows. class PathProviderWindows extends PathProviderPlatform { + /// The object to use for performing VerQueryValue calls. + @visibleForTesting + VersionInfoQuerier versionInfoQuerier = VersionInfoQuerier(); + /// This is typically the same as the TMP environment variable. @override Future getTemporaryPath() async { @@ -54,7 +88,8 @@ class PathProviderWindows extends PathProviderPlatform { @override Future getApplicationSupportPath() async { final appDataRoot = await getPath(WindowsKnownFolder.RoamingAppData); - final directory = Directory(path.join(appDataRoot, _getExeName())); + final directory = Directory( + path.join(appDataRoot, _getApplicationSpecificSubdirectory())); // Ensure that the returned directory exists, since it will on other // platforms. if (!directory.existsSync()) { @@ -99,22 +134,81 @@ class PathProviderWindows extends PathProviderPlatform { } } - /// Returns the name of the executable running this code, without the - /// extension. - String _getExeName() { - final buffer = allocate(count: MAX_PATH + 1).cast(); + /// Returns the relative path string to append to the root directory returned + /// by Win32 APIs for application storage (such as RoamingAppDir) to get a + /// directory that is unique to the application. + /// + /// The convention is to use company-name\product-name\. This will use that if + /// possible, using the data in the VERSIONINFO resource, with the following + /// fallbacks: + /// - If the company name isn't there, that component will be dropped. + /// - If the product name isn't there, it will use the exe's filename (without + /// extension). + String _getApplicationSpecificSubdirectory() { + String companyName; + String productName; + + final Pointer moduleNameBuffer = + allocate(count: MAX_PATH + 1).cast(); + final Pointer unused = allocate(); + Pointer infoBuffer; try { - final length = GetModuleFileName(0, buffer, MAX_PATH); - String exePath; - if (length == 0) { + // Get the module name. + final moduleNameLength = GetModuleFileName(0, moduleNameBuffer, MAX_PATH); + if (moduleNameLength == 0) { final error = GetLastError(); throw WindowsException(error); - } else { - exePath = buffer.unpackString(length); } - return path.basenameWithoutExtension(exePath); + + // From that, load the VERSIONINFO resource + int infoSize = GetFileVersionInfoSize(moduleNameBuffer, unused); + if (infoSize != 0) { + infoBuffer = allocate(count: infoSize); + if (GetFileVersionInfo(moduleNameBuffer, 0, infoSize, infoBuffer) == + 0) { + free(infoBuffer); + infoBuffer = null; + } + } + companyName = _sanitizedDirectoryName( + versionInfoQuerier.getStringValue(infoBuffer, 'CompanyName')); + productName = _sanitizedDirectoryName( + versionInfoQuerier.getStringValue(infoBuffer, 'ProductName')); + + // If there was no product name, use the executable name. + if (productName == null) { + productName = path.basenameWithoutExtension( + moduleNameBuffer.unpackString(moduleNameLength)); + } + + return companyName != null + ? path.join(companyName, productName) + : productName; } finally { - free(buffer); + free(moduleNameBuffer); + free(unused); + if (infoBuffer != null) { + free(infoBuffer); + } + } + } + + /// Makes [rawString] safe as a directory component. See + /// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions + /// + /// If after sanitizing the string is empty, returns null. + String _sanitizedDirectoryName(String rawString) { + if (rawString == null) { + return null; } + String sanitized = rawString + // Replace banned characters. + .replaceAll(RegExp(r'[<>:"/\\|?*]'), '_') + // Remove trailing (and leading, which is not necessary, but won't hurt) + // whitespace. + .trim() + // Ensure that it does not end with a '.'. + .replaceAll(RegExp(r'[.]+$'), ''); + return sanitized.isEmpty ? null : sanitized; } } diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index f89a28b32e1e..54d5a5190ddf 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -12,11 +12,12 @@ flutter: dependencies: path_provider_platform_interface: ^1.0.3 + meta: ^1.0.5 path: ^1.6.4 flutter: sdk: flutter ffi: ^0.1.3 - win32: ^1.7.0 + win32: ^1.7.1 dev_dependencies: flutter_test: diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index c9306e04d285..77d3d7c61707 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -1,39 +1,90 @@ // Copyright 2020 The Chromium 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:ffi'; import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:path_provider_windows/path_provider_windows.dart'; -void main() { - PathProviderWindows pathProvider; +// A fake VersionInfoQuerier that just returns preset responses. +class FakeVersionInfoQuerier implements VersionInfoQuerier { + FakeVersionInfoQuerier(this.responses); - setUp(() { - pathProvider = PathProviderWindows(); - }); + final Map responses; - tearDown(() {}); + getStringValue(Pointer versionInfo, key) => responses[key]; +} +void main() { test('getTemporaryPath', () async { + final pathProvider = PathProviderWindows(); expect(await pathProvider.getTemporaryPath(), contains(r'C:\')); }, skip: !Platform.isWindows); - test('getApplicationSupportPath', () async { + test('getApplicationSupportPath with no version info', () async { + final pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = + FakeVersionInfoQuerier({}); final path = await pathProvider.getApplicationSupportPath(); expect(path, contains(r'C:\')); expect(path, contains(r'AppData')); // The last path component should be the executable name. - expect(path, endsWith(r'example')); + expect(path, endsWith(r'flutter_tester')); + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with full version info', () async { + final pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': 'A Company', + 'ProductName': 'Amazing App', + }); + final path = await pathProvider.getApplicationSupportPath(); + expect(path, endsWith(r'AppData\Roaming\A Company\Amazing App')); + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with missing company', () async { + final pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'ProductName': 'Amazing App', + }); + final path = await pathProvider.getApplicationSupportPath(); + expect(path, endsWith(r'AppData\Roaming\Amazing App')); + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with problematic values', () async { + final pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': r'A Company: Name.', + 'ProductName': r'A"/Terrible\|App?*Name', + }); + final path = await pathProvider.getApplicationSupportPath(); + expect( + path, + endsWith(r'AppData\Roaming\' + r'A _Bad_ Company_ Name\' + r'A__Terrible__App__Name')); + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with a completely invalid company', () async { + final pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': r'..', + 'ProductName': r'Amazing App', + }); + final path = await pathProvider.getApplicationSupportPath(); + expect(path, endsWith(r'AppData\Roaming\Amazing App')); }, skip: !Platform.isWindows); test('getApplicationDocumentsPath', () async { + final pathProvider = PathProviderWindows(); final path = await pathProvider.getApplicationDocumentsPath(); expect(path, contains(r'C:\')); expect(path, contains(r'Documents')); }, skip: !Platform.isWindows); test('getDownloadsPath', () async { + final pathProvider = PathProviderWindows(); final path = await pathProvider.getDownloadsPath(); expect(path, contains(r'C:\')); expect(path, contains(r'Downloads')); From 80a0b6a6a894c05009cd35afffbf10b5f1939037 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 17 Sep 2020 16:05:58 -0700 Subject: [PATCH 33/39] Use TestOn --- .../path_provider_windows/pubspec.yaml | 1 + .../test/path_provider_windows_test.dart | 20 +++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 54d5a5190ddf..fd062841da30 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -23,6 +23,7 @@ dev_dependencies: flutter_test: sdk: flutter pedantic: ^1.8.0 + test: any environment: sdk: ">=2.1.0 <3.0.0" diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index 77d3d7c61707..8dc014434440 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -1,11 +1,11 @@ // Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +@TestOn('windows') import 'dart:ffi'; -import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; import 'package:path_provider_windows/path_provider_windows.dart'; +import 'package:test/test.dart'; // A fake VersionInfoQuerier that just returns preset responses. class FakeVersionInfoQuerier implements VersionInfoQuerier { @@ -20,7 +20,7 @@ void main() { test('getTemporaryPath', () async { final pathProvider = PathProviderWindows(); expect(await pathProvider.getTemporaryPath(), contains(r'C:\')); - }, skip: !Platform.isWindows); + }); test('getApplicationSupportPath with no version info', () async { final pathProvider = PathProviderWindows(); @@ -31,7 +31,7 @@ void main() { expect(path, contains(r'AppData')); // The last path component should be the executable name. expect(path, endsWith(r'flutter_tester')); - }, skip: !Platform.isWindows); + }); test('getApplicationSupportPath with full version info', () async { final pathProvider = PathProviderWindows(); @@ -41,7 +41,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\A Company\Amazing App')); - }, skip: !Platform.isWindows); + }); test('getApplicationSupportPath with missing company', () async { final pathProvider = PathProviderWindows(); @@ -50,7 +50,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\Amazing App')); - }, skip: !Platform.isWindows); + }); test('getApplicationSupportPath with problematic values', () async { final pathProvider = PathProviderWindows(); @@ -64,7 +64,7 @@ void main() { endsWith(r'AppData\Roaming\' r'A _Bad_ Company_ Name\' r'A__Terrible__App__Name')); - }, skip: !Platform.isWindows); + }); test('getApplicationSupportPath with a completely invalid company', () async { final pathProvider = PathProviderWindows(); @@ -74,19 +74,19 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\Amazing App')); - }, skip: !Platform.isWindows); + }); test('getApplicationDocumentsPath', () async { final pathProvider = PathProviderWindows(); final path = await pathProvider.getApplicationDocumentsPath(); expect(path, contains(r'C:\')); expect(path, contains(r'Documents')); - }, skip: !Platform.isWindows); + }); test('getDownloadsPath', () async { final pathProvider = PathProviderWindows(); final path = await pathProvider.getDownloadsPath(); expect(path, contains(r'C:\')); expect(path, contains(r'Downloads')); - }, skip: !Platform.isWindows); + }); } From 3a3fdb7e44c32e41eef0d872c9cb80ecb3f31e52 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 17 Sep 2020 16:16:05 -0700 Subject: [PATCH 34/39] Cap directory component length --- .../lib/path_provider_windows.dart | 9 ++++++--- .../test/path_provider_windows_test.dart | 11 +++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index 7b2831e19b39..ab0546ab1dc0 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -204,11 +204,14 @@ class PathProviderWindows extends PathProviderPlatform { String sanitized = rawString // Replace banned characters. .replaceAll(RegExp(r'[<>:"/\\|?*]'), '_') - // Remove trailing (and leading, which is not necessary, but won't hurt) - // whitespace. - .trim() + // Remove trailing whitespace. + .trimRight() // Ensure that it does not end with a '.'. .replaceAll(RegExp(r'[.]+$'), ''); + const maxComponentLength = 255; + if (sanitized.length > maxComponentLength) { + sanitized.substring(0, maxComponentLength); + } return sanitized.isEmpty ? null : sanitized; } } diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index 8dc014434440..8b9d3b7c1d94 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -76,6 +76,17 @@ void main() { expect(path, endsWith(r'AppData\Roaming\Amazing App')); }); + test('getApplicationSupportPath with very long app name', () async { + final pathProvider = PathProviderWindows(); + final truncatedName = 'A' * 255; + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': 'A Company', + 'ProductName': truncatedName * 2, + }); + final path = await pathProvider.getApplicationSupportPath(); + expect(path, endsWith('\\$truncatedName')); + }); + test('getApplicationDocumentsPath', () async { final pathProvider = PathProviderWindows(); final path = await pathProvider.getApplicationDocumentsPath(); From 954a8dfb27caee333f92a812c392a443e00855da Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 17 Sep 2020 17:30:05 -0700 Subject: [PATCH 35/39] Revert "Use TestOn" This reverts commit 80a0b6a6a894c05009cd35afffbf10b5f1939037. --- .../path_provider_windows/pubspec.yaml | 1 - .../test/path_provider_windows_test.dart | 20 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index fd062841da30..54d5a5190ddf 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -23,7 +23,6 @@ dev_dependencies: flutter_test: sdk: flutter pedantic: ^1.8.0 - test: any environment: sdk: ">=2.1.0 <3.0.0" diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index 8b9d3b7c1d94..6e65f2ca1ba5 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -1,11 +1,11 @@ // Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@TestOn('windows') import 'dart:ffi'; +import 'dart:io'; +import 'package:flutter_test/flutter_test.dart'; import 'package:path_provider_windows/path_provider_windows.dart'; -import 'package:test/test.dart'; // A fake VersionInfoQuerier that just returns preset responses. class FakeVersionInfoQuerier implements VersionInfoQuerier { @@ -20,7 +20,7 @@ void main() { test('getTemporaryPath', () async { final pathProvider = PathProviderWindows(); expect(await pathProvider.getTemporaryPath(), contains(r'C:\')); - }); + }, skip: !Platform.isWindows); test('getApplicationSupportPath with no version info', () async { final pathProvider = PathProviderWindows(); @@ -31,7 +31,7 @@ void main() { expect(path, contains(r'AppData')); // The last path component should be the executable name. expect(path, endsWith(r'flutter_tester')); - }); + }, skip: !Platform.isWindows); test('getApplicationSupportPath with full version info', () async { final pathProvider = PathProviderWindows(); @@ -41,7 +41,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\A Company\Amazing App')); - }); + }, skip: !Platform.isWindows); test('getApplicationSupportPath with missing company', () async { final pathProvider = PathProviderWindows(); @@ -50,7 +50,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\Amazing App')); - }); + }, skip: !Platform.isWindows); test('getApplicationSupportPath with problematic values', () async { final pathProvider = PathProviderWindows(); @@ -64,7 +64,7 @@ void main() { endsWith(r'AppData\Roaming\' r'A _Bad_ Company_ Name\' r'A__Terrible__App__Name')); - }); + }, skip: !Platform.isWindows); test('getApplicationSupportPath with a completely invalid company', () async { final pathProvider = PathProviderWindows(); @@ -74,7 +74,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\Amazing App')); - }); + }, skip: !Platform.isWindows); test('getApplicationSupportPath with very long app name', () async { final pathProvider = PathProviderWindows(); @@ -92,12 +92,12 @@ void main() { final path = await pathProvider.getApplicationDocumentsPath(); expect(path, contains(r'C:\')); expect(path, contains(r'Documents')); - }); + }, skip: !Platform.isWindows); test('getDownloadsPath', () async { final pathProvider = PathProviderWindows(); final path = await pathProvider.getDownloadsPath(); expect(path, contains(r'C:\')); expect(path, contains(r'Downloads')); - }); + }, skip: !Platform.isWindows); } From be299b9e9ed3d557cd6e0fdb8c6b51b483d9e53c Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 17 Sep 2020 17:31:01 -0700 Subject: [PATCH 36/39] Update the test added after the revert change --- .../path_provider_windows/lib/path_provider_windows.dart | 6 +++--- .../test/path_provider_windows_test.dart | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index ab0546ab1dc0..a493c89f051e 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -208,9 +208,9 @@ class PathProviderWindows extends PathProviderPlatform { .trimRight() // Ensure that it does not end with a '.'. .replaceAll(RegExp(r'[.]+$'), ''); - const maxComponentLength = 255; - if (sanitized.length > maxComponentLength) { - sanitized.substring(0, maxComponentLength); + const kMaxComponentLength = 255; + if (sanitized.length > kMaxComponentLength) { + sanitized.substring(0, kMaxComponentLength); } return sanitized.isEmpty ? null : sanitized; } diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index 6e65f2ca1ba5..2b7eecddc7c4 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -85,7 +85,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith('\\$truncatedName')); - }); + }, skip: !Platform.isWindows); test('getApplicationDocumentsPath', () async { final pathProvider = PathProviderWindows(); From e826b175c4c9e4ba9a1447542c2c23cbf540c6f8 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 17 Sep 2020 17:44:39 -0700 Subject: [PATCH 37/39] Use a named constant for the language code --- .../path_provider_windows/lib/path_provider_windows.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index a493c89f051e..c2733d242308 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -25,7 +25,8 @@ class VersionInfoQuerier { if (versionInfo == null) { return null; } - final keyPath = TEXT('\\StringFileInfo\\040904e4\\$key'); + const kEnglishCode = '040904e4'; + final keyPath = TEXT('\\StringFileInfo\\$kEnglishCode\\$key'); final length = allocate(); final valueAddress = allocate(); try { From 370f3ce351fcbacef4f94d6f091250e178c03abc Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 17 Sep 2020 17:45:26 -0700 Subject: [PATCH 38/39] Make the name more accurate --- .../path_provider_windows/lib/path_provider_windows.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index c2733d242308..ff3c560d7da7 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -25,8 +25,8 @@ class VersionInfoQuerier { if (versionInfo == null) { return null; } - const kEnglishCode = '040904e4'; - final keyPath = TEXT('\\StringFileInfo\\$kEnglishCode\\$key'); + const kEnUsLanguageCode = '040904e4'; + final keyPath = TEXT('\\StringFileInfo\\$kEnUsLanguageCode\\$key'); final length = allocate(); final valueAddress = allocate(); try { From fe6d47214abe39143b7f44cc394376587b3d202c Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 18 Sep 2020 06:01:36 -0700 Subject: [PATCH 39/39] Fix long path handling --- .../lib/path_provider_windows.dart | 14 +++++++++----- .../test/path_provider_windows_test.dart | 6 ++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart index ff3c560d7da7..e29b70a714d9 100644 --- a/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart +++ b/packages/path_provider/path_provider_windows/lib/path_provider_windows.dart @@ -91,10 +91,14 @@ class PathProviderWindows extends PathProviderPlatform { final appDataRoot = await getPath(WindowsKnownFolder.RoamingAppData); final directory = Directory( path.join(appDataRoot, _getApplicationSpecificSubdirectory())); - // Ensure that the returned directory exists, since it will on other - // platforms. - if (!directory.existsSync()) { - await directory.create(recursive: true); + // Ensure that the directory exists if possible, since it will on other + // platforms. If the name is longer than MAXPATH, creating will fail, so + // skip that step; it's up to the client to decide what to do with the path + // in that case (e.g., using a short path). + if (directory.path.length <= MAX_PATH) { + if (!directory.existsSync()) { + await directory.create(recursive: true); + } } return directory.path; } @@ -211,7 +215,7 @@ class PathProviderWindows extends PathProviderPlatform { .replaceAll(RegExp(r'[.]+$'), ''); const kMaxComponentLength = 255; if (sanitized.length > kMaxComponentLength) { - sanitized.substring(0, kMaxComponentLength); + sanitized = sanitized.substring(0, kMaxComponentLength); } return sanitized.isEmpty ? null : sanitized; } diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index 2b7eecddc7c4..83ceea9cdf0c 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -41,6 +41,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\A Company\Amazing App')); + expect(Directory(path).existsSync(), isTrue); }, skip: !Platform.isWindows); test('getApplicationSupportPath with missing company', () async { @@ -50,6 +51,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\Amazing App')); + expect(Directory(path).existsSync(), isTrue); }, skip: !Platform.isWindows); test('getApplicationSupportPath with problematic values', () async { @@ -64,6 +66,7 @@ void main() { endsWith(r'AppData\Roaming\' r'A _Bad_ Company_ Name\' r'A__Terrible__App__Name')); + expect(Directory(path).existsSync(), isTrue); }, skip: !Platform.isWindows); test('getApplicationSupportPath with a completely invalid company', () async { @@ -74,6 +77,7 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith(r'AppData\Roaming\Amazing App')); + expect(Directory(path).existsSync(), isTrue); }, skip: !Platform.isWindows); test('getApplicationSupportPath with very long app name', () async { @@ -85,6 +89,8 @@ void main() { }); final path = await pathProvider.getApplicationSupportPath(); expect(path, endsWith('\\$truncatedName')); + // The directory won't exist, since it's longer than MAXPATH, so don't check + // that here. }, skip: !Platform.isWindows); test('getApplicationDocumentsPath', () async {