Extract web platform service boundary
This commit is contained in:
@@ -1,7 +1,66 @@
|
|||||||
#include "platform_api/platform_services.h"
|
#include "platform_api/platform_services.h"
|
||||||
|
|
||||||
|
#include "platform_api/platform_policy.h"
|
||||||
|
|
||||||
namespace pp::platform {
|
namespace pp::platform {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
class DefaultWebPlatformServices final : public WebPlatformServices {
|
||||||
|
public:
|
||||||
|
void publish_exported_image(std::string_view path) override
|
||||||
|
{
|
||||||
|
(void)path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_persistent_storage() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int default_canvas_resolution() override
|
||||||
|
{
|
||||||
|
return platform_default_canvas_resolution(PlatformFamily::webgl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_prepared_file(
|
||||||
|
std::string_view path,
|
||||||
|
std::string_view suggested_name,
|
||||||
|
PreparedFileCallback callback) override
|
||||||
|
{
|
||||||
|
(void)suggested_name;
|
||||||
|
callback(std::string(path), false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
WebPlatformServices* g_injected_web_platform_services = nullptr;
|
||||||
|
|
||||||
static_assert(sizeof(PlatformServices*) == sizeof(void*));
|
static_assert(sizeof(PlatformServices*) == sizeof(void*));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebPlatformServices& default_web_platform_services()
|
||||||
|
{
|
||||||
|
static DefaultWebPlatformServices services;
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPlatformServices* injected_web_platform_services() noexcept
|
||||||
|
{
|
||||||
|
return g_injected_web_platform_services;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_injected_web_platform_services(WebPlatformServices* services) noexcept
|
||||||
|
{
|
||||||
|
g_injected_web_platform_services = services;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPlatformServices& resolve_web_platform_services(WebPlatformServices& fallback) noexcept
|
||||||
|
{
|
||||||
|
if (auto* services = injected_web_platform_services())
|
||||||
|
return *services;
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPlatformServices& active_web_platform_services()
|
||||||
|
{
|
||||||
|
return resolve_web_platform_services(default_web_platform_services());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,4 +90,23 @@ public:
|
|||||||
PreparedFileCallback callback) = 0;
|
PreparedFileCallback callback) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WebPlatformServices {
|
||||||
|
public:
|
||||||
|
virtual ~WebPlatformServices() = default;
|
||||||
|
|
||||||
|
virtual void publish_exported_image(std::string_view path) = 0;
|
||||||
|
virtual void flush_persistent_storage() = 0;
|
||||||
|
[[nodiscard]] virtual int default_canvas_resolution() = 0;
|
||||||
|
virtual void save_prepared_file(
|
||||||
|
std::string_view path,
|
||||||
|
std::string_view suggested_name,
|
||||||
|
PreparedFileCallback callback) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] WebPlatformServices& default_web_platform_services();
|
||||||
|
[[nodiscard]] WebPlatformServices* injected_web_platform_services() noexcept;
|
||||||
|
void set_injected_web_platform_services(WebPlatformServices* services) noexcept;
|
||||||
|
[[nodiscard]] WebPlatformServices& resolve_web_platform_services(WebPlatformServices& fallback) noexcept;
|
||||||
|
[[nodiscard]] WebPlatformServices& active_web_platform_services();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,48 @@ void invoke_picked_path_if_selected(
|
|||||||
callback(path);
|
callback(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WEB__
|
||||||
|
class RetainedWebPlatformServices final : public pp::platform::WebPlatformServices {
|
||||||
|
public:
|
||||||
|
void publish_exported_image(std::string_view path) override
|
||||||
|
{
|
||||||
|
(void)path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_persistent_storage() override
|
||||||
|
{
|
||||||
|
webgl_sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int default_canvas_resolution() override
|
||||||
|
{
|
||||||
|
return pp::platform::platform_default_canvas_resolution(pp::platform::PlatformFamily::webgl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_prepared_file(
|
||||||
|
std::string_view path,
|
||||||
|
std::string_view suggested_name,
|
||||||
|
pp::platform::PreparedFileCallback callback) override
|
||||||
|
{
|
||||||
|
const std::string value(path);
|
||||||
|
const std::string name(suggested_name);
|
||||||
|
webgl_pick_file_save(value, name, [callback = std::move(callback), value](bool success) {
|
||||||
|
callback(value, success);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[[nodiscard]] pp::platform::WebPlatformServices& active_legacy_web_platform_services()
|
||||||
|
{
|
||||||
|
#ifdef __WEB__
|
||||||
|
static RetainedWebPlatformServices services;
|
||||||
|
return pp::platform::resolve_web_platform_services(services);
|
||||||
|
#else
|
||||||
|
return pp::platform::active_web_platform_services();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// DEBT-0017: fallback for platforms that do not inject PlatformServices yet.
|
// DEBT-0017: fallback for platforms that do not inject PlatformServices yet.
|
||||||
class LegacyPlatformServices final : public pp::platform::PlatformServices {
|
class LegacyPlatformServices final : public pp::platform::PlatformServices {
|
||||||
public:
|
public:
|
||||||
@@ -300,7 +342,13 @@ public:
|
|||||||
|
|
||||||
void publish_exported_image(std::string_view path) override
|
void publish_exported_image(std::string_view path) override
|
||||||
{
|
{
|
||||||
if (!pp::platform::platform_publishes_exported_images(pp::platform::current_platform_family()))
|
const auto family = pp::platform::current_platform_family();
|
||||||
|
if (family == pp::platform::PlatformFamily::webgl)
|
||||||
|
{
|
||||||
|
active_legacy_web_platform_services().publish_exported_image(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!pp::platform::platform_publishes_exported_images(family))
|
||||||
{
|
{
|
||||||
(void)path;
|
(void)path;
|
||||||
return;
|
return;
|
||||||
@@ -314,11 +362,14 @@ public:
|
|||||||
|
|
||||||
void flush_persistent_storage() override
|
void flush_persistent_storage() override
|
||||||
{
|
{
|
||||||
if (!pp::platform::platform_flushes_persistent_storage(pp::platform::current_platform_family()))
|
const auto family = pp::platform::current_platform_family();
|
||||||
|
if (family == pp::platform::PlatformFamily::webgl)
|
||||||
|
{
|
||||||
|
active_legacy_web_platform_services().flush_persistent_storage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!pp::platform::platform_flushes_persistent_storage(family))
|
||||||
return;
|
return;
|
||||||
#ifdef __WEB__
|
|
||||||
webgl_sync();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::vector<std::string> document_browse_roots(
|
[[nodiscard]] std::vector<std::string> document_browse_roots(
|
||||||
@@ -501,8 +552,10 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] int default_canvas_resolution() override
|
[[nodiscard]] int default_canvas_resolution() override
|
||||||
{
|
{
|
||||||
return pp::platform::platform_default_canvas_resolution(
|
const auto family = pp::platform::current_platform_family();
|
||||||
pp::platform::current_platform_family());
|
if (family == pp::platform::PlatformFamily::webgl)
|
||||||
|
return active_legacy_web_platform_services().default_canvas_resolution();
|
||||||
|
return pp::platform::platform_default_canvas_resolution(family);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool draws_canvas_tip_for_pointer(
|
[[nodiscard]] bool draws_canvas_tip_for_pointer(
|
||||||
@@ -591,6 +644,16 @@ public:
|
|||||||
std::string_view suggested_name,
|
std::string_view suggested_name,
|
||||||
pp::platform::PreparedFileCallback callback) override
|
pp::platform::PreparedFileCallback callback) override
|
||||||
{
|
{
|
||||||
|
const auto family = pp::platform::current_platform_family();
|
||||||
|
if (family == pp::platform::PlatformFamily::webgl)
|
||||||
|
{
|
||||||
|
active_legacy_web_platform_services().save_prepared_file(
|
||||||
|
path,
|
||||||
|
suggested_name,
|
||||||
|
std::move(callback));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string value(path);
|
const std::string value(path);
|
||||||
const std::string name(suggested_name);
|
const std::string name(suggested_name);
|
||||||
#ifdef __IOS__
|
#ifdef __IOS__
|
||||||
@@ -599,10 +662,6 @@ public:
|
|||||||
[App::I->ios_view pick_file_save:value];
|
[App::I->ios_view pick_file_save:value];
|
||||||
});
|
});
|
||||||
callback(value, true);
|
callback(value, true);
|
||||||
#elif __WEB__
|
|
||||||
webgl_pick_file_save(value, name, [callback = std::move(callback), value](bool success) {
|
|
||||||
callback(value, success);
|
|
||||||
});
|
|
||||||
#else
|
#else
|
||||||
(void)name;
|
(void)name;
|
||||||
callback(value, false);
|
callback(value, false);
|
||||||
|
|||||||
@@ -14,6 +14,67 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
class FakeWebPlatformServices final : public pp::platform::WebPlatformServices {
|
||||||
|
public:
|
||||||
|
void publish_exported_image(std::string_view path) override
|
||||||
|
{
|
||||||
|
++exported_image_publishes;
|
||||||
|
exported_image_path.assign(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_persistent_storage() override
|
||||||
|
{
|
||||||
|
++persistent_storage_flushes;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int default_canvas_resolution() override
|
||||||
|
{
|
||||||
|
++default_canvas_resolution_requests;
|
||||||
|
return canvas_resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_prepared_file(
|
||||||
|
std::string_view path,
|
||||||
|
std::string_view suggested_name,
|
||||||
|
pp::platform::PreparedFileCallback callback) override
|
||||||
|
{
|
||||||
|
++save_prepared_file_requests;
|
||||||
|
prepared_file_path.assign(path);
|
||||||
|
prepared_file_name.assign(suggested_name);
|
||||||
|
callback(prepared_file_path, prepared_file_saved);
|
||||||
|
}
|
||||||
|
|
||||||
|
int exported_image_publishes = 0;
|
||||||
|
int persistent_storage_flushes = 0;
|
||||||
|
int default_canvas_resolution_requests = 0;
|
||||||
|
int save_prepared_file_requests = 0;
|
||||||
|
int canvas_resolution = 2048;
|
||||||
|
bool prepared_file_saved = true;
|
||||||
|
std::string exported_image_path;
|
||||||
|
std::string prepared_file_path;
|
||||||
|
std::string prepared_file_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScopedInjectedWebPlatformServices final {
|
||||||
|
public:
|
||||||
|
explicit ScopedInjectedWebPlatformServices(pp::platform::WebPlatformServices* services)
|
||||||
|
: previous_(pp::platform::injected_web_platform_services())
|
||||||
|
{
|
||||||
|
pp::platform::set_injected_web_platform_services(services);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedInjectedWebPlatformServices()
|
||||||
|
{
|
||||||
|
pp::platform::set_injected_web_platform_services(previous_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedInjectedWebPlatformServices(const ScopedInjectedWebPlatformServices&) = delete;
|
||||||
|
ScopedInjectedWebPlatformServices& operator=(const ScopedInjectedWebPlatformServices&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pp::platform::WebPlatformServices* previous_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class FakePlatformServices final : public pp::platform::PlatformServices {
|
class FakePlatformServices final : public pp::platform::PlatformServices {
|
||||||
public:
|
public:
|
||||||
explicit FakePlatformServices(std::string clipboard_value)
|
explicit FakePlatformServices(std::string clipboard_value)
|
||||||
@@ -715,6 +776,68 @@ void platform_services_dispatch_prepared_file_save(pp::tests::Harness& harness)
|
|||||||
PP_EXPECT(harness, saved);
|
PP_EXPECT(harness, saved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void web_platform_services_preserve_default_web_policy(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
ScopedInjectedWebPlatformServices scoped(nullptr);
|
||||||
|
auto& services = pp::platform::active_web_platform_services();
|
||||||
|
std::string saved_path;
|
||||||
|
bool saved = true;
|
||||||
|
|
||||||
|
services.publish_exported_image("/PanoPainter/export.png");
|
||||||
|
services.flush_persistent_storage();
|
||||||
|
services.save_prepared_file(
|
||||||
|
"/PanoPainter/export.png",
|
||||||
|
"export.png",
|
||||||
|
[&](std::string path, bool success) {
|
||||||
|
saved_path = std::move(path);
|
||||||
|
saved = success;
|
||||||
|
});
|
||||||
|
|
||||||
|
PP_EXPECT(harness, services.default_canvas_resolution() == 512);
|
||||||
|
PP_EXPECT(harness, saved_path == "/PanoPainter/export.png");
|
||||||
|
PP_EXPECT(harness, !saved);
|
||||||
|
}
|
||||||
|
|
||||||
|
void web_platform_services_resolve_injected_services(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
FakeWebPlatformServices fallback;
|
||||||
|
FakeWebPlatformServices injected;
|
||||||
|
ScopedInjectedWebPlatformServices cleared(nullptr);
|
||||||
|
|
||||||
|
PP_EXPECT(harness, &pp::platform::resolve_web_platform_services(fallback) == &fallback);
|
||||||
|
|
||||||
|
{
|
||||||
|
ScopedInjectedWebPlatformServices scoped(&injected);
|
||||||
|
auto& services = pp::platform::active_web_platform_services();
|
||||||
|
std::string saved_path;
|
||||||
|
bool saved = false;
|
||||||
|
|
||||||
|
services.publish_exported_image("/PanoPainter/export.png");
|
||||||
|
services.flush_persistent_storage();
|
||||||
|
services.save_prepared_file(
|
||||||
|
"/PanoPainter/export.png",
|
||||||
|
"export.png",
|
||||||
|
[&](std::string path, bool success) {
|
||||||
|
saved_path = std::move(path);
|
||||||
|
saved = success;
|
||||||
|
});
|
||||||
|
|
||||||
|
PP_EXPECT(harness, &pp::platform::resolve_web_platform_services(fallback) == &injected);
|
||||||
|
PP_EXPECT(harness, services.default_canvas_resolution() == 2048);
|
||||||
|
PP_EXPECT(harness, injected.exported_image_publishes == 1);
|
||||||
|
PP_EXPECT(harness, injected.exported_image_path == "/PanoPainter/export.png");
|
||||||
|
PP_EXPECT(harness, injected.persistent_storage_flushes == 1);
|
||||||
|
PP_EXPECT(harness, injected.default_canvas_resolution_requests == 1);
|
||||||
|
PP_EXPECT(harness, injected.save_prepared_file_requests == 1);
|
||||||
|
PP_EXPECT(harness, injected.prepared_file_path == "/PanoPainter/export.png");
|
||||||
|
PP_EXPECT(harness, injected.prepared_file_name == "export.png");
|
||||||
|
PP_EXPECT(harness, saved_path == "/PanoPainter/export.png");
|
||||||
|
PP_EXPECT(harness, saved);
|
||||||
|
}
|
||||||
|
|
||||||
|
PP_EXPECT(harness, pp::platform::injected_web_platform_services() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void platform_services_dispatch_writable_file_target(pp::tests::Harness& harness)
|
void platform_services_dispatch_writable_file_target(pp::tests::Harness& harness)
|
||||||
{
|
{
|
||||||
FakePlatformServices fake("unused");
|
FakePlatformServices fake("unused");
|
||||||
@@ -1086,6 +1209,8 @@ int main()
|
|||||||
"platform services dispatch working directory picker policy",
|
"platform services dispatch working directory picker policy",
|
||||||
platform_services_dispatch_working_directory_picker_policy);
|
platform_services_dispatch_working_directory_picker_policy);
|
||||||
harness.run("platform services dispatch prepared file save", platform_services_dispatch_prepared_file_save);
|
harness.run("platform services dispatch prepared file save", platform_services_dispatch_prepared_file_save);
|
||||||
|
harness.run("web platform services preserve default web policy", web_platform_services_preserve_default_web_policy);
|
||||||
|
harness.run("web platform services resolve injected services", web_platform_services_resolve_injected_services);
|
||||||
harness.run("platform services dispatch writable file target", platform_services_dispatch_writable_file_target);
|
harness.run("platform services dispatch writable file target", platform_services_dispatch_writable_file_target);
|
||||||
harness.run(
|
harness.run(
|
||||||
"platform services dispatch document export collection policy",
|
"platform services dispatch document export collection policy",
|
||||||
|
|||||||
Reference in New Issue
Block a user