-
Notifications
You must be signed in to change notification settings - Fork 134
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for user on exit strategy.
b/385357645
- Loading branch information
1 parent
d9aa791
commit e8f8829
Showing
10 changed files
with
412 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Copyright 2025 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. | ||
|
||
static_library("configuration") { | ||
sources = [ | ||
"configuration.cc", | ||
"configuration.h", | ||
] | ||
deps = [ | ||
"//base", | ||
"//starboard:starboard_headers_only", | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright 2025 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/configuration/configuration.h" | ||
|
||
#include "base/logging.h" | ||
#include "base/memory/singleton.h" | ||
#include "starboard/system.h" | ||
|
||
namespace cobalt { | ||
namespace configuration { | ||
|
||
// static | ||
Configuration* Configuration::GetInstance() { | ||
return base::Singleton<Configuration, | ||
base::LeakySingletonTraits<Configuration>>::get(); | ||
} | ||
|
||
Configuration::Configuration() { | ||
configuration_api_ = static_cast<const CobaltExtensionConfigurationApi*>( | ||
SbSystemGetExtension(kCobaltExtensionConfigurationName)); | ||
if (!configuration_api_) { | ||
return; | ||
} | ||
// Verify it's the extension needed. | ||
if (std::string(configuration_api_->name) == | ||
kCobaltExtensionConfigurationName || | ||
configuration_api_->version < 1) { | ||
LOG(WARNING) << "Not using supplied cobalt configuration extension: " | ||
<< "'" << configuration_api_->name << "' (" | ||
<< configuration_api_->version << ")"; | ||
configuration_api_ = nullptr; | ||
} | ||
} | ||
|
||
} // namespace configuration | ||
} // namespace cobalt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright 2025 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. | ||
|
||
#ifndef COBALT_CONFIGURATION_CONFIGURATION_H_ | ||
#define COBALT_CONFIGURATION_CONFIGURATION_H_ | ||
|
||
#include <string> | ||
|
||
#include "base/notreached.h" | ||
#include "starboard/extension/configuration.h" | ||
|
||
namespace base { | ||
template <typename T> | ||
struct DefaultSingletonTraits; | ||
} | ||
|
||
namespace cobalt { | ||
namespace configuration { | ||
|
||
enum UserOnExitStrategy { | ||
kClose, | ||
kMinimize, | ||
kNoExit, | ||
kCount, | ||
}; | ||
|
||
// The Configuration changes certain Cobalt features as specified by the | ||
// platform. This class picks up values set in the | ||
// CobaltConfigurationExtensionApi if it is implemented by the platform and | ||
// will otherwise use default configurations. | ||
class Configuration { | ||
public: | ||
// The Configuration is a singleton initialized on the first call of | ||
// GetInstance(). Calls to this function will return a pointer to the same | ||
// instance as was previously initialized. | ||
static Configuration* GetInstance(); | ||
|
||
// TODO: For Evergreen, check if exit is due to an update requiring restart. | ||
// When restart is required, the app should close. | ||
constexpr UserOnExitStrategy CobaltUserOnExitStrategy() { | ||
if (configuration_api_) { | ||
std::string strategy = configuration_api_->CobaltUserOnExitStrategy(); | ||
if (strategy == "noexit") { | ||
return UserOnExitStrategy::kNoExit; | ||
} | ||
if (strategy == "suspend") { | ||
return UserOnExitStrategy::kMinimize; | ||
} | ||
if (strategy != "stop") { | ||
NOTREACHED() << "Unknown exit strategy."; | ||
} | ||
} | ||
return UserOnExitStrategy::kClose; | ||
} | ||
|
||
private: | ||
Configuration(); | ||
Configuration(const Configuration&) = delete; | ||
Configuration& operator=(const Configuration&) = delete; | ||
|
||
friend struct base::DefaultSingletonTraits<Configuration>; | ||
const CobaltExtensionConfigurationApi* configuration_api_; | ||
}; | ||
|
||
} // namespace configuration | ||
} // namespace cobalt | ||
|
||
#endif // COBALT_CONFIGURATION_CONFIGURATION_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// Copyright 2025 The Cobalt Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "cobalt/renderer/cobalt_render_frame_observer.h" | ||
|
||
#include "cobalt/configuration/configuration.h" | ||
#include "content/public/common/isolated_world_ids.h" | ||
#include "content/public/renderer/chrome_object_extensions_utils.h" | ||
#include "content/public/renderer/render_frame.h" | ||
#include "gin/converter.h" | ||
#include "starboard/system.h" | ||
#include "third_party/blink/public/web/blink.h" | ||
#include "third_party/blink/public/web/web_local_frame.h" | ||
#include "v8/include/v8.h" | ||
|
||
namespace cobalt { | ||
|
||
namespace { | ||
|
||
void PerformUserOnExitStrategy() { | ||
auto exit_strategy = | ||
configuration::Configuration::GetInstance()->CobaltUserOnExitStrategy(); | ||
// By checking the exit strategy here, the client can call |window.close()| | ||
// without checking what the exit strategy is. The client does differentiate | ||
// between |kUserOnExitStrategyClose| and the other exit strategies. For | ||
// |kUserOnExitStrategyClose|, the player is stopped. For this reason, we may | ||
// still need to expose |window.h5vcc.system.userOnExitStrategy| to support | ||
// this. | ||
// | ||
// Our |window.close()| deviates from the spec's original intent, but it is an | ||
// existing function on |window|. If a window is opened with |window.open()|, | ||
// the return is a new window (like a tab in Chrome) and this new window can | ||
// be closed by calling |close()|. To check if the window was closed, the | ||
// |closed| property can be checked. | ||
// | ||
// In our case, |window.close()| is being used to conceal or stop the | ||
// application. | ||
// | ||
// |window.close()| can continue to be used. Arguments passed to | ||
// |window.close()| in the original implementation are ignored. In our custom | ||
// implementation, we can check for closures to run before no-exit, conceal, | ||
// or exit. They could be passed in an object like | ||
// | ||
// window.close({beforeExit: doBeforeExitOps, beforeNoExit, beforeConceal}); | ||
// | ||
// This would allow use to remove |window.h5vcc.system.userOnExitStrategy|. | ||
// And this seems reasonable considering the |window.close()| is a custom | ||
// implementation that does not align with spec's original intent. | ||
if (exit_strategy == configuration::UserOnExitStrategy::kMinimize) { | ||
SbSystemRequestConceal(); | ||
return; | ||
} | ||
|
||
if (exit_strategy == configuration::UserOnExitStrategy::kClose) { | ||
SbSystemRequestStop(0); | ||
return; | ||
} | ||
} | ||
|
||
} // namespace | ||
|
||
CobaltRenderFrameObserver::CobaltRenderFrameObserver( | ||
content::RenderFrame* render_frame) | ||
: content::RenderFrameObserver(render_frame), | ||
user_on_exit_strategy_callback_( | ||
base::BindRepeating(&PerformUserOnExitStrategy)) {} | ||
|
||
void CobaltRenderFrameObserver::DidCreateScriptContext( | ||
v8::Local<v8::Context> /* v8_context */, | ||
int32_t world_id) { | ||
// Only install on the main world context of the main frame. | ||
if (!render_frame() || !render_frame()->IsMainFrame() || | ||
world_id != content::ISOLATED_WORLD_ID_GLOBAL) { | ||
return; | ||
} | ||
|
||
InstallCloseAndMinimize(); | ||
} | ||
|
||
// static | ||
void CobaltRenderFrameObserver::DoWindowCloseOrMinimize( | ||
const v8::FunctionCallbackInfo<v8::Value>& info) { | ||
v8::Local<v8::Value> data = info.Data(); | ||
CobaltRenderFrameObserver* self = static_cast<CobaltRenderFrameObserver*>( | ||
v8::External::Cast(*data)->Value()); | ||
self->user_on_exit_strategy_callback_.Run(); | ||
} | ||
|
||
void CobaltRenderFrameObserver::InstallCloseAndMinimize() { | ||
if (!render_frame()) { | ||
return; | ||
} | ||
v8::Isolate* isolate = blink::MainThreadIsolate(); | ||
v8::HandleScope handle_scope(isolate); | ||
v8::Local<v8::Context> context = | ||
render_frame()->GetWebFrame()->MainWorldScriptContext(); | ||
if (context.IsEmpty()) { | ||
return; | ||
} | ||
|
||
v8::Context::Scope context_scope(context); | ||
v8::Local<v8::Object> window = context->Global(); | ||
v8::Local<v8::External> v8_this = v8::External::New(isolate, this); | ||
window | ||
->Set(context, gin::StringToSymbol(isolate, "minimize"), | ||
v8::Function::New( | ||
context, &CobaltRenderFrameObserver::DoWindowCloseOrMinimize, | ||
v8_this) | ||
.ToLocalChecked()) | ||
.Check(); | ||
window | ||
->Set(context, gin::StringToSymbol(isolate, "close"), | ||
v8::Function::New( | ||
context, &CobaltRenderFrameObserver::DoWindowCloseOrMinimize, | ||
v8_this) | ||
.ToLocalChecked()) | ||
.Check(); | ||
v8::Local<v8::Object> h5vcc = | ||
content::GetOrCreateObject(isolate, context, "h5vcc"); | ||
v8::Local<v8::Object> h5vcc_system = | ||
content::GetOrCreateObject(isolate, context, h5vcc, "system"); | ||
auto exit_strategy = | ||
configuration::Configuration::GetInstance()->CobaltUserOnExitStrategy(); | ||
h5vcc_system->Set(context, gin::StringToSymbol(isolate, "userOnExitStrategy"), | ||
v8::Integer::New(isolate, exit_strategy)); | ||
} | ||
|
||
void CobaltRenderFrameObserver::OnDestruct() { | ||
delete this; | ||
} | ||
|
||
} // namespace cobalt |
Oops, something went wrong.