提交 7fe880d8 编写于 作者: C Chinmay Garde

iOS: Implement service providers for flutter.platform

上级 69abe6b0
......@@ -13,8 +13,31 @@ mojom("interfaces") {
]
}
if (is_ios) {
source_set("platform_lib") {
sources = [
"ios/haptic_feedback_impl.h",
"ios/haptic_feedback_impl.mm",
"ios/path_provider_impl.h",
"ios/path_provider_impl.mm",
"ios/system_chrome_impl.h",
"ios/system_chrome_impl.mm",
"ios/system_sound_impl.h",
"ios/system_sound_impl.mm",
]
deps = [
"//base:base",
"//mojo/public/cpp/application",
":interfaces",
]
}
}
group("platform") {
deps = [
":interfaces"
]
if (is_ios) {
deps += [ ":platform_lib" ]
}
}
......@@ -9,6 +9,7 @@ module flutter.platform;
/// intentionally terse since it invokes default platform behavior. It is not
/// suitable for use if you require more flexible access to device sensors and
/// peripherals.
[ServiceName="flutter::platform::HapticFeedback"]
interface HapticFeedback {
/// Provides haptic feedback to the user for a short duration.
///
......
// Copyright 2016 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.
#ifndef SKY_SERVICES_PLATFORM_IOS_HAPTIC_FEEDBACK_IMPL_H_
#define SKY_SERVICES_PLATFORM_IOS_HAPTIC_FEEDBACK_IMPL_H_
#include "base/macros.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "sky/services/platform/haptic_feedback.mojom.h"
namespace flutter {
namespace platform {
class HapticFeedbackImpl : public HapticFeedback {
public:
explicit HapticFeedbackImpl(mojo::InterfaceRequest<HapticFeedback> request);
~HapticFeedbackImpl() override;
void Vibrate(const VibrateCallback& callback) override;
private:
mojo::StrongBinding<HapticFeedback> binding_;
DISALLOW_COPY_AND_ASSIGN(HapticFeedbackImpl);
};
class HapticFeedbackFactory : public mojo::InterfaceFactory<HapticFeedback> {
public:
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<HapticFeedback> request) override;
};
} // namespace platform
} // namespace flutter
#endif // SKY_SERVICES_PLATFORM_IOS_HAPTIC_FEEDBACK_IMPL_H_
// Copyright 2016 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.
#include "sky/services/platform/ios/haptic_feedback_impl.h"
#include <AudioToolbox/AudioToolbox.h>
namespace flutter {
namespace platform {
HapticFeedbackImpl::HapticFeedbackImpl(
mojo::InterfaceRequest<HapticFeedback> request)
: binding_(this, request.Pass()) {}
HapticFeedbackImpl::~HapticFeedbackImpl() {}
void HapticFeedbackFactory::Create(
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<HapticFeedback> request) {
new HapticFeedbackImpl(request.Pass());
}
void HapticFeedbackImpl::Vibrate(const VibrateCallback& callback) {
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
}
} // namespace platform
} // namespace flutter
// Copyright 2016 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.
#ifndef SKY_SERVICES_PLATFORM_IOS_PATH_PROVIDER_IMPL_H_
#define SKY_SERVICES_PLATFORM_IOS_PATH_PROVIDER_IMPL_H_
#include "base/macros.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "sky/services/platform/path_provider.mojom.h"
namespace flutter {
namespace platform {
class PathProviderImpl : public PathProvider {
public:
explicit PathProviderImpl(mojo::InterfaceRequest<PathProvider> request);
~PathProviderImpl() override;
void TemporaryDirectory(const TemporaryDirectoryCallback& callback) override;
void ApplicationDocumentsDirectory(
const ApplicationDocumentsDirectoryCallback& callback) override;
private:
mojo::StrongBinding<PathProvider> binding_;
DISALLOW_COPY_AND_ASSIGN(PathProviderImpl);
};
class PathProviderFactory : public mojo::InterfaceFactory<PathProvider> {
public:
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<PathProvider> request) override;
};
} // namespace platform
} // namespace flutter
#endif // SKY_SERVICES_PLATFORM_IOS_PATH_PROVIDER_IMPL_H_
// Copyright 2016 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.
#include "sky/services/platform/ios/path_provider_impl.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include <Foundation/Foundation.h>
#include <string>
namespace flutter {
namespace platform {
PathProviderImpl::PathProviderImpl(mojo::InterfaceRequest<PathProvider> request)
: binding_(this, request.Pass()) {}
PathProviderImpl::~PathProviderImpl() {}
void PathProviderFactory::Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<PathProvider> request) {
new PathProviderImpl(request.Pass());
}
static std::string GetDirectoryOfType(NSSearchPathDirectory dir) {
base::mac::ScopedNSAutoreleasePool pool;
NSArray* paths =
NSSearchPathForDirectoriesInDomains(dir, NSUserDomainMask, YES);
if (paths.count == 0) {
return "";
}
return [paths.firstObject UTF8String];
}
void PathProviderImpl::TemporaryDirectory(
const TemporaryDirectoryCallback& callback) {
callback.Run(GetDirectoryOfType(NSCachesDirectory));
}
void PathProviderImpl::ApplicationDocumentsDirectory(
const ApplicationDocumentsDirectoryCallback& callback) {
callback.Run(GetDirectoryOfType(NSDocumentDirectory));
}
} // namespace platform
} // namespace flutter
// Copyright 2016 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.
#ifndef SKY_SERVICES_PLATFORM_IOS_SYSTEM_CHROME_IMPL_H_
#define SKY_SERVICES_PLATFORM_IOS_SYSTEM_CHROME_IMPL_H_
#include "base/macros.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "sky/services/platform/system_chrome.mojom.h"
namespace flutter {
namespace platform {
class SystemChromeImpl : public SystemChrome {
public:
explicit SystemChromeImpl(mojo::InterfaceRequest<SystemChrome> request);
~SystemChromeImpl() override;
void SetPreferredOrientations(
uint32_t interface_orientation_mask,
uint32_t device_orientation_mask,
const SetPreferredOrientationsCallback& callback) override;
void SetEnabledSystemUIOverlays(
uint32_t overlays,
const SetEnabledSystemUIOverlaysCallback& callback) override;
private:
mojo::StrongBinding<SystemChrome> binding_;
DISALLOW_COPY_AND_ASSIGN(SystemChromeImpl);
};
class SystemChromeFactory : public mojo::InterfaceFactory<SystemChrome> {
public:
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<SystemChrome> request) override;
};
extern const char* const kOrientationUpdateNotificationName;
extern const char* const kOrientationUpdateNotificationKey;
} // namespace platform
} // namespace flutter
#endif // SKY_SERVICES_PLATFORM_IOS_SYSTEM_CHROME_IMPL_H_
// Copyright 2016 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.
#include "sky/services/platform/ios/system_chrome_impl.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include <UIKit/UIKit.h>
namespace flutter {
namespace platform {
SystemChromeImpl::SystemChromeImpl(mojo::InterfaceRequest<SystemChrome> request)
: binding_(this, request.Pass()) {}
SystemChromeImpl::~SystemChromeImpl() {}
void SystemChromeFactory::Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<SystemChrome> request) {
new SystemChromeImpl(request.Pass());
}
/// Desugars a typed enum value and checks if it is set in a mask
template <class T,
class = typename std::enable_if<std::is_enum<T>::value>::type>
static constexpr bool IsSet(uint32_t mask, T orientation) {
return (static_cast<int32_t>(orientation) & mask) != 0;
}
void SystemChromeImpl::SetPreferredOrientations(
uint32_t interface,
uint32_t device,
const SetPreferredOrientationsCallback& callback) {
UIInterfaceOrientationMask mask = 0;
if (IsSet(interface, InterfaceOrientation::Portrait)) {
if (IsSet(device, DeviceOrientation::PortraitUp)) {
mask |= UIInterfaceOrientationMaskPortrait;
}
if (IsSet(device, DeviceOrientation::PortraitDown)) {
mask |= UIInterfaceOrientationMaskPortraitUpsideDown;
}
}
if (IsSet(interface, InterfaceOrientation::Landscape)) {
if (IsSet(device, DeviceOrientation::LandscapeLeft)) {
mask |= UIInterfaceOrientationMaskLandscapeLeft;
}
if (IsSet(device, DeviceOrientation::LandscapeRight)) {
mask |= UIInterfaceOrientationMaskLandscapeRight;
}
}
if (mask == 0) {
// An impossible configuration was requested. Bail.
callback.Run(false);
return;
}
base::mac::ScopedNSAutoreleasePool pool;
// This notification is respected by the iOS embedder
[[NSNotificationCenter defaultCenter]
postNotificationName:@(kOrientationUpdateNotificationName)
object:nil
userInfo:@{
@(kOrientationUpdateNotificationKey) : @(mask)
}];
callback.Run(true);
}
void SystemChromeImpl::SetEnabledSystemUIOverlays(
uint32_t overlays,
const SetEnabledSystemUIOverlaysCallback& callback) {
// Checks if the top status bar should be visible. This platform ignores all
// other overlays
base::mac::ScopedNSAutoreleasePool pool;
// We opt out of view controller based status bar visibility since we want
// to be able to modify this on the fly. The key used is
// UIViewControllerBasedStatusBarAppearance
[UIApplication sharedApplication].statusBarHidden =
!IsSet(overlays, SystemUIOverlay::Top);
callback.Run(true);
}
const char* const kOrientationUpdateNotificationName =
"SystemChromeOrientationNotificationName";
const char* const kOrientationUpdateNotificationKey =
"SystemChromeOrientationNotificationName";
} // namespace platform
} // namespace flutter
// Copyright 2016 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.
#ifndef SKY_SERVICES_PLATFORM_IOS_SYSTEM_SOUND_IMPL_H_
#define SKY_SERVICES_PLATFORM_IOS_SYSTEM_SOUND_IMPL_H_
#include "base/macros.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "sky/services/platform/system_sound.mojom.h"
namespace flutter {
namespace platform {
class SystemSoundImpl : public SystemSound {
public:
explicit SystemSoundImpl(mojo::InterfaceRequest<SystemSound> request);
~SystemSoundImpl() override;
void Play(SystemSoundType type, const PlayCallback& callback) override;
private:
mojo::StrongBinding<SystemSound> binding_;
DISALLOW_COPY_AND_ASSIGN(SystemSoundImpl);
};
class SystemSoundFactory : public mojo::InterfaceFactory<SystemSound> {
public:
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<SystemSound> request) override;
};
} // namespace platform
} // namespace flutter
#endif // SKY_SERVICES_PLATFORM_IOS_SYSTEM_SOUND_IMPL_H_
// Copyright 2016 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.
#include "sky/services/platform/ios/system_sound_impl.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include <UIKit/UIKit.h>
namespace flutter {
namespace platform {
SystemSoundImpl::SystemSoundImpl(mojo::InterfaceRequest<SystemSound> request)
: binding_(this, request.Pass()) {}
SystemSoundImpl::~SystemSoundImpl() {}
void SystemSoundFactory::Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<SystemSound> request) {
new SystemSoundImpl(request.Pass());
}
void SystemSoundImpl::Play(SystemSoundType type, const PlayCallback& callback) {
base::mac::ScopedNSAutoreleasePool pool;
switch (type) {
case SystemSoundType::Click:
// All feedback types are specific to Android and are treated as equal on
// iOS. The surface must (and does) adopt the UIInputViewAudioFeedback
// protocol
[[UIDevice currentDevice] playInputClick];
callback.Run(true);
return;
// Add more system types here as they are introduced
}
callback.Run(false);
}
} // namespace platform
} // namespace flutter
......@@ -6,6 +6,7 @@
module flutter.platform;
/// Returns commonly used locations on the filesystem.
[ServiceName="flutter::platform::PathProvider"]
interface PathProvider {
/// Path to the temporary directory on the device. Files in this directory
/// may be cleared at any time. This does *not* return a new temporary
......
......@@ -48,6 +48,7 @@ enum SystemUIOverlay {
};
/// Controls specific aspects of the embedder interface.
[ServiceName="flutter::platform::SystemChrome"]
interface SystemChrome {
/// Specifies the set of orientations the application interface can
/// be displayed in.
......
......@@ -12,6 +12,7 @@ enum SystemSoundType {
/// Allows easy access to the library of short system specific sounds for
/// common tasks.
[ServiceName="flutter::platform::SystemSound"]
interface SystemSound {
/// Play the specified system sound. If that sound is not present on the
/// system, this method is a no-op and returns `true`.
......
......@@ -54,6 +54,7 @@ source_set("common") {
"//sky/engine/wtf",
"//sky/services/editing:interfaces",
"//sky/services/engine:interfaces",
"//sky/services/platform",
"//sky/services/pointer:interfaces",
"//sky/services/rasterizer:interfaces",
"//sky/shell/dart",
......
......@@ -10,8 +10,25 @@
#include "sky/shell/shell.h"
#include "sky/shell/shell_view.h"
#include "sky/services/platform/ios/system_chrome_impl.h"
@implementation SkyViewController
@implementation SkyViewController {
UIInterfaceOrientationMask _orientation_preferences;
}
- (instancetype)init {
self = [super init];
if (self) {
_orientation_preferences = UIInterfaceOrientationMaskAll;
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onOrientationPreferencesUpdated:)
name:@(flutter::platform::kOrientationUpdateNotificationName)
object:nil];
}
return self;
}
- (void)loadView {
auto shell_view = new sky::shell::ShellView(sky::shell::Shell::Shared());
......@@ -25,6 +42,35 @@
[surface release];
}
- (void)onOrientationPreferencesUpdated:(NSNotification*)notification {
// Notifications may not be on the iOS UI thread
dispatch_async(dispatch_get_main_queue(), ^{
NSDictionary* info = notification.userInfo;
NSNumber* update =
info[@(flutter::platform::kOrientationUpdateNotificationKey)];
if (update == nil) {
return;
}
NSUInteger new_preferences = update.unsignedIntegerValue;
if (new_preferences != _orientation_preferences) {
_orientation_preferences = new_preferences;
[UIViewController attemptRotationToDeviceOrientation];
}
});
}
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return _orientation_preferences;
}
- (SkySurface*)surface {
DCHECK([self isViewLoaded]);
return reinterpret_cast<SkySurface*>(self.view);
......@@ -42,4 +88,10 @@
return UIStatusBarStyleLightContent;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
@end
......@@ -53,6 +53,30 @@ void PlatformServiceProvider::ConnectToService(
nullptr, mojo::MakeRequest<::activity::Activity>(client_handle.Pass()));
return;
}
if (service_name == flutter::platform::HapticFeedback::Name_) {
haptic_feedback_.Create(
nullptr, mojo::MakeRequest<flutter::platform::HapticFeedback>(
client_handle.Pass()));
return;
}
if (service_name == flutter::platform::PathProvider::Name_) {
path_provider_.Create(nullptr,
mojo::MakeRequest<flutter::platform::PathProvider>(
client_handle.Pass()));
return;
}
if (service_name == flutter::platform::SystemChrome::Name_) {
system_chrome_.Create(nullptr,
mojo::MakeRequest<flutter::platform::SystemChrome>(
client_handle.Pass()));
return;
}
if (service_name == flutter::platform::SystemSound::Name_) {
system_sound_.Create(nullptr,
mojo::MakeRequest<flutter::platform::SystemSound>(
client_handle.Pass()));
return;
}
#endif
LOG(INFO) << "The platform service provider cannot find a service for '"
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_SHELL_PLATFORM_MAC_SERVICE_PROVIDER_H_
#define SKY_SHELL_PLATFORM_MAC_SERVICE_PROVIDER_H_
#ifndef SKY_SHELL_PLATFORM_MAC_PLATFORM_SERVICE_PROVIDER_H_
#define SKY_SHELL_PLATFORM_MAC_PLATFORM_SERVICE_PROVIDER_H_
#include "mojo/public/interfaces/application/service_provider.mojom.h"
#include "sky/engine/wtf/Assertions.h"
......@@ -15,6 +15,10 @@
#include "sky/services/editing/ios/keyboard_impl.h"
#include "sky/services/media/ios/media_player_impl.h"
#include "sky/services/media/ios/media_service_impl.h"
#include "sky/services/platform/ios/haptic_feedback_impl.h"
#include "sky/services/platform/ios/path_provider_impl.h"
#include "sky/services/platform/ios/system_chrome_impl.h"
#include "sky/services/platform/ios/system_sound_impl.h"
#include "sky/services/vsync/ios/vsync_provider_impl.h"
#endif
......@@ -27,7 +31,8 @@ namespace shell {
class PlatformServiceProvider : public mojo::ServiceProvider {
public:
PlatformServiceProvider(mojo::InterfaceRequest<mojo::ServiceProvider> request);
PlatformServiceProvider(
mojo::InterfaceRequest<mojo::ServiceProvider> request);
~PlatformServiceProvider() override;
void ConnectToService(const mojo::String& service_name,
......@@ -37,6 +42,10 @@ class PlatformServiceProvider : public mojo::ServiceProvider {
mojo::StrongBinding<mojo::ServiceProvider> binding_;
mojo::NetworkServiceFactory network_;
#if TARGET_OS_IPHONE
flutter::platform::HapticFeedbackFactory haptic_feedback_;
flutter::platform::PathProviderFactory path_provider_;
flutter::platform::SystemChromeFactory system_chrome_;
flutter::platform::SystemSoundFactory system_sound_;
sky::services::activity::ActivityFactory activity_;
sky::services::editing::KeyboardFactory keyboard_;
sky::services::media::MediaPlayerFactory media_player_;
......@@ -51,4 +60,4 @@ class PlatformServiceProvider : public mojo::ServiceProvider {
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_PLATFORM_MAC_SERVICE_PROVIDER_H_
#endif // SKY_SHELL_PLATFORM_MAC_PLATFORM_SERVICE_PROVIDER_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册