blob: 973527e1186bf9a9be3bd4c796a4bf81b23e8bc8 [file] [log] [blame]
// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/browser/lib/exported/main.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "cobalt/base/wrap_main.h"
#include "cobalt/browser/application.h"
#include "starboard/event.h"
#include "starboard/input.h"
namespace {
cobalt::browser::Application* g_application = NULL;
typedef base::Callback<void(void)> InitializedCallback;
typedef base::Callback<bool(const SbEvent*)> HandleEventCallback;
static base::LazyInstance<InitializedCallback>::DestructorAtExit
g_on_cobalt_initialized_callback = LAZY_INSTANCE_INITIALIZER;
static base::LazyInstance<HandleEventCallback>::DestructorAtExit
g_handle_event_callback = LAZY_INSTANCE_INITIALIZER;
// We cannot use LazyInstance here as this can be set before Cobalt has been
// initialized at all - thus there will not yet exist an AtExitManager which
// means the app would crash if we tried to replace the lazy instance too
// early. Instead, for this one callback, we simply do things manually.
CbLibMainCallbackRegistrationReadyCallback g_callback_registration_ready =
nullptr;
void* g_registration_ready_context = nullptr;
void PreloadApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
const base::Closure& quit_closure) {
LOG(INFO) << "Preloading application.";
DCHECK(!g_application);
CHECK(g_callback_registration_ready);
// Register a default event handler up front.
CbLibMainSetHandleEventCallback(nullptr, nullptr);
g_callback_registration_ready(g_registration_ready_context);
g_application =
new cobalt::browser::Application(quit_closure, true /*should_preload*/);
DCHECK(g_application);
}
void StartApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
const base::Closure& quit_closure) {
LOG(INFO) << "Starting application.";
if (!g_application) {
CHECK(g_callback_registration_ready);
// Register a default event handler up front.
CbLibMainSetHandleEventCallback(nullptr, nullptr);
g_callback_registration_ready(g_registration_ready_context);
g_application = new cobalt::browser::Application(quit_closure,
false /*should_preload*/);
DCHECK(g_application);
} else {
g_application->Start();
}
DCHECK(g_application);
if (!g_on_cobalt_initialized_callback.Get().is_null())
g_on_cobalt_initialized_callback.Get().Run();
}
void StopApplication() {
DCHECK(g_application);
LOG(INFO) << "Stopping application.";
delete g_application;
g_application = NULL;
}
void HandleStarboardEvent(const SbEvent* starboard_event) {
if (!g_application) {
return;
}
// TODO(dworsham): Host-generated input events will also be fed through the
// host callback, leading to re-entrancy issues. Set up a way of filtering
// them somehow.
//
// For now, works fine with YTVR as only input events are generated by the
// host and the host also ignores all input events sent its way.
if (!g_handle_event_callback.Get().Run(starboard_event)) {
g_application->HandleStarboardEvent(starboard_event);
}
}
} // namespace
COBALT_WRAP_MAIN(PreloadApplication, StartApplication, HandleStarboardEvent,
StopApplication);
void CbLibMainSetCallbackRegistrationReadyCallback(
void* context, CbLibMainOnCobaltInitializedCallback callback) {
g_registration_ready_context = context;
g_callback_registration_ready = callback;
}
void CbLibMainSetOnCobaltInitializedCallback(
void* context, CbLibMainOnCobaltInitializedCallback callback) {
g_on_cobalt_initialized_callback.Get() =
callback ? base::Bind(callback, context) : InitializedCallback();
}
void CbLibMainSetHandleEventCallback(void* context,
CbLibMainHandleEventCallback callback) {
// If the user passes nullptr, provide a default event handler so that it is
// never actually null.
g_handle_event_callback.Get() =
callback ? base::Bind(callback, context)
: base::Bind([](const SbEvent*) { return false; });
}
SbWindow CbLibMainGetSbWindow() {
auto* primary_window = cobalt::system_window::SystemWindow::PrimaryWindow();
return primary_window ? primary_window->GetSbWindow() : nullptr;
}