blob: 60773f241f9c85ba4f19994251bae47bc8ae2534 [file]
// Copyright 2015 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 "ui/views/mus/aura_init.h"
#include <utility>
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "services/catalog/public/cpp/resource_loader.h"
#include "services/catalog/public/interfaces/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "ui/aura/env.h"
#include "ui/base/ime/input_method_initializer.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/mus/mus_client.h"
#include "ui/views/style/typography_provider.h"
#include "ui/views/views_delegate.h"
#if defined(OS_LINUX)
#include "components/font_service/public/cpp/font_loader.h"
#include "ui/gfx/platform_font_linux.h"
#endif
namespace views {
namespace {
class MusViewsDelegate : public ViewsDelegate {
public:
MusViewsDelegate() {}
~MusViewsDelegate() override {}
private:
#if defined(OS_WIN)
HICON GetSmallWindowIcon() const override { return nullptr; }
#endif
void OnBeforeWidgetInit(
Widget::InitParams* params,
internal::NativeWidgetDelegate* delegate) override {}
LayoutProvider layout_provider_;
DISALLOW_COPY_AND_ASSIGN(MusViewsDelegate);
};
} // namespace
AuraInit::AuraInit() {
if (!ViewsDelegate::GetInstance())
views_delegate_ = std::make_unique<MusViewsDelegate>();
}
AuraInit::~AuraInit() {
#if defined(OS_LINUX)
if (font_loader_.get()) {
SkFontConfigInterface::SetGlobal(nullptr);
// FontLoader is ref counted. We need to explicitly shutdown the background
// thread, otherwise the background thread may be shutdown after the app is
// torn down, when we're in a bad state.
font_loader_->Shutdown();
}
#endif
}
std::unique_ptr<AuraInit> AuraInit::Create(
service_manager::Connector* connector,
const service_manager::Identity& identity,
const std::string& resource_file,
const std::string& resource_file_200,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
Mode mode,
bool register_path_provider) {
std::unique_ptr<AuraInit> aura_init = base::WrapUnique(new AuraInit());
if (!aura_init->Init(connector, identity, resource_file, resource_file_200,
io_task_runner, mode, register_path_provider)) {
aura_init.reset();
}
return aura_init;
}
bool AuraInit::Init(service_manager::Connector* connector,
const service_manager::Identity& identity,
const std::string& resource_file,
const std::string& resource_file_200,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
Mode mode,
bool register_path_provider) {
env_ = aura::Env::CreateInstance(
(mode == Mode::AURA_MUS || mode == Mode::AURA_MUS_WINDOW_MANAGER)
? aura::Env::Mode::MUS
: aura::Env::Mode::LOCAL);
if (mode == Mode::AURA_MUS) {
mus_client_ =
base::WrapUnique(new MusClient(connector, identity, io_task_runner));
}
// MaterialDesignController may have initialized already (such as happens
// in the utility process).
if (!ui::MaterialDesignController::is_mode_initialized())
ui::MaterialDesignController::Initialize();
if (!InitializeResources(connector, resource_file, resource_file_200,
register_path_provider)) {
return false;
}
// Initialize the skia font code to go ask fontconfig underneath.
#if defined(OS_LINUX)
font_loader_ = sk_make_sp<font_service::FontLoader>(connector);
SkFontConfigInterface::SetGlobal(font_loader_.get());
// Initialize static default font, by running this now, before any other apps
// load, we ensure all the state is set up.
bool success = gfx::PlatformFontLinux::InitDefaultFont();
// If a remote service manager has shut down, initializing the font will fail.
if (!success)
return false;
#endif // defined(OS_LINUX)
ui::InitializeInputMethodForTesting();
return true;
}
bool AuraInit::InitializeResources(service_manager::Connector* connector,
const std::string& resource_file,
const std::string& resource_file_200,
bool register_path_provider) {
// Resources may have already been initialized (e.g. when 'chrome --mash' is
// used to launch the current app).
if (ui::ResourceBundle::HasSharedInstance())
return true;
std::set<std::string> resource_paths({resource_file});
if (!resource_file_200.empty())
resource_paths.insert(resource_file_200);
catalog::ResourceLoader loader;
filesystem::mojom::DirectoryPtr directory;
connector->BindInterface(catalog::mojom::kServiceName, &directory);
// TODO(jonross): if this proves useful in resolving the crash of
// mash_unittests then switch AuraInit to have an Init method, returning a
// bool for success. Then update all callsites to use this to determine the
// shutdown of their ServiceContext.
// One cause of failure is that the peer has closed, but we have not been
// notified yet. It is not possible to complete initialization, so exit now.
// Calling services will shutdown ServiceContext as appropriate.
if (!loader.OpenFiles(std::move(directory), resource_paths))
return false;
if (register_path_provider)
ui::RegisterPathProvider();
base::File pak_file = loader.TakeFile(resource_file);
base::File pak_file_2 = pak_file.Duplicate();
ui::ResourceBundle::InitSharedInstanceWithPakFileRegion(
std::move(pak_file), base::MemoryMappedFile::Region::kWholeFile);
ui::ResourceBundle::GetSharedInstance().AddDataPackFromFile(
std::move(pak_file_2), ui::SCALE_FACTOR_100P);
if (!resource_file_200.empty())
ui::ResourceBundle::GetSharedInstance().AddDataPackFromFile(
loader.TakeFile(resource_file_200), ui::SCALE_FACTOR_200P);
return true;
}
} // namespace views