├── .gitignore ├── .vscode └── settings.json ├── BUILD.gn ├── README.md ├── README_zh.md ├── common └── utils.h ├── demo.cc ├── demo_android ├── BUILD.gn ├── demo_android_skia │ ├── AndroidManifest.xml │ ├── BUILD.gn │ ├── README.md │ ├── cpp │ │ ├── demo_android_skia_library_loader.cc │ │ ├── skia_canvas.cc │ │ ├── skia_canvas.h │ │ ├── skia_canvas_gl.cc │ │ ├── skia_canvas_gl.h │ │ ├── skia_canvas_software.cc │ │ ├── skia_canvas_software.h │ │ └── trace_android.h │ ├── gapid_opengles_trace.gfxtrace │ ├── res │ │ ├── layout │ │ │ └── main_activity.xml │ │ ├── mipmap-hdpi │ │ │ └── app_icon.png │ │ └── values │ │ │ └── strings.xml │ ├── src │ │ └── org │ │ │ └── demo │ │ │ ├── demo_android_skia │ │ │ ├── DemoAndroidSkiaActivity.java │ │ │ └── DemoAndroidSkiaApplication.java │ │ │ └── demo_jni │ │ │ └── SkiaCanvas.java │ └── systrace_data.zip └── demo_apk │ ├── AndroidManifest.xml │ ├── BUILD.gn │ ├── README.md │ ├── cpp │ ├── demo_apk_library_loader.cc │ ├── demo_foo.cc │ └── demo_foo.h │ ├── res │ ├── layout │ │ └── demo_apk_activity.xml │ ├── mipmap-hdpi │ │ └── app_icon.png │ └── values │ │ └── strings.xml │ └── src │ └── org │ └── chromium │ ├── demo_apk │ ├── DemoApkActivity.java │ └── DemoApkApplication.java │ └── demo_jni │ └── DemoFoo.java ├── demo_cc ├── BUILD.gn ├── README.md ├── TRACE.txt ├── demo_cc_gui.cc └── demo_cc_offscreen.cc ├── demo_gl ├── BUILD.gn ├── README.md └── demo_gl.cc ├── demo_ipc.cc ├── demo_ipc_message_generator.cc ├── demo_ipc_message_generator.h ├── demo_ipc_messages.h ├── demo_log.cc ├── demo_memory.cc ├── demo_mojo_multiple_process.cc ├── demo_mojo_multiple_process_binding.cc ├── demo_mojo_single_process.cc ├── demo_resources ├── BUILD.gn ├── demo_resource_ids ├── demo_resources.cc ├── demo_resources.grd ├── demo_resources_zh-CN.xtb ├── demo_strings.grd └── demo_strings_zh-CN.xtb ├── demo_services.cc ├── demo_shell ├── BUILD.gn ├── README.md ├── android │ ├── BUILD.gn │ ├── demo_shell_descriptors.h │ ├── demo_shell_library_loader.cc │ ├── demo_shell_manager.cc │ ├── demo_shell_manager.h │ ├── java │ │ ├── res │ │ │ ├── layout │ │ │ │ └── shell_view.xml │ │ │ ├── mipmap-hdpi │ │ │ │ └── app_icon.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── app_icon.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── app_icon.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── app_icon.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── app_icon.png │ │ │ └── values │ │ │ │ └── strings.xml │ │ └── src │ │ │ └── org │ │ │ └── chromium │ │ │ └── demo_shell │ │ │ ├── Shell.java │ │ │ ├── ShellManager.java │ │ │ └── ShellViewAndroidDelegate.java │ └── shell_apk │ │ ├── AndroidManifest.xml.jinja2 │ │ ├── res │ │ ├── layout │ │ │ └── demo_shell_activity.xml │ │ └── values │ │ │ └── strings.xml │ │ └── src │ │ └── org │ │ └── chromium │ │ └── demo_shell_apk │ │ ├── DemoShellActivity.java │ │ └── DemoShellApplication.java ├── app │ ├── demo_shell_content_main_delegate.cc │ ├── demo_shell_content_main_delegate.h │ └── demo_shell_main.cc ├── browser │ ├── demo_shell_browser_context.cc │ ├── demo_shell_browser_context.h │ ├── demo_shell_browser_main_parts.cc │ ├── demo_shell_browser_main_parts.h │ ├── demo_shell_content_browser_client.cc │ ├── demo_shell_content_browser_client.h │ ├── demo_shell_download_manager_delegate.cc │ ├── demo_shell_download_manager_delegate.h │ ├── demo_shell_permission_manager.cc │ ├── demo_shell_permission_manager.h │ ├── demo_shell_platform_data_aura.cc │ ├── demo_shell_platform_data_aura.h │ ├── shell.cc │ ├── shell.h │ ├── shell_android.cc │ └── shell_views.cc ├── common │ ├── demo_shell_content_client.cc │ ├── demo_shell_content_client.h │ ├── demo_shell_origin_trial_policy.cc │ ├── demo_shell_origin_trial_policy.h │ ├── demo_shell_switches.cc │ └── demo_shell_switches.h ├── demo_shell_resources.grd ├── renderer │ ├── demo_shell_content_renderer_client.cc │ └── demo_shell_content_renderer_client.h ├── resource_ids ├── resources │ ├── README.txt │ ├── brokenCanvas.png │ └── shell_devtools_discovery_page.html ├── utility │ ├── demo_shell_content_utility_client.cc │ └── demo_shell_content_utility_client.h └── version.h.in ├── demo_skia ├── BUILD.gn ├── README.md ├── demo_skia.cc ├── skia_canvas.cc ├── skia_canvas.h ├── skia_canvas_gl.cc ├── skia_canvas_gl.h ├── skia_canvas_software.cc └── skia_canvas_software.h ├── demo_tasks.cc ├── demo_tracing ├── BUILD.gn ├── README.md ├── demo_tracing_console.cc ├── demo_tracing_perfetto.cc └── demo_tracing_perfetto_content.cc ├── demo_views ├── BUILD.gn ├── README.md └── demo_views.cc ├── demo_viz ├── BUILD.gn ├── README.md ├── demo_viz_gui.cc ├── demo_viz_gui_gpu.cc ├── demo_viz_layer.cc ├── demo_viz_layer_offscreen.cc ├── demo_viz_layer_offscreen_client.cc ├── demo_viz_layer_offscreen_client.h └── demo_viz_offscreen.cc ├── demo_x11 ├── BUILD.gn ├── README.md ├── demo_x11.cc ├── demo_x11_egl.cc └── demo_x11_glx.cc ├── docs ├── content.md ├── images │ ├── 2020-01-03-09-53-49.png │ ├── 2020-01-03-10-00-48.png │ ├── 2020-01-03-10-01-55.png │ ├── 2020-01-03-13-48-06.png │ ├── 2020-01-03-13-49-40.png │ ├── 2020-01-03-14-13-56.png │ ├── 2020-01-03-15-10-02.png │ ├── 2020-01-03-17-09-31.png │ ├── 2020-05-22-17-09-02.png │ ├── chromium-mojo-layer.png │ ├── mojo_interface_pipe.png │ └── mojo_stack.png ├── mojo.md ├── startup.md ├── tracing.md ├── ui.md └── viz.md ├── mojom ├── consumer_service_manifest.json ├── test.mojom ├── test2.mojom ├── test3.mojom ├── test4.mojom ├── test_service.mojom └── test_service_manifest.json └── patches └── 0001-demo_viz_layer_offscreen-add-GetOffscreenTextureId.patch /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/c++,tags,code,ninja 3 | # Edit at https://www.gitignore.io/?templates=c++,tags,code,ninja 4 | 5 | ### C++ ### 6 | # Prerequisites 7 | *.d 8 | 9 | # Compiled Object files 10 | *.slo 11 | *.lo 12 | *.o 13 | *.obj 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Compiled Dynamic libraries 20 | *.so 21 | *.dylib 22 | *.dll 23 | 24 | # Fortran module files 25 | *.mod 26 | *.smod 27 | 28 | # Compiled Static libraries 29 | *.lai 30 | *.la 31 | *.a 32 | *.lib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | 39 | ### Code ### 40 | .vscode/* 41 | !.vscode/settings.json 42 | !.vscode/tasks.json 43 | !.vscode/launch.json 44 | !.vscode/extensions.json 45 | 46 | ### Ninja ### 47 | .ninja_deps 48 | .ninja_log 49 | 50 | ### Tags ### 51 | # Ignore tags created by etags, ctags, gtags (GNU global) and cscope 52 | TAGS 53 | .TAGS 54 | !TAGS/ 55 | tags 56 | .tags 57 | !tags/ 58 | gtags.files 59 | GTAGS 60 | GRTAGS 61 | GPATH 62 | GSYMS 63 | cscope.files 64 | cscope.out 65 | cscope.in.out 66 | cscope.po.out 67 | 68 | 69 | # End of https://www.gitignore.io/api/c++,tags,code,ninja 70 | 71 | *.xmb 72 | 73 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.gni": "python", 4 | "string": "cpp", 5 | "bitset": "cpp", 6 | "forward_list": "cpp", 7 | "functional": "cpp", 8 | "list": "cpp", 9 | "memory": "cpp", 10 | "tuple": "cpp", 11 | "*.tcc": "cpp", 12 | "__tree": "cpp", 13 | "algorithm": "cpp", 14 | "random": "cpp", 15 | "optional": "cpp", 16 | "system_error": "cpp", 17 | "regex": "cpp" 18 | }, 19 | "commentTranslate.targetLanguage": "zh-CN", 20 | "pasteImage.filePathConfirmInputBoxMode": "onlyName", 21 | "pasteImage.path": "${currentFileDir}/images" 22 | } -------------------------------------------------------------------------------- /BUILD.gn: -------------------------------------------------------------------------------- 1 | # for mojo 2 | import("//mojo/public/tools/bindings/mojom.gni") 3 | 4 | group("demo") { 5 | testonly = true 6 | # 除非特殊说明,所有demo仅在Linux上进行测试,其他平台未经测试 7 | deps = [ 8 | ":demo_exe", 9 | ":demo_log", 10 | "demo_tracing", 11 | ":demo_messageloop", 12 | ":demo_tasks", 13 | ":demo_mojo_single_process", 14 | ":demo_mojo_multiple_process", 15 | ":demo_mojo_multiple_process_binding", 16 | ":demo_services", 17 | ":demo_ipc", 18 | ":demo_memory", 19 | "demo_resources", 20 | "demo_gl", 21 | "demo_viz", 22 | "demo_cc", 23 | "demo_x11", 24 | "demo_skia", 25 | "demo_views", 26 | "demo_android", 27 | "demo_shell", 28 | ] 29 | 30 | if(!is_linux) { 31 | deps -= [ 32 | ":demo_services", 33 | "demo_views", 34 | "demo_gl", 35 | "demo_viz", 36 | "demo_cc", 37 | "demo_skia", 38 | "demo_x11", 39 | ] 40 | } 41 | } 42 | 43 | executable("demo_exe") { 44 | sources = [ 45 | "demo.cc", 46 | ] 47 | 48 | deps = [ 49 | "//base", 50 | ] 51 | } 52 | 53 | executable("demo_log") { 54 | sources = [ 55 | "demo_log.cc", 56 | ] 57 | 58 | deps = [ 59 | "//base", 60 | ] 61 | } 62 | 63 | executable("demo_messageloop") { 64 | sources = [ 65 | "demo_tasks.cc", 66 | ] 67 | 68 | defines = ["DEMO_MESSAGE_LOOP"] 69 | 70 | deps = [ 71 | "//base", 72 | ] 73 | } 74 | 75 | executable("demo_tasks") { 76 | sources = [ 77 | "demo_tasks.cc", 78 | ] 79 | 80 | defines = ["DEMO_TASK"] 81 | 82 | deps = [ 83 | "//base", 84 | ] 85 | } 86 | 87 | executable("demo_memory") { 88 | sources = [ 89 | "demo_memory.cc", 90 | ] 91 | 92 | deps = [ 93 | "//base", 94 | ] 95 | } 96 | 97 | executable("demo_mojo_single_process") { 98 | testonly = true 99 | sources = [ 100 | "demo_mojo_single_process.cc", 101 | ] 102 | 103 | deps = [ 104 | "//base", 105 | "//mojo/public", 106 | "//mojo/core/embedder", 107 | ] 108 | } 109 | 110 | executable("demo_mojo_multiple_process") { 111 | testonly = true 112 | sources = [ 113 | "demo_mojo_multiple_process.cc", 114 | ] 115 | 116 | deps = [ 117 | ":mojom_test", 118 | ":mojom_test2", 119 | "//base", 120 | "//mojo/public", 121 | "//mojo/core/embedder", 122 | ] 123 | } 124 | 125 | executable("demo_mojo_multiple_process_binding") { 126 | testonly = true 127 | sources = [ 128 | "demo_mojo_multiple_process_binding.cc", 129 | ] 130 | 131 | deps = [ 132 | "//base", 133 | "//mojo/public", 134 | "//mojo/core/embedder", 135 | ":mojom_test", 136 | ":mojom_test2", 137 | ":mojom_test3", 138 | ":mojom_test4", 139 | ] 140 | } 141 | 142 | executable("demo_services") { 143 | testonly = true 144 | sources = [ 145 | "demo_services.cc", 146 | ] 147 | 148 | deps = [ 149 | ":mojom_test_service", 150 | "//base", 151 | # TODO: 查明为什么这里必须显式依赖base_static,它明明已经作为base的public_deps了, 152 | # 难道public_deps对静态库(base_static)无效? 153 | "//base:base_static", 154 | "//mojo/public", 155 | "//services/service_manager", 156 | "//services/service_manager/embedder", 157 | "//services/service_manager/public/cpp/service_executable:support" 158 | ] 159 | } 160 | 161 | executable("demo_ipc") { 162 | testonly = true 163 | sources = [ 164 | "demo_ipc.cc", 165 | "demo_ipc_messages.h", 166 | "demo_ipc_message_generator.h", 167 | "demo_ipc_message_generator.cc", 168 | ] 169 | 170 | deps = [ 171 | "//base", 172 | "//base:base_static", 173 | "//mojo/public", 174 | "//services/service_manager/embedder", 175 | ] 176 | 177 | deps += [ "//services/service_manager:all" ] 178 | } 179 | 180 | mojom("mojom_test") { 181 | sources = [ 182 | "mojom/test.mojom", 183 | ] 184 | } 185 | 186 | mojom("mojom_test2") { 187 | sources = [ 188 | "mojom/test2.mojom", 189 | ] 190 | } 191 | 192 | mojom("mojom_test3") { 193 | sources = [ 194 | "mojom/test3.mojom", 195 | ] 196 | } 197 | 198 | mojom("mojom_test4") { 199 | sources = [ 200 | "mojom/test4.mojom", 201 | ] 202 | } 203 | 204 | mojom("mojom_test_service") { 205 | sources = [ 206 | "mojom/test_service.mojom", 207 | ] 208 | } 209 | 210 | -------------------------------------------------------------------------------- /common/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_COMMON_UTILS_H 2 | #define DEMO_COMMON_UTILS_H 3 | 4 | #include "base/base_paths.h" 5 | #include "base/bind.h" 6 | #include "base/callback.h" 7 | #include "base/command_line.h" 8 | #include "base/files/file.h" 9 | #include "base/files/file_path.h" 10 | #include "base/logging.h" 11 | #include "base/memory/ref_counted_memory.h" 12 | #include "base/threading/thread.h" 13 | #include "base/trace_event/trace_buffer.h" 14 | 15 | namespace demo { 16 | 17 | std::unique_ptr& trace_file() { 18 | static std::unique_ptr g_trace_file; 19 | return g_trace_file; 20 | } 21 | 22 | void InitTrace(const std::string& file) { 23 | trace_file() = std::make_unique( 24 | base::FilePath(file), base::File::FLAG_OPEN_ALWAYS | 25 | base::File::FLAG_WRITE | 26 | base::File::FLAG_OPEN_TRUNCATED); 27 | DCHECK(trace_file()->IsValid()); 28 | trace_file()->WriteAtCurrentPos("[", 1); 29 | DLOG(INFO) << "Init trace file: " << file; 30 | } 31 | 32 | void StartTrace(const std::string& categories = "",base::trace_event::TraceRecordMode mode = base::trace_event::RECORD_AS_MUCH_AS_POSSIBLE) { 33 | DLOG(INFO) << "Start trace: " << categories; 34 | static std::string categories_; 35 | if (!categories.empty()) 36 | categories_ = categories; 37 | // 配置及启动 Trace 38 | base::trace_event::TraceConfig trace_config = 39 | base::trace_event::TraceConfig(categories_,mode); 40 | base::trace_event::TraceLog::GetInstance()->SetEnabled( 41 | trace_config, base::trace_event::TraceLog::RECORDING_MODE); 42 | } 43 | 44 | void FlushTrace(base::RepeatingClosure quit_closure) { 45 | DLOG(INFO) << "Flush trace begin."; 46 | 47 | base::trace_event::TraceLog::GetInstance()->SetDisabled(); 48 | base::trace_event::TraceLog::GetInstance()->Flush(base::BindRepeating( 49 | [](base::OnceClosure quit_closure, 50 | const scoped_refptr& events_str, 51 | bool has_more_events) { 52 | // LOG(INFO) << std::endl << events_str->data(); 53 | trace_file()->WriteAtCurrentPos(events_str->data().c_str(), 54 | events_str->size()); 55 | trace_file()->WriteAtCurrentPos(",\n", 2); 56 | if (!has_more_events) { 57 | trace_file()->WriteAtCurrentPos("\n", 1); 58 | trace_file()->Flush(); 59 | DLOG(INFO) << "Flush trace end."; 60 | if (quit_closure) 61 | std::move(quit_closure).Run(); 62 | } 63 | }, 64 | std::move(quit_closure))); 65 | } 66 | 67 | } // namespace demo 68 | 69 | #endif // !DEMO_COMMON_UTILS_H 70 | -------------------------------------------------------------------------------- /demo.cc: -------------------------------------------------------------------------------- 1 | #include "base/at_exit.h" 2 | #include "base/command_line.h" 3 | #include "base/logging.h" 4 | #include "base/message_loop/message_loop.h" 5 | #include "base/task/thread_pool/thread_pool_instance.h" 6 | 7 | int main(int argc, char** argv) { 8 | // 类似C++的 atexit() 方法,用于管理程序的销毁逻辑,base::Singleton类依赖它 9 | base::AtExitManager at_exit; 10 | // 初始化CommandLine 11 | base::CommandLine::Init(argc, argv); 12 | // 设置日志格式 13 | logging::SetLogItems(true,false,true,false); 14 | // 创建主消息循环 15 | base::MessageLoop message_loop; 16 | // 初始化线程池,会创建新的线程,在新的线程中会创建新消息循环MessageLoop 17 | base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Demo"); 18 | 19 | // 复制当前文件来创建新的demo 20 | LOG(INFO) << "hello,world!"; 21 | 22 | LOG(INFO) << "running..."; 23 | base::RunLoop().Run(); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /demo_android/BUILD.gn: -------------------------------------------------------------------------------- 1 | 2 | group("demo_android") { 3 | testonly = true 4 | if(is_android) { 5 | deps = [ 6 | "demo_apk", 7 | "demo_android_skia", 8 | ] 9 | } else { 10 | print("demo_apk only support android.") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/BUILD.gn: -------------------------------------------------------------------------------- 1 | import("//build/config/android/config.gni") 2 | import("//build/config/android/rules.gni") 3 | #import("//third_party/icu/config.gni") 4 | 5 | android_resources("demo_android_skia_resources") { 6 | testonly = true 7 | resource_dirs = [ "res" ] 8 | custom_package = "org.demo.demo_android_skia" 9 | } 10 | 11 | # 从Java类生成JNI接口,用于让C++和JAVA可以互相调用 12 | # 详见文档://base/android/jni_generator/README.md 13 | generate_jni("demo_android_skia_jni_headers") { 14 | sources = [ 15 | "src/org/demo/demo_jni/SkiaCanvas.java", 16 | ] 17 | } 18 | 19 | android_library("demo_android_skia_java") { 20 | testonly = true 21 | 22 | #srcjar_deps = [ ":demo_javatests_aidl" ] 23 | 24 | deps = [ 25 | #":demo_android_skia_manifest", 26 | ":demo_android_skia_resources", 27 | ":demo_android_skia_jni_headers", 28 | "//base:base_java", 29 | "//base:jni_java", 30 | #"//ui/android:ui_java", 31 | ] 32 | 33 | java_files = [ 34 | "src/org/demo/demo_android_skia/DemoAndroidSkiaActivity.java", 35 | "src/org/demo/demo_android_skia/DemoAndroidSkiaApplication.java", 36 | "src/org/demo/demo_jni/SkiaCanvas.java", 37 | ] 38 | 39 | #android_manifest_for_lint = demo_android_skia_manifest 40 | annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] 41 | } 42 | 43 | # native 动态库,实现JNI接口 44 | shared_library("libdemo_android_skia") { 45 | testonly = true 46 | sources = [ 47 | "cpp/demo_android_skia_library_loader.cc", 48 | "cpp/skia_canvas.cc", 49 | "cpp/skia_canvas.h", 50 | "cpp/skia_canvas_software.cc", 51 | "cpp/skia_canvas_software.h", 52 | "cpp/skia_canvas_gl.cc", 53 | "cpp/skia_canvas_gl.h", 54 | ] 55 | deps = [ 56 | ":demo_android_skia_jni_headers", 57 | "//base", 58 | # 直接依赖它会导致和chromium中的变量定义冲突 59 | #"//third_party/skia", 60 | "//skia", 61 | ] 62 | 63 | defines = ["GR_TEST_UTILS=1"] 64 | 65 | libs = ["EGL","GLESv2"] 66 | 67 | configs -= [ "//build/config/android:hide_all_but_jni_onload" ] 68 | configs += [ "//build/config/android:hide_all_but_jni" ] 69 | } 70 | 71 | # 定义生成apk的target,详见://build/config/android/rules.gni 72 | android_apk("demo_android_skia") { 73 | testonly = true 74 | apk_name = "DemoAndroidSkia" 75 | android_manifest = "AndroidManifest.xml" 76 | #android_manifest_dep = ":demo_android_skia_manifest" 77 | shared_libraries = [ ":libdemo_android_skia" ] 78 | #loadable_modules = [ "$root_out_dir/libchrome_crashpad_handler.so" ] 79 | command_line_flags_file = "demo-apk-command-line" 80 | 81 | # 默认的 min 和 target 分别为 19,23,这里修改是为了去除在21:9的屏幕上的黑边 82 | min_sdk_version = 23 83 | target_sdk_version = 26 84 | 85 | deps = [ 86 | ":demo_android_skia_java", 87 | "//base:base_java", 88 | "//base:base_java_test_support", 89 | #"//ui/android:ui_java", 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/README.md: -------------------------------------------------------------------------------- 1 | # demo_android_skia 2 | 3 | 这个 demo 用于演示在 Android 中使用 skia 进行绘图,主要用来演示使用 skia 进行软件渲染和硬件渲染的性能差异,顺便演示 chromium 的渲染和 android 对接的方式。 4 | 5 | 在 demo 中主要演示了划线的功能,对比 chromium 中 canvas 的划线,这里演示的方法应该是 canvas 划线的性能上限,可以用来评估 chromium 渲染引入的性能损失情况。 6 | 7 | - [gapid_opengles_trace.gfxtrace](./gapid_opengles_trace.gfxtrace) 是通过 [gapid](https://github.com/google/gapid) 抓到的 OpenGLES API 的调用数据。 8 | - [systrace_data.zip](./systrace_data.zip) 是通过 [systrace](https://developer.android.com/topic/performance/tracing/command-line#app-trace) 抓到的 trace 数据,解压后可以使用浏览器直接打开。 9 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/cpp/demo_android_skia_library_loader.cc: -------------------------------------------------------------------------------- 1 | #include "base/android/jni_android.h" 2 | // #include "content/public/app/content_jni_onload.h" 3 | // #include "content/public/app/content_main.h" 4 | 5 | #include "base/android/base_jni_onload.h" 6 | #include "base/logging.h" 7 | 8 | //#include "demo/demo_shell/app/demo_shell_content_main_delegate.h" 9 | 10 | JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { 11 | DLOG(INFO) << "[demo_android_skia] JNI_OnLoad start"; 12 | // 这个初始化是必要的,因为LibraryLoader依赖它,大量的base::android::*都依赖它 13 | // 它其实就是将vm保存为了内部的全局变量 14 | base::android::InitVM(vm); 15 | // 下面这个初始化在这个程序中不是必须的,但是推荐加上,主要是初始化了ClassLoader 16 | if (!base::android::OnJNIOnLoadInit()) 17 | return false; 18 | 19 | // 我们没有使用(crazy linker)动态注册JNI函数的方式,所以这里不需要以下代码 20 | // if (!RegisterMainDexNatives(env) || !RegisterNonMainDexNatives(env)) { 21 | // return -1; 22 | // } 23 | 24 | DLOG(INFO) << "[demo_android_skia] JNI_OnLoad finished"; 25 | return JNI_VERSION_1_4; 26 | } 27 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/cpp/skia_canvas.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_DEMO_ANDROID_SKIA_CANVAS_H 2 | #define DEMO_DEMO_ANDROID_SKIA_CANVAS_H 3 | 4 | #include 5 | 6 | #include "android/native_window_jni.h" 7 | #include "base/android/jni_android.h" 8 | #include "base/android/scoped_java_ref.h" 9 | #include "base/threading/thread.h" 10 | #include "base/sequenced_task_runner.h" 11 | 12 | #include "third_party/skia/include/core/SkBitmap.h" 13 | #include "third_party/skia/include/core/SkCanvas.h" 14 | #include "third_party/skia/include/core/SkPath.h" 15 | #include "third_party/skia/include/core/SkImageInfo.h" 16 | #include "third_party/skia/include/core/SkSurface.h" 17 | 18 | #include "base/timer/timer.h" 19 | 20 | namespace demo_jni { 21 | 22 | class SkiaCanvas { 23 | public: 24 | void OnTouch(JNIEnv* env, int action, jfloat x, jfloat y); 25 | 26 | protected: 27 | SkiaCanvas(JNIEnv* env, 28 | const base::android::JavaParamRef& caller, 29 | const base::android::JavaParamRef& surface); 30 | virtual void InitializeOnRenderThread(); 31 | virtual SkCanvas* BeginPaint() = 0; 32 | virtual void OnPaint(SkCanvas* canvas) {} 33 | virtual void SwapBuffer() = 0; 34 | void SetNeedsRedraw(bool need_redraw); 35 | void ShowInfo(std::string info); 36 | 37 | const base::android::ScopedJavaGlobalRef caller_; 38 | // SurfaceView 对应的 Window 39 | ANativeWindow* nativeWindow_; 40 | int width_; 41 | int height_; 42 | 43 | sk_sp skSurface_ = nullptr; 44 | SkPaint pathPaint_; 45 | SkPaint circlePaint_; 46 | SkPath skPath_; 47 | SkScalar strokeWidth_ = 5.f; 48 | SkColor background_ = SK_ColorBLACK; 49 | std::string tag_; 50 | bool need_redraw_ = false; 51 | bool is_drawing_ = false; 52 | base::TimeDelta total_frame_time_; 53 | base::TimeTicks last_frame_time_; 54 | unsigned int frame_count_ = 0; 55 | base::TimeDelta total_paint_time_; 56 | base::TimeDelta total_swap_time_; 57 | 58 | unsigned int touch_count_ = 0; 59 | base::TimeTicks touch_start_time_; 60 | base::TimeDelta total_touch_time_; 61 | 62 | private: 63 | void OnTouchOnRenderThread(int action, jfloat x, jfloat y); 64 | void OnRenderOnRenderThread(); 65 | void ShowFrameRateOnRenderThread(); 66 | base::Thread render_thread_; 67 | scoped_refptr render_task_runner_; 68 | base::RepeatingTimer timer_; 69 | base::RepeatingClosure render_closure_; 70 | base::WeakPtrFactory weak_factory_{this}; 71 | }; 72 | 73 | } // namespace demo_jni 74 | 75 | #endif // DEMO_DEMO_ANDROID_SKIA_CANVAS_H -------------------------------------------------------------------------------- /demo_android/demo_android_skia/cpp/skia_canvas_gl.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_DEMO_ANDROID_SKIA_CANVAS_GL_H 2 | #define DEMO_DEMO_ANDROID_SKIA_CANVAS_GL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #ifndef GL_GLEXT_PROTOTYPES 9 | #define GL_GLEXT_PROTOTYPES 10 | #endif 11 | #include 12 | 13 | #include "base/android/jni_android.h" 14 | #include "base/android/scoped_java_ref.h" 15 | 16 | #include "android/native_window_jni.h" 17 | 18 | #include "demo/demo_android/demo_android_skia/cpp/skia_canvas.h" 19 | 20 | #include "third_party/skia/include/gpu/GrContext.h" 21 | #include "third_party/skia/include/gpu/GrContextOptions.h" 22 | #include "third_party/skia/include/gpu/gl/GrGLInterface.h" 23 | #include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h" 24 | 25 | namespace demo_jni { 26 | 27 | class SkiaCanvasGL : public SkiaCanvas { 28 | public: 29 | SkiaCanvasGL(JNIEnv* env, 30 | const base::android::JavaParamRef& caller, 31 | const base::android::JavaParamRef& surface); 32 | 33 | private: 34 | void InitializeOnRenderThread() override; 35 | SkCanvas* BeginPaint() override; 36 | void OnPaint(SkCanvas* canvas) override; 37 | void SwapBuffer() override; 38 | 39 | EGLDisplay display_; 40 | EGLContext context_; 41 | EGLSurface surface_; 42 | EGLint stencilBits_; 43 | EGLint sampleCount_; 44 | sk_sp grGLInterface_; 45 | sk_sp grContext_; 46 | bool use_ddl_ = false; 47 | std::unique_ptr recorder_; 48 | }; 49 | 50 | } // namespace demo_jni 51 | 52 | #endif // DEMO_DEMO_ANDROID_SKIA_CANVAS_GL_H -------------------------------------------------------------------------------- /demo_android/demo_android_skia/cpp/skia_canvas_software.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "demo/demo_android/demo_android_skia/cpp/skia_canvas_software.h" 3 | 4 | #include "base/android/jni_android.h" 5 | #include "base/android/jni_string.h" 6 | #include "base/android/scoped_java_ref.h" 7 | #include "base/bind.h" 8 | #include "base/lazy_instance.h" 9 | 10 | namespace demo_jni { 11 | 12 | SkiaCanvasSoftware::SkiaCanvasSoftware( 13 | JNIEnv* env, 14 | const base::android::JavaParamRef& caller, 15 | const base::android::JavaParamRef& jsurface) 16 | : SkiaCanvas(env, caller, jsurface) { 17 | background_ = 0xFF00DE96; 18 | tag_ = "SkiaCanvasSoftware"; 19 | } 20 | 21 | void SkiaCanvasSoftware::InitializeOnRenderThread() { 22 | 23 | ANativeWindow_setBuffersGeometry(nativeWindow_, width_, height_, 24 | WINDOW_FORMAT_RGB_565); 25 | 26 | // 当 format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4 27 | // 时,一个像素占2个字节,所以x2 28 | // memset(buffer.bits, 0xAA, buffer.stride * buffer.height * 2); 29 | 30 | auto canvas = BeginPaint(); 31 | canvas->clear(background_); 32 | //canvas->drawCircle(20, 20, 20, circlePaint_); 33 | SwapBuffer(); 34 | SkiaCanvas::InitializeOnRenderThread(); 35 | } 36 | 37 | SkCanvas* SkiaCanvasSoftware::BeginPaint() { 38 | ANativeWindow_Buffer buffer; 39 | DCHECK(ANativeWindow_lock(nativeWindow_, &buffer, &dirtyRect_)==0); 40 | SkImageInfo info = SkImageInfo::Make(width_, height_, kRGB_565_SkColorType, 41 | kPremul_SkAlphaType, nullptr); 42 | skSurface_ = SkSurface::MakeRasterDirect(info, buffer.bits, buffer.stride * 2, 43 | nullptr); 44 | return skSurface_->getCanvas(); 45 | } 46 | 47 | void SkiaCanvasSoftware::OnPaint(SkCanvas* canvas) { 48 | skSurface_->flush(); 49 | } 50 | 51 | void SkiaCanvasSoftware::SwapBuffer() { 52 | ANativeWindow_unlockAndPost(nativeWindow_); 53 | } 54 | 55 | } // namespace demo_jni -------------------------------------------------------------------------------- /demo_android/demo_android_skia/cpp/skia_canvas_software.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_DEMO_ANDROID_SKIA_CANVAS_SOFTWARE_H 2 | #define DEMO_DEMO_ANDROID_SKIA_CANVAS_SOFTWARE_H 3 | 4 | #include 5 | 6 | #include "base/android/jni_android.h" 7 | #include "base/android/scoped_java_ref.h" 8 | 9 | #include "android/native_window_jni.h" 10 | 11 | #include "demo/demo_android/demo_android_skia/cpp/skia_canvas.h" 12 | 13 | namespace demo_jni { 14 | 15 | class SkiaCanvasSoftware : public SkiaCanvas { 16 | public: 17 | SkiaCanvasSoftware(JNIEnv* env, 18 | const base::android::JavaParamRef& caller, 19 | const base::android::JavaParamRef& surface); 20 | void InitializeOnRenderThread() override; 21 | void OnPaint(SkCanvas* canvas) override; 22 | 23 | private: 24 | SkCanvas* BeginPaint() override; 25 | void SwapBuffer() override; 26 | 27 | ARect dirtyRect_; 28 | }; 29 | 30 | } // namespace demo_jni 31 | 32 | #endif // DEMO_DEMO_ANDROID_SKIA_CANVAS_SOFTWARE_H -------------------------------------------------------------------------------- /demo_android/demo_android_skia/cpp/trace_android.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_DEMO_ANDROID_DEMO_ANDROID_SKIA_CPP_TRACE_ANDROID_H 2 | #define DEMO_DEMO_ANDROID_DEMO_ANDROID_SKIA_CPP_TRACE_ANDROID_H 3 | 4 | #include 5 | #include 6 | #include "base/logging.h" 7 | 8 | namespace demo_jni { 9 | 10 | namespace { 11 | void* (*ATrace_beginSection)(const char* sectionName); 12 | void* (*ATrace_endSection)(void); 13 | } // namespace 14 | 15 | #define ATRACE_NAME(name) ScopedTrace ___tracer(name) 16 | 17 | // ATRACE_CALL is an ATRACE_NAME that uses the current function name. 18 | #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__) 19 | 20 | class ScopedTrace { 21 | public: 22 | typedef void* (*fp_ATrace_beginSection)(const char* sectionName); 23 | typedef void* (*fp_ATrace_endSection)(void); 24 | 25 | static bool Initialize() { 26 | // Retrieve a handle to libandroid. 27 | void* lib = dlopen("libandroid.so", RTLD_NOW); 28 | DCHECK(lib); 29 | // Access the native tracing functions. 30 | if (lib != nullptr) { 31 | // Use dlsym() to prevent crashes on devices running Android 5.1 32 | // (API level 22) or lower. 33 | ATrace_beginSection = reinterpret_cast( 34 | dlsym(lib, "ATrace_beginSection")); 35 | ATrace_endSection = reinterpret_cast( 36 | dlsym(lib, "ATrace_endSection")); 37 | return true; 38 | } 39 | return false; 40 | } 41 | 42 | inline ScopedTrace(const char* name) { ATrace_beginSection(name); } 43 | 44 | inline ~ScopedTrace() { ATrace_endSection(); } 45 | }; 46 | 47 | } // namespace demo_jni 48 | 49 | #endif // !DEMO_DEMO_ANDROID_DEMO_ANDROID_SKIA_CPP_TRACE_ANDROID_H -------------------------------------------------------------------------------- /demo_android/demo_android_skia/gapid_opengles_trace.gfxtrace: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_android/demo_android_skia/gapid_opengles_trace.gfxtrace -------------------------------------------------------------------------------- /demo_android/demo_android_skia/res/layout/main_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 16 | 25 | 36 | 43 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/res/mipmap-hdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_android/demo_android_skia/res/mipmap-hdpi/app_icon.png -------------------------------------------------------------------------------- /demo_android/demo_android_skia/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 上面的色块使用Skia的软件渲染。\n下面的色块使用Skia的OpenGLES硬件渲染。 4 | Hello,DemoAndroidSkia! 5 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/src/org/demo/demo_android_skia/DemoAndroidSkiaActivity.java: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | package org.demo.demo_android_skia; 6 | 7 | import android.app.Activity; 8 | import android.content.Intent; 9 | import android.os.Bundle; 10 | import android.util.Log; 11 | import android.view.SurfaceHolder; 12 | import android.view.SurfaceView; 13 | import android.view.View; 14 | import android.widget.TextView; 15 | import android.view.MotionEvent; 16 | import android.os.Trace; 17 | 18 | import org.chromium.base.CommandLine; 19 | import org.chromium.base.library_loader.LibraryLoader; 20 | import org.chromium.base.library_loader.LibraryProcessType; 21 | import org.chromium.base.TraceEvent; 22 | 23 | import org.demo.demo_jni.SkiaCanvas; 24 | 25 | /** 26 | * Activity for managing the Demo shell. 27 | */ 28 | public class DemoAndroidSkiaActivity extends Activity 29 | implements SurfaceHolder.Callback, SkiaCanvas.Callback, View.OnTouchListener { 30 | 31 | private static final String TAG = "DemoAndroidSkia"; 32 | 33 | public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs"; 34 | private TextView mTextView; 35 | 36 | @Override 37 | protected void onCreate(final Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.main_activity); 40 | 41 | // Initializing the command line must occur before loading the library. 42 | if (!CommandLine.isInitialized()) { 43 | ((DemoAndroidSkiaApplication) getApplication()).initCommandLine(); 44 | String[] commandLineParams = getCommandLineParamsFromIntent(getIntent()); 45 | if (commandLineParams == null) { 46 | commandLineParams = new String[] {"--enable-idle-tracing"}; 47 | } 48 | CommandLine.getInstance().appendSwitchesAndArguments(commandLineParams); 49 | } 50 | 51 | // 加载JNI库 52 | LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER); 53 | mTextView = (TextView) findViewById(R.id.text); 54 | 55 | SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceViewSoftware); 56 | surfaceView.getHolder().addCallback(this); 57 | surfaceView.setOnTouchListener(this); 58 | 59 | surfaceView = (SurfaceView) findViewById(R.id.surfaceViewGL); 60 | surfaceView.getHolder().addCallback(this); 61 | surfaceView.setOnTouchListener(this); 62 | } 63 | 64 | private static String[] getCommandLineParamsFromIntent(Intent intent) { 65 | return intent != null ? intent.getStringArrayExtra(COMMAND_LINE_ARGS_KEY) : null; 66 | } 67 | 68 | public void onClick(View view) { 69 | Log.i(TAG, "Call onClick"); 70 | } 71 | 72 | SkiaCanvas mCanvasSoftware; 73 | SkiaCanvas mCanvasGL; 74 | 75 | @Override 76 | public void surfaceCreated(SurfaceHolder holder) { 77 | Log.i(TAG, "surfaceCreated"); 78 | if (mCanvasSoftware == null && ((SurfaceView) findViewById(R.id.surfaceViewSoftware)).getHolder() == holder) 79 | mCanvasSoftware = new SkiaCanvas(holder.getSurface(), this, false); 80 | else if (mCanvasGL == null && ((SurfaceView) findViewById(R.id.surfaceViewGL)).getHolder() == holder) 81 | mCanvasGL = new SkiaCanvas(holder.getSurface(), this, true); 82 | } 83 | 84 | @Override 85 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 86 | Log.i(TAG, "surfaceChanged"); 87 | } 88 | 89 | @Override 90 | public void surfaceDestroyed(SurfaceHolder holder) { 91 | Log.i(TAG, "surfaceDestroyed"); 92 | } 93 | 94 | @Override 95 | public boolean onTouch(View v, MotionEvent event) { 96 | try (TraceEvent e = TraceEvent.scoped("DemoAndroidSkiaActivity.onTouch")) { 97 | Trace.beginSection("DemoAndroidSkiaActivity.onTouch"); 98 | int count = event.getPointerCount(); 99 | for (int i = 0; i < count; i++) { 100 | final float x = event.getX(i); 101 | final float y = event.getY(i); 102 | final int owner = event.getPointerId(i); 103 | Log.i(TAG, "" + x + "," + y); 104 | int action = event.getAction() & MotionEvent.ACTION_MASK; 105 | if (v.getId() == R.id.surfaceViewSoftware) 106 | mCanvasSoftware.onTouch(action, x, y); 107 | else 108 | mCanvasGL.onTouch(action, x, y); 109 | } 110 | 111 | Trace.endSection(); 112 | return true; 113 | } 114 | } 115 | 116 | @Override 117 | public void showInfo(String info) { 118 | mTextView.setText(info); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/src/org/demo/demo_android_skia/DemoAndroidSkiaApplication.java: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | package org.demo.demo_android_skia; 6 | 7 | import android.app.Application; 8 | import android.content.Context; 9 | import android.view.Display; 10 | import android.view.WindowManager; 11 | import android.util.Log; 12 | import android.view.Choreographer; 13 | 14 | import java.lang.reflect.Field; 15 | import java.lang.reflect.Modifier; 16 | 17 | import org.chromium.base.ApplicationStatus; 18 | import org.chromium.base.BuildConfig; 19 | import org.chromium.base.CommandLine; 20 | import org.chromium.base.ContextUtils; 21 | import org.chromium.base.PathUtils; 22 | import org.chromium.base.multidex.ChromiumMultiDexInstaller; 23 | 24 | /** 25 | * Entry point for the demo apk application. Handles initialization of 26 | * information that needs to be shared across the main activity and the child 27 | * services created. 28 | */ 29 | public class DemoAndroidSkiaApplication extends Application { 30 | public static final String COMMAND_LINE_FILE = "/data/local/tmp/demo-apk-command-line"; 31 | private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "demo_android_skia"; 32 | private static final String TAG = "DemoAndroidSkiaApplication"; 33 | 34 | public DemoAndroidSkiaApplication() { 35 | try { 36 | setFinalStatic(Choreographer.class.getDeclaredField("USE_VSYNC"), false); 37 | 38 | } catch (Exception e) { 39 | Log.e(TAG,e.toString()); 40 | } 41 | } 42 | 43 | @Override 44 | protected void attachBaseContext(Context base) { 45 | super.attachBaseContext(base); 46 | // SystemProperties.getBoolean("debug.choreographer.vsync"); 47 | boolean isBrowserProcess = !ContextUtils.getProcessName().contains(":"); 48 | ContextUtils.initApplicationContext(this); 49 | if (isBrowserProcess) { 50 | if (BuildConfig.IS_MULTIDEX_ENABLED) { 51 | ChromiumMultiDexInstaller.install(this); 52 | } 53 | PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX); 54 | ApplicationStatus.initialize(this); 55 | } 56 | 57 | Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 58 | float refreshRating = display.getRefreshRate(); 59 | Log.e(TAG, "Refresh Rating: " + refreshRating); 60 | } 61 | 62 | public void initCommandLine() { 63 | if (!CommandLine.isInitialized()) { 64 | CommandLine.initFromFile(COMMAND_LINE_FILE); 65 | } 66 | } 67 | 68 | static void setFinalStatic(Field field, Object newValue) throws Exception { 69 | field.setAccessible(true); 70 | 71 | Field modifiersField = Field.class.getDeclaredField("modifiers"); 72 | modifiersField.setAccessible(true); 73 | modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 74 | 75 | field.set(null, newValue); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /demo_android/demo_android_skia/src/org/demo/demo_jni/SkiaCanvas.java: -------------------------------------------------------------------------------- 1 | 2 | package org.demo.demo_jni; 3 | 4 | import android.util.Log; 5 | import android.view.Surface; 6 | 7 | import java.lang.String; 8 | 9 | import org.chromium.base.annotations.CalledByNative; 10 | import org.chromium.base.annotations.JNINamespace; 11 | import org.chromium.base.annotations.NativeMethods; 12 | 13 | @JNINamespace("demo_jni") 14 | public class SkiaCanvas { 15 | 16 | public interface Callback { 17 | public void showInfo(String info); 18 | } 19 | 20 | private static final String TAG = "DemoAndroidSkia.SkiaCanvas"; 21 | private long mNativeSkiaCanvas; 22 | private Callback mCallback; 23 | 24 | public SkiaCanvas(Surface surface,Callback callback, boolean useGL) { 25 | mCallback = callback; 26 | mNativeSkiaCanvas = SkiaCanvasJni.get().init(this, surface, useGL); 27 | } 28 | 29 | public void onTouch(int action,float x,float y){ 30 | SkiaCanvasJni.get().onTouch(mNativeSkiaCanvas, action, x, y); 31 | } 32 | 33 | @CalledByNative 34 | public void showInfo(String info) { 35 | Log.i(TAG, "info: " + info); 36 | mCallback.showInfo(info); 37 | } 38 | 39 | // 固定格式,用于定义并生成JNI接口 40 | @NativeMethods 41 | public interface Natives { 42 | // 初始化,传入Java的this,返回C++的this 43 | long init(SkiaCanvas caller, Surface surface, boolean useGL); 44 | 45 | void onTouch(long nativeSkiaCanvas,int action, float x, float y); 46 | } 47 | } -------------------------------------------------------------------------------- /demo_android/demo_android_skia/systrace_data.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_android/demo_android_skia/systrace_data.zip -------------------------------------------------------------------------------- /demo_android/demo_apk/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /demo_android/demo_apk/BUILD.gn: -------------------------------------------------------------------------------- 1 | import("//build/config/android/config.gni") 2 | import("//build/config/android/rules.gni") 3 | import("//third_party/icu/config.gni") 4 | 5 | # 可以使用 jinja 模板来生成 Manifest 6 | # 这里不使用jinja模板,直接像普通的Android一样提前写好 7 | # demo_apk_manifest = "$target_gen_dir/demo_apk_manifest_jinja/AndroidManifest.xml" 8 | # jinja_template("demo_apk_manifest") { 9 | # testonly = true 10 | # input = "AndroidManifest.xml.jinja2" 11 | # output = demo_apk_manifest 12 | # variables = [ "manifest_package=org.chromium.demo_apk" ] 13 | # } 14 | 15 | android_resources("demo_apk_resources") { 16 | testonly = true 17 | resource_dirs = [ "res" ] 18 | custom_package = "org.chromium.demo_apk" 19 | } 20 | 21 | # 从Java类生成JNI接口,用于让C++和JAVA可以互相调用 22 | # 详见文档://base/android/jni_generator/README.md 23 | generate_jni("demo_apk_jni_headers") { 24 | sources = [ 25 | "src/org/chromium/demo_jni/DemoFoo.java", 26 | ] 27 | } 28 | 29 | android_library("demo_apk_java") { 30 | testonly = true 31 | 32 | #srcjar_deps = [ ":demo_javatests_aidl" ] 33 | 34 | deps = [ 35 | #":demo_apk_manifest", 36 | ":demo_apk_resources", 37 | ":demo_apk_jni_headers", 38 | "//base:base_java", 39 | "//base:jni_java", 40 | "//ui/android:ui_java", 41 | ] 42 | 43 | java_files = [ 44 | "src/org/chromium/demo_apk/DemoApkActivity.java", 45 | "src/org/chromium/demo_apk/DemoApkApplication.java", 46 | "src/org/chromium/demo_jni/DemoFoo.java", 47 | ] 48 | 49 | #android_manifest_for_lint = demo_apk_manifest 50 | annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] 51 | } 52 | 53 | # native 动态库,实现JNI接口 54 | shared_library("libdemo_apk") { 55 | testonly = true 56 | sources = [ 57 | "cpp/demo_apk_library_loader.cc", 58 | "cpp/demo_foo.cc", 59 | "cpp/demo_foo.h", 60 | ] 61 | deps = [ 62 | ":demo_apk_jni_headers", 63 | "//base", 64 | ] 65 | 66 | configs -= [ "//build/config/android:hide_all_but_jni_onload" ] 67 | configs += [ "//build/config/android:hide_all_but_jni" ] 68 | } 69 | 70 | # 定义生成apk的target,详见://build/config/android/rules.gni 71 | android_apk("demo_apk") { 72 | testonly = true 73 | apk_name = "DemoApk" 74 | android_manifest = "AndroidManifest.xml" 75 | #android_manifest_dep = ":demo_apk_manifest" 76 | shared_libraries = [ ":libdemo_apk" ] 77 | #loadable_modules = [ "$root_out_dir/libchrome_crashpad_handler.so" ] 78 | command_line_flags_file = "demo-apk-command-line" 79 | 80 | # 默认的 min 和 target 分别为 19,23,这里修改是为了去除在21:9的屏幕上的黑边 81 | min_sdk_version = 23 82 | target_sdk_version = 26 83 | 84 | deps = [ 85 | ":demo_apk_java", 86 | "//base:base_java", 87 | "//base:base_java_test_support", 88 | "//ui/android:ui_java", 89 | ] 90 | } 91 | -------------------------------------------------------------------------------- /demo_android/demo_apk/README.md: -------------------------------------------------------------------------------- 1 | # demo_apk 2 | 3 | `demo_apk` 可以构建出一名为`DemoApk.apk`的Android应用,它和普通的Android应用最大的不同就是构建方式。一般的Android开发者使用AndroidStudio等IDE来构建Android应用,在chromium中不使用这些IDE而使用gn。 4 | 5 | chromium提供了一套gn配置用来打包各种Android组件,包括 apk,aar,jar 等。主要的脚本位于`//build/config/android/`目录下。可以重点查看以下两个文件: 6 | 7 | ```gn 8 | //build/config/android/config.gni 9 | //build/config/android/rules.gni 10 | ``` 11 | 12 | ## demo_apk 构成 13 | 14 | demo_apk 由以下几部分组成: 15 | 16 | 1. `AndroidManifest.xml`:Android应用的描述文件,包括权限定义,icon等; 17 | 2. `res`: Android应用的资源文件,包括UI布局,图片,字符串等; 18 | 3. `src`: 源代码文件; 19 | 4. `cpp`: 保存 JNI 相关代码; 20 | 21 | ## JNI 22 | 23 | gn提供了从java代码生成JNI/C++头文件的脚本,具体信息参考`base/android/jni_generator/README.md`。 -------------------------------------------------------------------------------- /demo_android/demo_apk/cpp/demo_apk_library_loader.cc: -------------------------------------------------------------------------------- 1 | #include "base/android/jni_android.h" 2 | // #include "content/public/app/content_jni_onload.h" 3 | // #include "content/public/app/content_main.h" 4 | 5 | #include "base/android/base_jni_onload.h" 6 | #include "base/logging.h" 7 | 8 | //#include "demo/demo_shell/app/demo_shell_content_main_delegate.h" 9 | 10 | JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { 11 | DLOG(INFO) << "[demo_apk] JNI_OnLoad start"; 12 | // 这个初始化是必要的,因为LibraryLoader依赖它,大量的base::android::*都依赖它 13 | // 它其实就是将vm保存为了内部的全局变量 14 | base::android::InitVM(vm); 15 | // 下面这个初始化在这个程序中不是必须的,但是推荐加上,主要是初始化了ClassLoader 16 | if (!base::android::OnJNIOnLoadInit()) 17 | return false; 18 | 19 | // 我们没有使用(crazy linker)动态注册JNI函数的方式,所以这里不需要以下代码 20 | // if (!RegisterMainDexNatives(env) || !RegisterNonMainDexNatives(env)) { 21 | // return -1; 22 | // } 23 | 24 | DLOG(INFO) << "[demo_apk] JNI_OnLoad finished"; 25 | return JNI_VERSION_1_4; 26 | } 27 | -------------------------------------------------------------------------------- /demo_android/demo_apk/cpp/demo_foo.cc: -------------------------------------------------------------------------------- 1 | #include "demo/demo_android/demo_apk/cpp/demo_foo.h" 2 | 3 | #include "base/android/jni_android.h" 4 | #include "base/android/jni_string.h" 5 | #include "base/android/scoped_java_ref.h" 6 | #include "base/bind.h" 7 | #include "base/lazy_instance.h" 8 | 9 | #include "demo/demo_android/demo_apk/demo_apk_jni_headers/DemoFoo_jni.h" 10 | 11 | namespace demo_jni { 12 | 13 | base::android::ScopedJavaGlobalRef j_demo_foo; 14 | 15 | void DemoFoo::HelloDemoFoo(JNIEnv* env, const base::android::JavaParamRef& who) { 16 | LOG(INFO)<<"[demo_foo] DemoFoo::HelloDemoFoo: Hello," << base::android::ConvertJavaStringToUTF8(env, who); 17 | } 18 | 19 | static jlong JNI_DemoFoo_Init(JNIEnv* env, const base::android::JavaParamRef& caller) { 20 | DLOG(INFO) << "[demo_apk]================ JNI_DemoFoo_Init"; 21 | j_demo_foo.Reset(caller); 22 | return reinterpret_cast(new DemoFoo()); 23 | } 24 | 25 | static void JNI_DemoFoo_Hello(JNIEnv* env, const base::android::JavaParamRef& who) { 26 | LOG(INFO)<<"[demo_foo] JNI_DemoFoo_Hello: Hello,"< 5 | 6 | #include "base/android/jni_android.h" 7 | #include "base/android/scoped_java_ref.h" 8 | 9 | namespace demo_jni { 10 | 11 | class DemoFoo { 12 | public: 13 | void HelloDemoFoo(JNIEnv* env, const base::android::JavaParamRef& who); 14 | }; 15 | 16 | void Hi(std::string who); 17 | void HiStatic(std::string who); 18 | } 19 | 20 | #endif //DEMO_DEMO_ANDROID_DEMO_FOO_H -------------------------------------------------------------------------------- /demo_android/demo_apk/res/layout/demo_apk_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 16 | 25 | 26 | -------------------------------------------------------------------------------- /demo_android/demo_apk/res/mipmap-hdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_android/demo_apk/res/mipmap-hdpi/app_icon.png -------------------------------------------------------------------------------- /demo_android/demo_apk/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello,DemoApk! 4 | -------------------------------------------------------------------------------- /demo_android/demo_apk/src/org/chromium/demo_apk/DemoApkActivity.java: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | package org.chromium.demo_apk; 6 | 7 | import android.app.Activity; 8 | import android.content.Intent; 9 | import android.os.Bundle; 10 | import android.util.Log; 11 | import android.view.View; 12 | 13 | import org.chromium.base.CommandLine; 14 | import org.chromium.base.library_loader.LibraryLoader; 15 | import org.chromium.base.library_loader.LibraryProcessType; 16 | 17 | import org.chromium.demo_jni.DemoFoo; 18 | 19 | /** 20 | * Activity for managing the Demo shell. 21 | */ 22 | public class DemoApkActivity extends Activity { 23 | 24 | private static final String TAG = "DemoApk.DemoApkActivity"; 25 | 26 | public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs"; 27 | 28 | @Override 29 | protected void onCreate(final Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | 32 | // Initializing the command line must occur before loading the library. 33 | if (!CommandLine.isInitialized()) { 34 | ((DemoApkApplication) getApplication()).initCommandLine(); 35 | String[] commandLineParams = getCommandLineParamsFromIntent(getIntent()); 36 | if (commandLineParams != null) { 37 | CommandLine.getInstance().appendSwitchesAndArguments(commandLineParams); 38 | } 39 | } 40 | 41 | setContentView(R.layout.demo_apk_activity); 42 | } 43 | 44 | private static String[] getCommandLineParamsFromIntent(Intent intent) { 45 | return intent != null ? intent.getStringArrayExtra(COMMAND_LINE_ARGS_KEY) : null; 46 | } 47 | 48 | public void onClick(View view) { 49 | Log.i(TAG,"Call onClick"); 50 | 51 | // 加载JNI库 52 | LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER); 53 | 54 | DemoFoo foo = new DemoFoo(); 55 | foo.Hello("JNI"); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /demo_android/demo_apk/src/org/chromium/demo_apk/DemoApkApplication.java: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | package org.chromium.demo_apk; 6 | 7 | import android.app.Application; 8 | import android.content.Context; 9 | 10 | import org.chromium.base.ApplicationStatus; 11 | import org.chromium.base.BuildConfig; 12 | import org.chromium.base.CommandLine; 13 | import org.chromium.base.ContextUtils; 14 | import org.chromium.base.PathUtils; 15 | import org.chromium.base.multidex.ChromiumMultiDexInstaller; 16 | import org.chromium.ui.base.ResourceBundle; 17 | 18 | /** 19 | * Entry point for the demo apk application. Handles initialization of information that needs 20 | * to be shared across the main activity and the child services created. 21 | */ 22 | public class DemoApkApplication extends Application { 23 | public static final String COMMAND_LINE_FILE = "/data/local/tmp/demo-apk-command-line"; 24 | private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "demo_apk"; 25 | 26 | @Override 27 | protected void attachBaseContext(Context base) { 28 | super.attachBaseContext(base); 29 | boolean isBrowserProcess = !ContextUtils.getProcessName().contains(":"); 30 | ContextUtils.initApplicationContext(this); 31 | ResourceBundle.setNoAvailableLocalePaks(); 32 | if (isBrowserProcess) { 33 | if (BuildConfig.IS_MULTIDEX_ENABLED) { 34 | ChromiumMultiDexInstaller.install(this); 35 | } 36 | PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX); 37 | ApplicationStatus.initialize(this); 38 | } 39 | } 40 | 41 | public void initCommandLine() { 42 | if (!CommandLine.isInitialized()) { 43 | CommandLine.initFromFile(COMMAND_LINE_FILE); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /demo_android/demo_apk/src/org/chromium/demo_jni/DemoFoo.java: -------------------------------------------------------------------------------- 1 | 2 | package org.chromium.demo_jni; 3 | 4 | import android.util.Log; 5 | import java.lang.String; 6 | import org.chromium.base.annotations.CalledByNative; 7 | import org.chromium.base.annotations.JNINamespace; 8 | import org.chromium.base.annotations.NativeMethods; 9 | 10 | @JNINamespace("demo_jni") 11 | public class DemoFoo { 12 | 13 | private static final String TAG = "DemoApk.DemoFoo"; 14 | private long mNativeDemoFoo; 15 | 16 | public DemoFoo() { 17 | Log.i(TAG,"Call DemoFoo.ctor"); 18 | mNativeDemoFoo = DemoFooJni.get().init(this); 19 | } 20 | 21 | public void HelloDemoFoo(String who) { 22 | Log.i(TAG,"Call HelloDemoFoo"); 23 | DemoFoo.Natives foo = DemoFooJni.get(); 24 | foo.HelloDemoFoo(mNativeDemoFoo,who); 25 | } 26 | 27 | public void Hello(String who) { 28 | // DemoFooJni 是根据DemoFoo.Natives自动生成的类 29 | Log.i(TAG,"Call Hello"); 30 | DemoFooJni.get().Hello(who); 31 | } 32 | 33 | // C++和Java都可以调用该方法 34 | // 演示实例方法的使用 35 | @CalledByNative 36 | public void Hi(String who) { 37 | Log.i(TAG,"Hi,"+who); 38 | } 39 | 40 | // C++和Java都可以调用该方法 41 | // 演示static方法的使用 42 | @CalledByNative 43 | public static void HiStatic(String who) { 44 | Log.i(TAG,"Hi Static,"+who); 45 | } 46 | 47 | // 固定格式,用于定义并生成JNI接口 48 | @NativeMethods 49 | public interface Natives { 50 | // 初始化,传入Java的this,返回C++的this 51 | long init(DemoFoo caller); 52 | // 第一个参数以 native 开头,因此调用nativeDemoFoo对象的实例方法 53 | void HelloDemoFoo(long nativeDemoFoo,String who); 54 | // 第一个参数不是以 native 开头,因此调用全局方法 55 | void Hello(String who); 56 | 57 | } 58 | } -------------------------------------------------------------------------------- /demo_cc/BUILD.gn: -------------------------------------------------------------------------------- 1 | 2 | import("//build/config/ui.gni") 3 | 4 | template("cc") { 5 | executable(target_name){ 6 | testonly = true 7 | forward_variables_from(invoker, "*") 8 | 9 | deps = [ 10 | "//base", 11 | "//build/win:default_exe_manifest", 12 | "//cc:test_support", 13 | "//cc", 14 | "//components/viz/demo:host", 15 | "//components/viz/demo:service", 16 | "//components/viz/host", 17 | "//components/viz/service", 18 | "//components/viz/service/main", 19 | "//mojo/core/embedder", 20 | "//skia", 21 | "//ui/events", 22 | "//ui/events/platform", 23 | "//ui/platform_window", 24 | ] 25 | 26 | if (use_x11) { 27 | deps += [ 28 | "//ui/events/platform/x11", 29 | "//ui/platform_window/x11", 30 | ] 31 | configs += [ "//build/config/linux:x11" ] 32 | } 33 | } 34 | } 35 | 36 | group("demo_cc") { 37 | testonly = true 38 | deps = [ 39 | ":demo_cc_gui", 40 | ":demo_cc_offscreen" 41 | ] 42 | } 43 | 44 | cc("demo_cc_gui") { 45 | sources = [ 46 | "demo_cc_gui.cc" 47 | ] 48 | } 49 | 50 | cc("demo_cc_offscreen") { 51 | sources = [ 52 | "demo_cc_offscreen.cc" 53 | ] 54 | } 55 | 56 | -------------------------------------------------------------------------------- /demo_cc/README.md: -------------------------------------------------------------------------------- 1 | # cc (Chrome Compositor) 2 | 3 | > Viz 和 cc 相关的类图见: 4 | 5 | TODO: 完善文档 6 | 7 | cc 的核心调度入口在 `cc::Scheduler::ProcessScheduledActions()`,主要代码如下: 8 | 9 | ```C++ 10 | // 2020年1月(v80.0.3987.158),有删减 11 | void Scheduler::ProcessScheduledActions() { 12 | SchedulerStateMachine::Action action; 13 | do { 14 | action = state_machine_.NextAction(); 15 | switch (action) { 16 | case SchedulerStateMachine::Action::NONE: 17 | break; 18 | case SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME: 19 | // 绘制新帧,这会触发cc embedder的绘制(Paint),比如views::View::Paint()或者blink::GraphicsLayer::Paint() 20 | client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_); 21 | break; 22 | case SchedulerStateMachine::Action::COMMIT: { 23 | // 执行提交,也就是将cc::Layer的内容复制到cc::LayerImpl中 24 | client_->ScheduledActionCommit(); 25 | break; 26 | } 27 | case SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE: 28 | // 执行同步,也就是将pending_tree的内容同步到active_tree 29 | client_->ScheduledActionActivateSyncTree(); 30 | break; 31 | case SchedulerStateMachine::Action::DRAW_IF_POSSIBLE: 32 | // 执行submit,创建CompositorFrame并提交到DisplayCompsitor 33 | DrawIfPossible(); 34 | break; 35 | case SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION: 36 | // 初始化,请求创建LayerTreeFrameSink 37 | client_->ScheduledActionBeginLayerTreeFrameSinkCreation(); 38 | break; 39 | case SchedulerStateMachine::Action::PREPARE_TILES: 40 | // 执行Raster,并且准备Tiles 41 | client_->ScheduledActionPrepareTiles(); 42 | break; 43 | } 44 | } 45 | } while (action != SchedulerStateMachine::Action::NONE); 46 | 47 | // 用于设定一个Deadline,在该Deadline之前都允许触发SEND_BEGIN_MAIN_FRAME事件,在Deadline触发后就不再允许触发该事件。它会Post一个延迟的OnBeginImplFrameDeadline事件,如果该事件执行了表示已经到了Deadline(状态机进入INSIDE_DEADLINE状态),它会设置一些状态禁止触发BeginMainFrame,然后进行下一次调度,这些调度都是需要在Deadline状态才能执行的操作,可能调度到DRAW_IF_POSSIBLE,这会触发client提交CF到viz,也可能调度到其他状态比如PREPARE_TILES等,当然也可能调度到NONE状态,在进入Deadline之后的所有操作都完成之后,调度器会进入空闲状态IDLE,此时就算退出Deadline了,后续就允许触发SEND_BEGIN_MAIN_FRAME事件了。 48 | ScheduleBeginImplFrameDeadline(); 49 | 50 | // 用于检测是否需要触发SEND_BEGIN_MAIN_FRAME事件,如果需要它会Post HandlePendingBeginFrame事件,该事件执行后会使状态机进入INSIDE_BEGIN_FRAME状态,随后调度器会在合适的时机触发SEND_BEGIN_MAIN_FRAME事件,这会调用client进行绘制,在client绘制完成之后会请求调度器执行提交COMMIT以及激活ACTIVATE_SYNC_TREE。 51 | PostPendingBeginFrameTask(); 52 | 53 | // 用于检测当前是否处于IDLE状态,如果是则将自己从 BFS 移除,否则则将自己 加入BFS。如果调度器将自己从BFS上移除,则会进入”休眠状态“,此时不会调度器不会占用CPU,如果后续外部需要更新显示的画面,可以通过cc::Scheduler::SetNeedsBeginFrame()来激活调度器(注意cc模块外可以通过cc::LayerTreeHost::SetNeedsCommit()来间接调用它,如果在cc::Layer中,则可以直接调用它的SetNeedsCommit成员函数,如果cc::Layer没有任何变化,只调用SetNeddsCommit()则不会激活调度器,必须有实际的变更或者标记区域demaged)。 54 | StartOrStopBeginFrames(); 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /demo_gl/BUILD.gn: -------------------------------------------------------------------------------- 1 | 2 | import("//build/config/ui.gni") 3 | 4 | executable("demo_gl") { 5 | testonly = true 6 | 7 | sources = [ 8 | "demo_gl.cc", 9 | ] 10 | 11 | deps = [ 12 | "//base", 13 | "//base:i18n", 14 | "//gpu", 15 | "//gpu:gles2", 16 | "//gpu:raster", 17 | # "//gpu/command_buffer/client", 18 | # "//gpu/command_buffer/client:gles2_cmd_helper", 19 | # "//gpu/command_buffer/service", 20 | # "//gpu/command_buffer/service:gles2", 21 | "//ui/base", 22 | "//ui/gl", 23 | "//ui/gl/init", 24 | "//ui/events", 25 | "//ui/events/platform", 26 | "//ui/platform_window", 27 | # "//skia", 28 | ] 29 | 30 | if (use_x11) { 31 | deps += [ 32 | "//ui/events/platform/x11", 33 | "//ui/platform_window/x11", 34 | ] 35 | configs += [ "//build/config/linux:x11" ] 36 | } 37 | 38 | # libs = ["EGL","GLESv2"] 39 | } 40 | -------------------------------------------------------------------------------- /demo_gl/README.md: -------------------------------------------------------------------------------- 1 | # demo_gl 2 | 3 | 演示如何通过 `//ui/gl` 模块进行 EGL/GL 调用。 4 | 5 | `//ui/gl` 模块封装了各平台的 native GL,在 Chromium 中负责直接和 native GL 打交道,运行在 GPU 进程中。 6 | -------------------------------------------------------------------------------- /demo_ipc_message_generator.cc: -------------------------------------------------------------------------------- 1 | // Get basic type definitions. 2 | #define IPC_MESSAGE_IMPL 3 | #include "demo_ipc_message_generator.h" 4 | // Generate constructors. 5 | #include "ipc/struct_constructor_macros.h" 6 | #include "demo_ipc_message_generator.h" 7 | // Generate param traits write methods. 8 | #include "ipc/param_traits_write_macros.h" 9 | namespace IPC { 10 | #include "demo_ipc_message_generator.h" 11 | } // namespace IPC 12 | // Generate param traits read methods. 13 | #include "ipc/param_traits_read_macros.h" 14 | namespace IPC { 15 | #include "demo_ipc_message_generator.h" 16 | } // namespace IPC 17 | // Generate param traits log methods. 18 | #include "ipc/param_traits_log_macros.h" 19 | namespace IPC { 20 | #include "demo_ipc_message_generator.h" 21 | } // namespace IPC -------------------------------------------------------------------------------- /demo_ipc_message_generator.h: -------------------------------------------------------------------------------- 1 | #undef DEMO_IPC_MESSAGES_H_ 2 | #include "demo_ipc_messages.h" 3 | #ifndef DEMO_IPC_MESSAGES_H_ 4 | #error "Failed to include header demo_ipc_messages.h" 5 | #endif -------------------------------------------------------------------------------- /demo_ipc_messages.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_IPC_MESSAGES_H_ 2 | #define DEMO_IPC_MESSAGES_H_ 3 | 4 | #include "ipc/ipc_message.h" 5 | #include "ipc/ipc_message_macros.h" 6 | #include "ipc/ipc_param_traits.h" 7 | 8 | // 使用 IPCTestMsgStart 来测试,它不能随意命名,必须存在于 ipc/ipc_message_start.h 中 9 | // 详情见 ipc/ipc_message_start.h 文件头的解释 10 | // 关于 IPC 的介绍见 http://www.chromium.org/developers/design-documents/inter-process-communication 11 | #define IPC_MESSAGE_START TestMsgStart 12 | 13 | IPC_MESSAGE_CONTROL1(IPCTestMsg_Hello,std::string) 14 | IPC_MESSAGE_CONTROL1(IPCTestMsg_Hi,std::string) 15 | 16 | IPC_MESSAGE_ROUTED1(IPCTestMsg_RoutedHello,std::string) 17 | IPC_MESSAGE_ROUTED1(IPCTestMsg_RoutedHi,std::string) 18 | 19 | #endif //DEMO_IPC_MESSAGES_H_ -------------------------------------------------------------------------------- /demo_log.cc: -------------------------------------------------------------------------------- 1 | #include "base/command_line.h" 2 | #include "base/logging.h" 3 | #include "base/debug/stack_trace.h" 4 | 5 | int main(int argc, char** argv) { 6 | // 使用log以来它 7 | base::CommandLine::Init(argc, argv); 8 | 9 | int loglevel = -1; 10 | 11 | logging::SetLogPrefix("demo"); 12 | logging::SetLogItems(true,false,true,false); 13 | // 设置为负数启用VLOG,在chromium中使用 --v=1 达到同样效果 14 | logging::SetMinLogLevel(loglevel); 15 | 16 | logging::LoggingSettings settings; 17 | settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR; 18 | settings.log_file_path = nullptr; 19 | settings.lock_log = logging::DONT_LOCK_LOG_FILE; 20 | settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE; 21 | bool logging_res = logging::InitLogging(settings); 22 | CHECK(logging_res); 23 | 24 | // 主动打印堆栈信息 25 | LOG(INFO) << "Stack: " << base::debug::StackTrace().ToString(); 26 | 27 | LOG(INFO) << "set loglevel to: " << loglevel; 28 | 29 | LOG(INFO) << "LOG: INFO"; 30 | DLOG(INFO) << "DLOG: INFO"; 31 | 32 | LOG(WARNING) << "LOG: WARNING"; 33 | LOG(ERROR) << "LOG: ERROR"; 34 | 35 | LOG_IF(INFO,2>1) << "LOG_IF: INFO 2>1"; 36 | DLOG_IF(INFO,2>1) << "DLOG_IF: INFO 2>1"; 37 | 38 | // 不会打印出来,因为我们设置了LogLevel为 -1 39 | VLOG(2) << "VLOG: 2"; 40 | VLOG(3) << "VLOG: 3"; 41 | 42 | VLOG(1) << "VLOG: 1"; 43 | DVLOG(1) << "DVLOG: 1"; 44 | 45 | // 在日志后面追加 GetLastError() on Windows and errno on POSIX 46 | PLOG(INFO) << "PLOG: INFO"; 47 | DPLOG(INFO) << "DPLOG: INFO"; 48 | 49 | // 会使进程立即退出 50 | DLOG(FATAL) << "DLOG: FATAL"; 51 | LOG(FATAL) << "LOG: FATAL"; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /demo_memory.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | * base/memory/sheared_memory.h 在 fa7e8cc73e59e49c7ac12465dee031e7370ce1c0 3 | * 中被删除: [base] Remove base::SharedMemory and base::SharedMemoryHandle 4 | * 5 | * There are no users of the deprecated shared memory left, so its code 6 | * can safely removed. 7 | * 8 | * To use shared memory in Chrome, please refer to 9 | * base::WritableSharedMemoryRegion and base::ReadOnlySharedMemoryRegion 10 | * classes. 11 | * 12 | * 所以在这里只演示使用 base::WritableSharedMemoryRegion 和 13 | * base::ReadOnlySharedMemoryRegion 14 | */ 15 | 16 | #include "base/at_exit.h" 17 | #include "base/command_line.h" 18 | #include "base/logging.h" 19 | #include "base/message_loop/message_loop.h" 20 | #include "base/task/thread_pool/thread_pool_instance.h" 21 | 22 | // For SharedMemoryTest 23 | #include "base/memory/read_only_shared_memory_region.h" 24 | #include "base/memory/writable_shared_memory_region.h" 25 | #include "base/system/sys_info.h" 26 | 27 | // For MemoryPressureTest 28 | #include "base/memory/memory_pressure_monitor.h" 29 | //#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h" 30 | 31 | void SharedMemoryTest() { 32 | base::WritableSharedMemoryRegion memory = 33 | base::WritableSharedMemoryRegion::Create(10); 34 | LOG(INFO) << "memory size: " << memory.GetSize(); 35 | { 36 | base::WritableSharedMemoryMapping mapping = memory.Map(); 37 | void* buffer = mapping.memory(); 38 | memset(buffer, 'a', 9); 39 | LOG(INFO) << "mapping size: " << mapping.size(); 40 | } 41 | { 42 | int gra = base::SysInfo::VMAllocationGranularity(); 43 | LOG(INFO) << "VMAllocationGranularity: " << gra; 44 | // MapAt 的 offset 必须对齐到 VMAllocationGranularity 45 | base::WritableSharedMemoryMapping mapping = memory.MapAt(0, 5); 46 | DCHECK(mapping.IsValid()); 47 | char* buffer = mapping.GetMemoryAs(); 48 | LOG(INFO) << "mapping size: " << mapping.size() << ", data=" << buffer; 49 | } 50 | { 51 | // WritableSharedMemoryRegion 52 | // 可以转换为ReadOnly的,但是转换后原来的Region将不可用 53 | base::ReadOnlySharedMemoryRegion memory_read_only = 54 | base::WritableSharedMemoryRegion::ConvertToReadOnly(std::move(memory)); 55 | // ReadOnlySharedMemoryRegion 是可以复制的 56 | base::ReadOnlySharedMemoryRegion memory_read_only2 = 57 | memory_read_only.Duplicate(); 58 | 59 | base::ReadOnlySharedMemoryMapping mapping_read_only = 60 | memory_read_only.Map(); 61 | DCHECK(mapping_read_only.IsValid()); 62 | base::ReadOnlySharedMemoryMapping mapping_read_only2 = 63 | memory_read_only2.Map(); 64 | DCHECK(mapping_read_only2.IsValid()); 65 | LOG(INFO) << "mapping size: " << mapping_read_only.size() 66 | << ", data=" << mapping_read_only.GetMemoryAs(); 67 | LOG(INFO) << "mapping2 size: " << mapping_read_only2.size() 68 | << ", data2=" << mapping_read_only2.GetMemoryAs(); 69 | } 70 | } 71 | 72 | // 只支持ChromeOS,MAC,WIN,不支持linux 73 | void MemoryPresureTest() { 74 | // https://source.chromium.org/chromium/chromium/src/+/master:content/browser/browser_main_loop.cc;l=367;drc=88c20a4027a89de88d6c559fe2ae49124a01ff8d 75 | // 初始化,要一直保活 76 | // 在新版本才有 77 | //std::unique_ptr monitor; 78 | #if defined(OS_CHROMEOS) 79 | if (chromeos::switches::MemoryPressureHandlingEnabled()) 80 | monitor = std::make_unique(); 81 | #elif defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_FUCHSIA) 82 | monitor = std::make_unique(); 83 | #else 84 | return; 85 | #endif 86 | 87 | base::MemoryPressureMonitor* monitor = base::MemoryPressureMonitor::Get(); 88 | base::MemoryPressureMonitor::MemoryPressureLevel level = 89 | monitor->GetCurrentPressureLevel(); 90 | 91 | if (level == base::MemoryPressureMonitor::MemoryPressureLevel:: 92 | MEMORY_PRESSURE_LEVEL_CRITICAL) { 93 | LOG(INFO) << "应该释放内存"; 94 | // 应该释放内存 95 | } 96 | } 97 | 98 | int main(int argc, char** argv) { 99 | // 类似C++的 atexit() 方法,用于管理程序的销毁逻辑,base::Singleton类依赖它 100 | base::AtExitManager at_exit; 101 | // 初始化CommandLine 102 | base::CommandLine::Init(argc, argv); 103 | // 设置日志格式 104 | logging::SetLogItems(true, false, true, false); 105 | // 创建主消息循环 106 | base::MessageLoop message_loop; 107 | // 初始化线程池,会创建新的线程,在新的线程中会创建新消息循环MessageLoop 108 | base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Demo"); 109 | 110 | SharedMemoryTest(); 111 | //MemoryPresureTest(); 112 | 113 | LOG(INFO) << "running..."; 114 | base::RunLoop().Run(); 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /demo_mojo_single_process.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "base/command_line.h" 3 | #include "base/message_loop/message_loop.h" 4 | #include 5 | #include 6 | #include 7 | 8 | #include "mojo/public/c/system/buffer.h" 9 | #include "mojo/public/c/system/data_pipe.h" 10 | #include "mojo/public/c/system/message_pipe.h" 11 | #include "mojo/public/cpp/system/buffer.h" 12 | #include "mojo/public/cpp/system/data_pipe.h" 13 | #include "mojo/public/cpp/system/message_pipe.h" 14 | #include "mojo/public/cpp/system/simple_watcher.h" 15 | #include "mojo/public/cpp/system/wait.h" 16 | 17 | int main(int argc, char** argv) { 18 | // 初始化CommandLine,DataPipe 依赖它 19 | base::CommandLine::Init(argc, argv); 20 | mojo::core::Init(); 21 | base::Thread ipc_thread("ipc!"); 22 | ipc_thread.StartWithOptions( 23 | base::Thread::Options(base::MessagePumpType::IO, 0)); 24 | 25 | // As long as this object is alive, all Mojo API surface relevant to IPC 26 | // connections is usable, and message pipes which span a process boundary will 27 | // continue to function. 28 | mojo::core::ScopedIPCSupport ipc_support( 29 | ipc_thread.task_runner(), 30 | mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN); 31 | 32 | // 使用 C 接口创建一条MessagePipe 33 | // MessagePipe 34 | // 只是一对数字,只用于ID标识,并不对应任何系统资源,并且该行为在单进程和多进程中都是一致的 35 | // 因此可以非常快速,不可能失败的,创建大量的MessagePipe。 36 | MojoHandle sender_handle, receiver_handle; 37 | MojoResult result = 38 | MojoCreateMessagePipe(NULL, &sender_handle, &receiver_handle); 39 | DCHECK_EQ(result, MOJO_RESULT_OK); 40 | // 使用 C 接口发送一条消息 41 | { 42 | MojoMessageHandle message; 43 | result = MojoCreateMessage(nullptr, &message); 44 | DCHECK_EQ(result, MOJO_RESULT_OK); 45 | MojoAppendMessageDataOptions options; 46 | options.struct_size = sizeof(options); 47 | options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; 48 | void* buffer; 49 | uint32_t buffer_size; 50 | result = MojoAppendMessageData(message, 6, nullptr, 0, &options, &buffer, 51 | &buffer_size); 52 | DCHECK_EQ(result, MOJO_RESULT_OK); 53 | memcpy(buffer, "hello", 6); 54 | LOG(INFO) << "send: " << (const char*)buffer; 55 | 56 | result = MojoWriteMessage(sender_handle, message, nullptr); 57 | DCHECK_EQ(result, MOJO_RESULT_OK); 58 | } 59 | // 使用 C 接口接收一条消息 60 | { 61 | MojoMessageHandle message; 62 | MojoResult result = MojoReadMessage(receiver_handle, nullptr, &message); 63 | DCHECK_EQ(result, MOJO_RESULT_OK); 64 | 65 | void* buffer = NULL; 66 | uint32_t num_bytes; 67 | result = MojoGetMessageData(message, nullptr, &buffer, &num_bytes, nullptr, 68 | nullptr); 69 | LOG(INFO) << "receive: " << (const char*)buffer; 70 | } 71 | 72 | // 使用C++接口创建一条 MessagePipe 73 | mojo::MessagePipe pipe; 74 | // 使用 C++ 接口发送一条消息 75 | { 76 | const char kMessage[] = "HELLO"; 77 | result = 78 | mojo::WriteMessageRaw(pipe.handle0.get(), kMessage, sizeof(kMessage), 79 | nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); 80 | DCHECK_EQ(result, MOJO_RESULT_OK); 81 | LOG(INFO) << "send: " << kMessage; 82 | } 83 | // 使用 C++ 接口接收一条消息 84 | { 85 | std::vector data; 86 | result = mojo::ReadMessageRaw(pipe.handle1.get(), &data, nullptr, 87 | MOJO_READ_MESSAGE_FLAG_NONE); 88 | DCHECK_EQ(result, MOJO_RESULT_OK); 89 | LOG(INFO) << "receive msg: " << (char*)&data[0]; 90 | } 91 | 92 | // 使用 C++ 接口创建一条 DataPipe,DataPipe 是单向的 93 | mojo::ScopedDataPipeProducerHandle producer; 94 | mojo::ScopedDataPipeConsumerHandle consumer; 95 | // 内部涉及系统资源的分配,可能会失败,因此不建议使用 mojo::DataPipe 96 | // 来创建,会导致崩溃 97 | result = mojo::CreateDataPipe(nullptr, &producer, &consumer); 98 | // 使用 DataPipe 写数据 99 | { 100 | const char kMessage[] = "DataPipe"; 101 | uint32_t length = sizeof(kMessage); 102 | result = producer->WriteData(kMessage, &length, MOJO_WRITE_DATA_FLAG_NONE); 103 | DCHECK_EQ(result, MOJO_RESULT_OK); 104 | LOG(INFO) << "send data: " << kMessage; 105 | } 106 | // 使用 DataPipe 读数据 107 | { 108 | char buffer[100]; 109 | uint32_t num_bytes = 100; 110 | result = consumer->ReadData(buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); 111 | DCHECK_EQ(result, MOJO_RESULT_OK); 112 | LOG(INFO) << "receive data: " << buffer; 113 | } 114 | 115 | // 使用 C++ 接口创建一个 SharedBuffer 116 | // Shared Buffer 内部也使用 Shared Memory 实现 117 | mojo::ScopedSharedBufferHandle buffer = 118 | mojo::SharedBufferHandle::Create(4096); 119 | // clone一个buffer的句柄,该句柄和buffer指向相同的内存,内部有引用计数 120 | // 当计数为0的时候,句柄指向的内存会被销毁 121 | // 这里只是为了演示Clone,并不是必须的 122 | mojo::ScopedSharedBufferHandle buffer_clone = 123 | buffer->Clone(mojo::SharedBufferHandle::AccessMode::READ_WRITE); 124 | // 向 SharedBuffer 写数据 125 | { 126 | const std::string kMessage("SharedBuffer\0", 13); 127 | mojo::ScopedSharedBufferMapping mapping = buffer->Map(kMessage.length()); 128 | DCHECK(mapping); 129 | std::copy(kMessage.begin(), kMessage.end(), 130 | static_cast(mapping.get())); 131 | LOG(INFO) << "write buffer: " << kMessage; 132 | } 133 | // 从 SharedBuffer 读数据 134 | { 135 | mojo::ScopedSharedBufferMapping mapping = buffer_clone ->Map(64); 136 | LOG(INFO) << "read buffer: " << static_cast(mapping.get()); 137 | } 138 | 139 | // 创建消息循环 140 | base::MessageLoop message_loop; 141 | base::RunLoop run_loop; 142 | run_loop.Run(); 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /demo_resources/BUILD.gn: -------------------------------------------------------------------------------- 1 | 2 | # for demo_resources 3 | import("//tools/grit/grit_rule.gni") 4 | import("//tools/grit/repack.gni") 5 | 6 | executable("demo_resources") { 7 | sources = [ 8 | "demo_resources.cc", 9 | ] 10 | 11 | deps = [ 12 | ":demo_resources_pak", 13 | "//base", 14 | "//ui/base", 15 | # 因为使用了xxx_map.cc,因此需要添加对他们的直接依赖 16 | ":demo_resources_grit", 17 | ":demo_strings_grit", 18 | ] 19 | } 20 | 21 | grit("demo_resources_grit") { 22 | source = "demo_resources.grd" 23 | # 设置为""可以使用grd文件中的first_ids_file 24 | # resource_ids = "" 25 | resource_ids = "demo_resource_ids" 26 | outputs = [ 27 | "grit/demo_gen_resources.h", 28 | "grit/demo_gen_resources_map.h", 29 | "grit/demo_gen_resources_map.cc", 30 | "grit/demo_gen_resources_en.pak", 31 | "grit/demo_gen_resources_zh-CN.pak", 32 | "grit/demo_gen_resources_en.rc", 33 | "grit/demo_gen_resources_zh-CN.rc", 34 | "grit/demo_gen_resources_translateable_zh-CN.rc", 35 | "grit/demo_gen_resources_nontranslateable_zh-CN.rc", 36 | ] 37 | } 38 | 39 | grit("demo_strings_grit") { 40 | source = "demo_strings.grd" 41 | resource_ids = "demo_resource_ids" 42 | outputs = [ 43 | "grit/demo_gen_strings.h", 44 | "grit/demo_gen_strings_map.h", 45 | "grit/demo_gen_strings_map.cc", 46 | "grit/demo_gen_strings_en.pak", 47 | "grit/demo_gen_strings_zh-CN.pak", 48 | ] 49 | } 50 | 51 | repack("demo_resources_pak_en") { 52 | sources = [ 53 | "$root_gen_dir/demo/demo_resources/grit/demo_gen_resources_en.pak", 54 | "$root_gen_dir/demo/demo_resources/grit/demo_gen_strings_en.pak", 55 | ] 56 | output = "$root_gen_dir/demo/demo_resources/grit/demo_gen_pak_en.pak" 57 | deps = [ 58 | ":demo_resources_grit", 59 | ":demo_strings_grit", 60 | ] 61 | } 62 | 63 | repack("demo_resources_pak_zh-CN") { 64 | sources = [ 65 | "$root_gen_dir/demo/demo_resources/grit/demo_gen_resources_zh-CN.pak", 66 | "$root_gen_dir/demo/demo_resources/grit/demo_gen_strings_zh-CN.pak", 67 | ] 68 | output = "$root_gen_dir/demo/demo_resources/grit/demo_gen_pak_zh-CN.pak" 69 | deps = [ 70 | ":demo_resources_grit", 71 | ":demo_strings_grit", 72 | ] 73 | } 74 | 75 | group("demo_resources_pak") { 76 | deps = [ 77 | ":demo_resources_pak_en", 78 | ":demo_resources_pak_zh-CN", 79 | ] 80 | } -------------------------------------------------------------------------------- /demo_resources/demo_resource_ids: -------------------------------------------------------------------------------- 1 | { 2 | "SRCDIR": ".", 3 | # 31000之后的范围留给第三方,所以我们从31000开始 4 | "demo_resources.grd": { 5 | "messages": [31000], 6 | }, 7 | 8 | "demo_strings.grd": { 9 | "messages": [32000], 10 | }, 11 | } -------------------------------------------------------------------------------- /demo_resources/demo_resources.cc: -------------------------------------------------------------------------------- 1 | #include "base/at_exit.h" 2 | #include "base/command_line.h" 3 | #include "base/logging.h" 4 | #include "base/message_loop/message_loop.h" 5 | #include "base/path_service.h" 6 | #include "base/task/thread_pool/thread_pool_instance.h" 7 | 8 | #include 9 | 10 | // for resources 11 | #include "ui/base/l10n/l10n_util.h" 12 | #include "ui/base/resource/resource_bundle.h" 13 | #include "ui/base/ui_base_paths.h" 14 | 15 | // grit生成的头文件 16 | #include "demo/demo_resources/grit/demo_gen_resources.h" 17 | #include "demo/demo_resources/grit/demo_gen_resources_map.h" 18 | #include "demo/demo_resources/grit/demo_gen_strings.h" 19 | #include "demo/demo_resources/grit/demo_gen_strings_map.h" 20 | 21 | void LoadResources(base::StringPiece resource_file, bool use_strings = false) { 22 | // 因为InitSharedInstanceWithxxx只能执行一次,因此这里先清除之前的数据 23 | if (ui::ResourceBundle::HasSharedInstance()) 24 | ui::ResourceBundle::CleanupSharedInstance(); 25 | 26 | // 初始化locale,也就是本地化/语言资源包 27 | // 会导致代码去加载 28 | // chrome_100_percent.pak,chrome_200_percent.pak,locale/xxx.pak 29 | // 前2个资源如果不存在的,会报WARNING. 30 | // 最后一个资源我本机是有的,如果你本地没有会崩溃。 31 | // 这里传入了空的语言类型,因为在Linux/Android等系统上这个值是没有用的,代码会从系统获取语言类型 32 | // 具体逻辑见 l10n_util::GetApplicationLocaleInternal 33 | // 实际项目中应该使用这个进行初始化 34 | // ui::ResourceBundle::InitSharedInstanceWithLocale( 35 | // "", nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES); 36 | 37 | // 加载数据资源包 38 | base::FilePath resource_path; 39 | if (base::PathService::Get(base::DIR_MODULE, &resource_path)) 40 | resource_path = resource_path.AppendASCII(resource_file); 41 | ui::ResourceBundle::InitSharedInstanceWithPakPath(resource_path); 42 | 43 | ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 44 | // 你也可以使用这个方法来加载其他的pak资源 45 | // SCALE_FATOR 46 | // 缩放因子,用来支持高分屏等情况,用户可以根据当前显示的情况选择使用拥有哪一个缩放因子的资源 47 | // 在初始化的时候,大多数情况会支持SCALE_FACTOR_100P和SCALE_FACTOR_200P,在IOS上还支持SCALE_FACTOR_300P 48 | // 具有相同ID并且SCALE_FATOR相同的资源只能有一个,否则会导致崩溃 49 | // bundle.AddDataPackFromPath(resource_path, ui::SCALE_FACTOR_NONE); 50 | 51 | std::cout << "Load: " << resource_file << std::endl; 52 | 53 | // 遍历demo_gen_resources.pak资源 54 | // text6会显示类似乱码的样子,因为grit使用了伪翻译,详见demo_resources.grd文件 55 | // 这里故意保持乱码以便读者注意这个问题 56 | for (size_t i = 0; i < kDemoGenResourcesSize; i++) { 57 | auto resource = kDemoGenResources[i]; 58 | 59 | std::cout << resource.name << ": [" 60 | << bundle.GetRawDataResource(resource.value) << "]" << std::endl; 61 | // 读取语言内容 62 | // 本来应该读不到的,因为语言资源包里没有这些资源,但是内部代码为了单元测试 63 | // 添加了failback到数据资源包的逻辑,所以这里也能读取出来数据资源 64 | // 注意我本机是有 locale/xxx.pak 文件的(因为编译过content_shell) 65 | std::cout << resource.name << ": [" 66 | << l10n_util::GetStringUTF16(resource.value) << "]" << std::endl; 67 | } 68 | if (use_strings) { 69 | std::cout << "------------------------------------------" << std::endl; 70 | // 遍历demo_gen_strings.pak资源 71 | for (size_t i = 0; i < kDemoGenStringsSize; i++) { 72 | auto resource = kDemoGenStrings[i]; 73 | std::cout << resource.name << ": [" 74 | << bundle.GetRawDataResource(resource.value) << "]" 75 | << std::endl; 76 | std::cout << resource.name << ": [" 77 | << l10n_util::GetStringUTF16(resource.value) << "]" 78 | << std::endl; 79 | } 80 | } 81 | std::cout << "==========================================" << std::endl; 82 | } 83 | 84 | int main(int argc, char** argv) { 85 | // 类似C++的 atexit() 方法,用于管理程序的销毁逻辑,base::Singleton类依赖它 86 | base::AtExitManager at_exit; 87 | // 初始化CommandLine 88 | base::CommandLine::Init(argc, argv); 89 | // 设置日志格式 90 | logging::SetLogItems(true, false, true, false); 91 | // 创建主消息循环 92 | base::MessageLoop message_loop; 93 | // 初始化线程池,会创建新的线程,在新的线程中会创建新消息循环MessageLoop 94 | base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Demo"); 95 | 96 | // 提供 DIR_LOCALE 路径,用于寻找资源 97 | ui::RegisterPathProvider(); 98 | 99 | LoadResources("gen/demo/demo_resources/grit/demo_gen_resources_en.pak"); 100 | LoadResources("gen/demo/demo_resources/grit/demo_gen_resources_zh-CN.pak"); 101 | LoadResources("gen/demo/demo_resources/grit/demo_gen_pak_en.pak", true); 102 | LoadResources("gen/demo/demo_resources/grit/demo_gen_pak_zh-CN.pak", true); 103 | 104 | LOG(INFO) << "running..."; 105 | base::RunLoop().Run(); 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /demo_resources/demo_resources.grd: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 45 | 46 | 47 | 48 | 49 | 50 | 53 | 54 | 55 | 56 | 57 | 61 | 62 | 63 | grd:Hello,Text1. This is a text from .grd file. 64 | 65 | 66 | 67 | 68 | grd:你好,文本1. 这是来自.grd文件的文本. 69 | 70 | 71 | 72 | ''' grd:Hello,Text2 prefixed with 4 whitespace.(use_name_for_id=true) ''' 73 | 74 | 75 | grd:Hello,Text3.(not translateable) 76 | 77 | 78 | grd:Hello,Text4.(translateable) 79 | 80 | 81 | grd:Hello,Text5. It is the %sfourth text. 82 | 83 | 91 | 92 | grd:Hello,Text6.(translateable) 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /demo_resources/demo_resources_zh-CN.xtb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | xtb:你好,文本2带有4个空格前缀。(use_name_for_id=true) 5 | xtb:你好,文本4。(可翻译) 6 | xtb:你好,文本5。这是第个文本。 7 | -------------------------------------------------------------------------------- /demo_resources/demo_strings.grd: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | strings_grd:Hello. 23 | 24 | 25 | strings_grd:Hi. 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /demo_resources/demo_strings_zh-CN.xtb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | strings_xtb:你好,Hello 5 | strings_xtb:你好,Hi 6 | 7 | -------------------------------------------------------------------------------- /demo_shell/README.md: -------------------------------------------------------------------------------- 1 | # demo_shell 2 | 3 | TODO: 完善 demo_shell 的文档。 4 | -------------------------------------------------------------------------------- /demo_shell/android/demo_shell_descriptors.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef DEMO_DEMO_SHELL_ANDROID_DEMO_SHELL_DESCRIPTORS_H_ 6 | #define DEMO_DEMO_SHELL_ANDROID_DEMO_SHELL_DESCRIPTORS_H_ 7 | 8 | #include "content/public/common/content_descriptors.h" 9 | 10 | // This is a list of global descriptor keys to be used with the 11 | // base::GlobalDescriptors object (see base/posix/global_descriptors.h) 12 | enum { 13 | kShellPakDescriptor = kContentIPCDescriptorMax + 1, 14 | kAndroidMinidumpDescriptor, 15 | }; 16 | 17 | #endif // DEMO_DEMO_SHELL_ANDROID_DEMO_SHELL_DESCRIPTORS_H_ -------------------------------------------------------------------------------- /demo_shell/android/demo_shell_library_loader.cc: -------------------------------------------------------------------------------- 1 | #include "base/android/jni_android.h" 2 | #include "content/public/app/content_jni_onload.h" 3 | #include "content/public/app/content_main.h" 4 | 5 | #include "base/android/base_jni_onload.h" 6 | #include "base/logging.h" 7 | 8 | #include "demo/demo_shell/app/demo_shell_content_main_delegate.h" 9 | 10 | JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { 11 | base::android::InitVM(vm); 12 | // JNIEnv* env = base::android::AttachCurrentThread(); 13 | // if (!RegisterMainDexNatives(env) || !RegisterNonMainDexNatives(env)) { 14 | // return -1; 15 | // } 16 | if (!content::android::OnJNIOnLoadInit()) 17 | return -1; 18 | content::SetContentMainDelegate(new content::DemoShellContentMainDelegate()); 19 | DLOG(INFO) << "======JNI_OnLoad finished"; 20 | return JNI_VERSION_1_4; 21 | } 22 | -------------------------------------------------------------------------------- /demo_shell/android/demo_shell_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "demo/demo_shell/android/demo_shell_manager.h" 6 | 7 | #include "base/android/jni_android.h" 8 | #include "base/android/jni_string.h" 9 | #include "base/android/scoped_java_ref.h" 10 | #include "base/bind.h" 11 | #include "base/lazy_instance.h" 12 | #include "content/public/browser/web_contents.h" 13 | 14 | #include "demo/demo_shell/browser/shell.h" 15 | #include "demo/demo_shell/browser/demo_shell_browser_context.h" 16 | #include "demo/demo_shell/browser/demo_shell_content_browser_client.h" 17 | #include "demo/demo_shell/android/demo_shell_jni_headers/ShellManager_jni.h" 18 | 19 | #include "url/gurl.h" 20 | 21 | using base::android::JavaParamRef; 22 | using base::android::JavaRef; 23 | using base::android::ScopedJavaLocalRef; 24 | 25 | namespace { 26 | 27 | struct GlobalState { 28 | GlobalState() {} 29 | base::android::ScopedJavaGlobalRef j_shell_manager; 30 | }; 31 | 32 | base::LazyInstance::DestructorAtExit g_global_state = 33 | LAZY_INSTANCE_INITIALIZER; 34 | 35 | } // namespace 36 | 37 | namespace content { 38 | 39 | ScopedJavaLocalRef CreateShellView(DemoShell* shell) { 40 | DLOG(INFO) << "============== CreateShellView"; 41 | 42 | JNIEnv* env = base::android::AttachCurrentThread(); 43 | return Java_ShellManager_createShell(env, 44 | g_global_state.Get().j_shell_manager, 45 | reinterpret_cast(shell)); 46 | } 47 | 48 | void RemoveShellView(const JavaRef& shell_view) { 49 | JNIEnv* env = base::android::AttachCurrentThread(); 50 | Java_ShellManager_removeShell(env, g_global_state.Get().j_shell_manager, 51 | shell_view); 52 | } 53 | 54 | static void JNI_ShellManager_Init(JNIEnv* env, 55 | const JavaParamRef& obj) { 56 | g_global_state.Get().j_shell_manager.Reset(obj); 57 | DLOG(INFO) << "============== JNI_ShellManager_Init"; 58 | } 59 | 60 | void JNI_ShellManager_LaunchShell(JNIEnv* env, 61 | const JavaParamRef& jurl) { 62 | DemoShellBrowserContext* browserContext = 63 | DemoShellContentBrowserClient::Get()->browser_context(); 64 | GURL url(base::android::ConvertJavaStringToUTF8(env, jurl)); 65 | DemoShell::CreateNewWindow(browserContext, 66 | url, 67 | nullptr, 68 | gfx::Size()); 69 | DLOG(INFO) << "============== JNI_ShellManager_LaunchShell"; 70 | 71 | } 72 | 73 | void DestroyShellManager() { 74 | JNIEnv* env = base::android::AttachCurrentThread(); 75 | Java_ShellManager_destroy(env, g_global_state.Get().j_shell_manager); 76 | DLOG(INFO) << "============== DestroyShellManager"; 77 | 78 | } 79 | 80 | } // namespace content 81 | -------------------------------------------------------------------------------- /demo_shell/android/demo_shell_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTENT_DEMO_SHELL_ANDROID_SHELL_MANAGER_H_ 2 | #define CONTENT_DEMO_SHELL_ANDROID_SHELL_MANAGER_H_ 3 | 4 | #include 5 | 6 | #include "base/android/jni_android.h" 7 | #include "base/android/scoped_java_ref.h" 8 | 9 | class DemoShell; 10 | 11 | namespace cc { 12 | class Layer; 13 | } 14 | 15 | namespace content { 16 | 17 | // Creates an Android specific shell view, which is our version of a shell 18 | // window. This view holds the controls and content views necessary to 19 | // render a shell window. Returns the java object representing the shell view. 20 | // object. 21 | base::android::ScopedJavaLocalRef CreateShellView(DemoShell* shell); 22 | 23 | // Removes a previously created shell view. 24 | void RemoveShellView(const base::android::JavaRef& shell_view); 25 | 26 | void ShellAttachLayer(cc::Layer* layer); 27 | void ShellRemoveLayer(cc::Layer* layer); 28 | 29 | // Destroys the ShellManager on app exit. Must not use the above functions 30 | // after this is called. 31 | void DestroyShellManager(); 32 | 33 | } // namespace content 34 | 35 | #endif // CONTENT_DEMO_SHELL_ANDROID_SHELL_MANAGER_H_ -------------------------------------------------------------------------------- /demo_shell/android/java/res/layout/shell_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 16 | 51 | 55 | -------------------------------------------------------------------------------- /demo_shell/android/java/res/mipmap-hdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_shell/android/java/res/mipmap-hdpi/app_icon.png -------------------------------------------------------------------------------- /demo_shell/android/java/res/mipmap-mdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_shell/android/java/res/mipmap-mdpi/app_icon.png -------------------------------------------------------------------------------- /demo_shell/android/java/res/mipmap-xhdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_shell/android/java/res/mipmap-xhdpi/app_icon.png -------------------------------------------------------------------------------- /demo_shell/android/java/res/mipmap-xxhdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_shell/android/java/res/mipmap-xxhdpi/app_icon.png -------------------------------------------------------------------------------- /demo_shell/android/java/res/mipmap-xxxhdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_shell/android/java/res/mipmap-xxxhdpi/app_icon.png -------------------------------------------------------------------------------- /demo_shell/android/java/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /demo_shell/android/java/src/org/chromium/demo_shell/ShellViewAndroidDelegate.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | package org.chromium.demo_shell; 6 | 7 | import android.graphics.Bitmap; 8 | import android.view.ViewGroup; 9 | 10 | import org.chromium.ui.base.ViewAndroidDelegate; 11 | import org.chromium.ui_base.web.CursorType; 12 | 13 | /** 14 | * Implementation of the abstract class {@link ViewAndroidDelegate} for demo shell. 15 | * Extended for testing. 16 | */ 17 | public class ShellViewAndroidDelegate extends ViewAndroidDelegate { 18 | /** 19 | * An interface delegates a {@link CallbackHelper} for cursor update. see more in {@link 20 | * ContentViewPointerTypeTest.OnCursorUpdateHelperImpl}. 21 | */ 22 | public interface OnCursorUpdateHelper { 23 | /** 24 | * Record the last notifyCalled pointer type, see more {@link CallbackHelper#notifyCalled}. 25 | * @param type The pointer type of the notifyCalled. 26 | */ 27 | void notifyCalled(int type); 28 | } 29 | 30 | private OnCursorUpdateHelper mOnCursorUpdateHelper; 31 | 32 | public ShellViewAndroidDelegate(ViewGroup containerView) { 33 | super(containerView); 34 | } 35 | 36 | public void setOnCursorUpdateHelper(OnCursorUpdateHelper helper) { 37 | mOnCursorUpdateHelper = helper; 38 | } 39 | 40 | public OnCursorUpdateHelper getOnCursorUpdateHelper() { 41 | return mOnCursorUpdateHelper; 42 | } 43 | 44 | @Override 45 | public void onCursorChangedToCustom(Bitmap customCursorBitmap, int hotspotX, int hotspotY) { 46 | super.onCursorChangedToCustom(customCursorBitmap, hotspotX, hotspotY); 47 | if (mOnCursorUpdateHelper != null) { 48 | mOnCursorUpdateHelper.notifyCalled(CursorType.CUSTOM); 49 | } 50 | } 51 | 52 | @Override 53 | public void onCursorChanged(int cursorType) { 54 | super.onCursorChanged(cursorType); 55 | if (mOnCursorUpdateHelper != null) { 56 | mOnCursorUpdateHelper.notifyCalled(cursorType); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /demo_shell/android/shell_apk/AndroidManifest.xml.jinja2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% block extra_uses_permissions %} 23 | {% endblock %} 24 | 25 | 28 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | 49 | 51 | {% set num_sandboxed_services = 40 %} 52 | 54 | {% for i in range(num_sandboxed_services) %} 55 | 59 | {% endfor %} 60 | 61 | {% set num_privileged_services = 5 %} 62 | 64 | {% for i in range(num_privileged_services) %} 65 | 69 | {% endfor %} 70 | 72 | 73 | 75 | 76 | 78 | {% set num_test_services = 2 %} 79 | 81 | {% for i in range(num_test_services) %} 82 | 86 | {% endfor %} 87 | {% block extra_application_definitions_for_test %} 88 | {% endblock %} 89 | 90 | 91 | {% block extra_root_definitions %} 92 | {% endblock %} 93 | 94 | -------------------------------------------------------------------------------- /demo_shell/android/shell_apk/res/layout/demo_shell_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /demo_shell/android/shell_apk/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | Initialization failed. 11 | 12 | -------------------------------------------------------------------------------- /demo_shell/android/shell_apk/src/org/chromium/demo_shell_apk/DemoShellApplication.java: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | package org.chromium.demo_shell_apk; 6 | 7 | import android.app.Application; 8 | import android.content.Context; 9 | 10 | import org.chromium.base.ApplicationStatus; 11 | import org.chromium.base.BuildConfig; 12 | import org.chromium.base.CommandLine; 13 | import org.chromium.base.ContextUtils; 14 | import org.chromium.base.PathUtils; 15 | import org.chromium.base.multidex.ChromiumMultiDexInstaller; 16 | import org.chromium.ui.base.ResourceBundle; 17 | 18 | /** 19 | * Entry point for the demo shell application. Handles initialization of information that needs 20 | * to be shared across the main activity and the child services created. 21 | */ 22 | public class DemoShellApplication extends Application { 23 | public static final String COMMAND_LINE_FILE = "/data/local/tmp/content-shell-command-line"; 24 | private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "demo_shell"; 25 | 26 | @Override 27 | protected void attachBaseContext(Context base) { 28 | super.attachBaseContext(base); 29 | boolean isBrowserProcess = !ContextUtils.getProcessName().contains(":"); 30 | ContextUtils.initApplicationContext(this); 31 | ResourceBundle.setNoAvailableLocalePaks(); 32 | if (isBrowserProcess) { 33 | if (BuildConfig.IS_MULTIDEX_ENABLED) { 34 | ChromiumMultiDexInstaller.install(this); 35 | } 36 | PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX); 37 | ApplicationStatus.initialize(this); 38 | } 39 | } 40 | 41 | public void initCommandLine() { 42 | if (!CommandLine.isInitialized()) { 43 | CommandLine.initFromFile(COMMAND_LINE_FILE); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /demo_shell/app/demo_shell_content_main_delegate.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTENT_DEMO_SHELL_APP_DEMO_SHELL_CONTENT_MAIN_DELEGATE_H 2 | #define CONTENT_DEMO_SHELL_APP_DEMO_SHELL_CONTENT_MAIN_DELEGATE_H 3 | 4 | #include "content/public/app/content_main_delegate.h" 5 | #include "base/macros.h" 6 | #include "build/build_config.h" 7 | 8 | namespace content{ 9 | 10 | class ContentClient; 11 | class DemoShellContentBrowserClient; 12 | class ShellContentUtilityClient; 13 | class DemoShellContentRendererClient; 14 | 15 | class DemoShellContentMainDelegate : public content::ContentMainDelegate { 16 | public: 17 | 18 | DemoShellContentMainDelegate(); 19 | 20 | ~DemoShellContentMainDelegate() override; 21 | 22 | //基本的初始化工作完成,此时可以安全创建某些单例和检查命令行工作 23 | bool BasicStartupComplete(int* exit_code) override; 24 | 25 | //Sandbox启动前的逻辑,主要用于初始化User Data目录和PDF模块 26 | void PreSandboxStartup() override; 27 | 28 | // 用于请求embedder启动一个进程。 29 | int RunProcess( 30 | const std::string& process_type, 31 | const MainFunctionParams& main_function_params) override; 32 | 33 | #if defined(OS_LINUX) 34 | void ZygoteForked() override; 35 | #endif 36 | 37 | //如下函数由DemoContentMainRunnerImpl中的ContentClientInitializer调用 38 | ContentBrowserClient* CreateContentBrowserClient() override; 39 | ContentGpuClient* CreateContentGpuClient() override; 40 | ContentRendererClient* CreateContentRendererClient() override; 41 | ContentUtilityClient* CreateContentUtilityClient() override; 42 | 43 | static void InitializeResourceBundle(); 44 | 45 | private: 46 | 47 | std::unique_ptr browser_client_; 48 | std::unique_ptr gpu_client_; 49 | std::unique_ptr renderer_client_; 50 | std::unique_ptr utility_client_; 51 | std::unique_ptr content_client_; 52 | 53 | 54 | DISALLOW_COPY_AND_ASSIGN(DemoShellContentMainDelegate); 55 | 56 | }; 57 | 58 | } 59 | 60 | 61 | #endif //CONTENT_DEMO_SHELL_APP_DEMO_SHELL_MAIN_DELEGATE_H -------------------------------------------------------------------------------- /demo_shell/app/demo_shell_main.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "demo/demo_shell/app/demo_shell_content_main_delegate.h" 3 | #include "content/public/app/content_main.h" 4 | 5 | int main(int argc, const char** argv){ 6 | content::DemoShellContentMainDelegate demo_shell_content_delegate; 7 | content::ContentMainParams content_main_params(&demo_shell_content_delegate); 8 | content_main_params.argc = argc; 9 | content_main_params.argv = argv; 10 | content::ContentMain(content_main_params); 11 | } -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_browser_context.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_BROWSER_CONTEXT_H_ 6 | #define CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_BROWSER_CONTEXT_H_ 7 | 8 | #include 9 | 10 | #include "base/compiler_specific.h" 11 | #include "base/files/file_path.h" 12 | #include "base/macros.h" 13 | #include "base/memory/ref_counted.h" 14 | #include "content/public/browser/browser_context.h" 15 | #include "content/public/browser/content_browser_client.h" 16 | #include "content/public/browser/resource_context.h" 17 | #include "net/url_request/url_request_job_factory.h" 18 | 19 | namespace content { 20 | 21 | class BackgroundSyncController; 22 | class DownloadManagerDelegate; 23 | class PermissionControllerDelegate; 24 | class DemoShellDownloadManagerDelegate; 25 | class DemoShellPermissionManager; 26 | 27 | #if !defined(OS_ANDROID) 28 | class ZoomLevelDelegate; 29 | #endif // !defined(OS_ANDROID) 30 | 31 | class DemoShellBrowserContext : public BrowserContext { 32 | public: 33 | // If |delay_services_creation| is true, the owner is responsible for calling 34 | // CreateBrowserContextServices() for this BrowserContext. 35 | DemoShellBrowserContext(bool off_the_record, 36 | bool delay_services_creation = false); 37 | ~DemoShellBrowserContext() override; 38 | 39 | // BrowserContext implementation. 40 | base::FilePath GetPath() override; 41 | #if !defined(OS_ANDROID) 42 | std::unique_ptr CreateZoomLevelDelegate( 43 | const base::FilePath& partition_path) override; 44 | #endif // !defined(OS_ANDROID) 45 | bool IsOffTheRecord() override; 46 | DownloadManagerDelegate* GetDownloadManagerDelegate() override; 47 | ResourceContext* GetResourceContext() override; 48 | BrowserPluginGuestManager* GetGuestManager() override; 49 | storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override; 50 | PushMessagingService* GetPushMessagingService() override; 51 | StorageNotificationService* GetStorageNotificationService() override; 52 | SSLHostStateDelegate* GetSSLHostStateDelegate() override; 53 | PermissionControllerDelegate* GetPermissionControllerDelegate() override; 54 | ClientHintsControllerDelegate* GetClientHintsControllerDelegate() override; 55 | BackgroundFetchDelegate* GetBackgroundFetchDelegate() override; 56 | BackgroundSyncController* GetBackgroundSyncController() override; 57 | BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate() override; 58 | ContentIndexProvider* GetContentIndexProvider() override; 59 | 60 | protected: 61 | // Contains URLRequestContextGetter required for resource loading. 62 | class DemoShellResourceContext : public ResourceContext { 63 | public: 64 | DemoShellResourceContext(); 65 | ~DemoShellResourceContext() override; 66 | 67 | DISALLOW_COPY_AND_ASSIGN(DemoShellResourceContext); 68 | }; 69 | 70 | std::unique_ptr resource_context_; 71 | std::unique_ptr download_manager_delegate_; 72 | std::unique_ptr permission_manager_; 73 | std::unique_ptr background_sync_controller_; 74 | 75 | private: 76 | // Performs initialization of the ShellBrowserContext while IO is still 77 | // allowed on the current thread. 78 | void InitWhileIOAllowed(); 79 | 80 | bool off_the_record_; 81 | base::FilePath path_; 82 | 83 | DISALLOW_COPY_AND_ASSIGN(DemoShellBrowserContext); 84 | }; 85 | 86 | } // namespace content 87 | 88 | #endif // CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_BROWSER_CONTEXT_H_ 89 | -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_browser_main_parts.cc: -------------------------------------------------------------------------------- 1 | #include "demo/demo_shell/browser/demo_shell_browser_main_parts.h" 2 | 3 | #include "content/public/browser/browser_context.h" 4 | #include "ui/base/material_design/material_design_controller.h" 5 | 6 | #if defined(OS_ANDROID) 7 | #include "components/crash/content/browser/child_exit_observer_android.h" 8 | #include "components/crash/content/browser/child_process_crash_observer_android.h" 9 | #include "net/android/network_change_notifier_factory_android.h" 10 | #include "net/base/network_change_notifier.h" 11 | #endif 12 | 13 | 14 | #if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(OS_LINUX) 15 | #include "ui/base/ime/init/input_method_initializer.h" 16 | #endif 17 | #if defined(USE_AURA) && defined(USE_X11) 18 | #include "ui/events/devices/x11/touch_factory_x11.h" // nogncheck 19 | #endif 20 | 21 | #include "demo/demo_shell/browser/shell.h" 22 | 23 | namespace content{ 24 | 25 | namespace{ 26 | // GURL GetStartupURL(){ 27 | // return GURL("http://www.baidu.com"); 28 | // } 29 | } 30 | 31 | DemoShellBrowserMainParts::DemoShellBrowserMainParts(const MainFunctionParams& params) 32 | : main_function_params_(params) 33 | , run_message_loop_(true) { 34 | } 35 | 36 | DemoShellBrowserMainParts::~DemoShellBrowserMainParts() { 37 | 38 | } 39 | 40 | // BrowserMainParts s. 41 | int DemoShellBrowserMainParts::PreEarlyInitialization() { 42 | DLOG(INFO) << "============ PreEarlyInitialization"; 43 | 44 | #if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(OS_LINUX) 45 | ui::InitializeInputMethodForTesting(); 46 | #endif 47 | #if defined(OS_ANDROID) 48 | net::NetworkChangeNotifier::SetFactory( 49 | new net::NetworkChangeNotifierFactoryAndroid()); 50 | #endif 51 | return BrowserMainParts::PreEarlyInitialization(); 52 | } 53 | 54 | int DemoShellBrowserMainParts::PreCreateThreads() { 55 | DLOG(INFO) << "============ PreCreateThreads"; 56 | // #if defined(OS_ANDROID) 57 | // const base::CommandLine* command_line = 58 | // base::CommandLine::ForCurrentProcess(); 59 | // crash_reporter::ChildExitObserver::Create(); 60 | // if (command_line->HasSwitch(switches::kEnableCrashReporter)) { 61 | // crash_reporter::ChildExitObserver::GetInstance()->RegisterClient( 62 | // std::make_unique()); 63 | // } 64 | // #endif 65 | return 0; 66 | } 67 | 68 | void DemoShellBrowserMainParts::PreMainMessageLoopStart() { 69 | DLOG(INFO) << "============ PreMainMessageLoopStart"; 70 | 71 | #if defined(USE_AURA) && defined(USE_X11) 72 | ui::TouchFactory::SetTouchDeviceListFromCommandLine(); 73 | #endif 74 | } 75 | 76 | void DemoShellBrowserMainParts::PostMainMessageLoopStart() { 77 | DLOG(INFO) << "============ PostMainMessageLoopStart"; 78 | 79 | } 80 | 81 | void DemoShellBrowserMainParts::InitializeBrowserContexts(){ 82 | DLOG(INFO) << "============ InitializeBrowserContexts"; 83 | 84 | browser_context_.reset(new DemoShellBrowserContext(false)); 85 | } 86 | 87 | void DemoShellBrowserMainParts::InitializeMessageLoopContext(){ 88 | DLOG(INFO) << "============ InitializeMessageLoopContext"; 89 | 90 | ui::MaterialDesignController::Initialize(); 91 | DemoShell::CreateNewWindow(browser_context_.get(), GURL("http://www.baidu.com"), nullptr, 92 | gfx::Size()); 93 | } 94 | 95 | 96 | void DemoShellBrowserMainParts::PreMainMessageLoopRun() { 97 | DLOG(INFO) << "============ PreMainMessageLoopRun1"; 98 | InitializeBrowserContexts(); 99 | DemoShell::Initialize(); 100 | InitializeMessageLoopContext(); 101 | if (main_function_params_.ui_task) { 102 | DLOG(INFO) << "============ PreMainMessageLoopRun2"; 103 | std::move(*main_function_params_.ui_task).Run(); 104 | delete main_function_params_.ui_task; 105 | run_message_loop_ = false; 106 | } 107 | } 108 | 109 | bool DemoShellBrowserMainParts::MainMessageLoopRun(int* result_code) { 110 | DLOG(INFO) << "============ MainMessageLoopRun"; 111 | return !run_message_loop_; 112 | } 113 | 114 | void DemoShellBrowserMainParts::PreDefaultMainMessageLoopRun(base::OnceClosure quit_closure) { 115 | DLOG(INFO) << "============ PreDefaultMainMessageLoopRun"; 116 | DemoShell::SetMainMessageLoopQuitClosure(std::move(quit_closure)); 117 | } 118 | 119 | void DemoShellBrowserMainParts::PostMainMessageLoopRun() { 120 | DLOG(INFO) << "============ PostMainMessageLoopRun"; 121 | browser_context_.reset(); 122 | } 123 | 124 | void DemoShellBrowserMainParts::PostDestroyThreads() { 125 | DLOG(INFO) << "============ PostDestroyThreads"; 126 | } 127 | 128 | 129 | } -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_browser_main_parts.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_BROWSER_MAIN_PARTS_H_ 2 | #define CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_BROWSER_MAIN_PARTS_H_ 3 | 4 | #include "content/public/browser/browser_main_parts.h" 5 | #include "content/public/common/main_function_params.h" 6 | #include "base/macros.h" 7 | 8 | #include "demo/demo_shell/browser/demo_shell_browser_context.h" 9 | 10 | namespace content { 11 | 12 | class DemoShellBrowserMainParts : public BrowserMainParts { 13 | public: 14 | DemoShellBrowserMainParts(const MainFunctionParams& params); 15 | ~DemoShellBrowserMainParts() override; 16 | 17 | // BrowserMainParts overrides. 18 | int PreEarlyInitialization() override; 19 | int PreCreateThreads() override; 20 | void PreMainMessageLoopStart() override; 21 | void PostMainMessageLoopStart() override; 22 | void PreMainMessageLoopRun() override; 23 | bool MainMessageLoopRun(int* result_code) override; 24 | void PreDefaultMainMessageLoopRun(base::OnceClosure quit_closure) override; 25 | void PostMainMessageLoopRun() override; 26 | void PostDestroyThreads() override; 27 | 28 | DemoShellBrowserContext* browser_context() { 29 | return browser_context_.get(); 30 | } 31 | 32 | protected: 33 | virtual void InitializeBrowserContexts(); 34 | virtual void InitializeMessageLoopContext(); 35 | 36 | 37 | private: 38 | const MainFunctionParams main_function_params_; 39 | bool run_message_loop_; 40 | 41 | std::unique_ptr browser_context_; 42 | 43 | DISALLOW_COPY_AND_ASSIGN(DemoShellBrowserMainParts); 44 | }; 45 | 46 | } 47 | 48 | #endif //CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_BROWSER_MAIN_PARTS_H_ -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_content_browser_client.cc: -------------------------------------------------------------------------------- 1 | #include "demo/demo_shell/browser/demo_shell_content_browser_client.h" 2 | #include "demo/demo_shell/browser/demo_shell_browser_main_parts.h" 3 | #include "demo/demo_shell/browser/demo_shell_browser_context.h" 4 | 5 | 6 | namespace content{ 7 | 8 | DemoShellContentBrowserClient* g_demo_content_browser_client; 9 | DemoShellContentBrowserClient* DemoShellContentBrowserClient::Get(){ 10 | return g_demo_content_browser_client; 11 | } 12 | 13 | DemoShellContentBrowserClient::DemoShellContentBrowserClient() 14 | :demo_shell_browser_main_parts_(nullptr){ 15 | DCHECK(!g_demo_content_browser_client); 16 | g_demo_content_browser_client = this; 17 | } 18 | 19 | DemoShellContentBrowserClient::~DemoShellContentBrowserClient() { 20 | g_demo_content_browser_client = nullptr; 21 | } 22 | 23 | std::unique_ptr DemoShellContentBrowserClient::CreateBrowserMainParts( 24 | const MainFunctionParams& parameters) { 25 | auto parts = std::make_unique(parameters); 26 | demo_shell_browser_main_parts_ = parts.get(); 27 | return parts; 28 | } 29 | 30 | DemoShellBrowserContext* DemoShellContentBrowserClient::browser_context() { 31 | if(demo_shell_browser_main_parts_) { 32 | return demo_shell_browser_main_parts_->browser_context(); 33 | } 34 | return nullptr; 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_content_browser_client.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_CONTENT_BROWSER_CLIENT_H_ 2 | #define CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_CONTENT_BROWSER_CLIENT_H_ 3 | 4 | #include "content/public/browser/content_browser_client.h" 5 | 6 | 7 | namespace content{ 8 | 9 | class DemoShellBrowserMainParts; 10 | class DemoShellBrowserContext; 11 | 12 | class DemoShellContentBrowserClient : public ContentBrowserClient { 13 | public: 14 | static DemoShellContentBrowserClient* Get(); 15 | 16 | DemoShellContentBrowserClient(); 17 | ~DemoShellContentBrowserClient() override; 18 | 19 | // ContentBrowserClient overrides. 20 | std::unique_ptr CreateBrowserMainParts( 21 | const MainFunctionParams& parameters) override; 22 | 23 | DemoShellBrowserContext* browser_context(); 24 | 25 | private: 26 | DemoShellBrowserMainParts* demo_shell_browser_main_parts_ = nullptr; 27 | 28 | }; 29 | 30 | } 31 | 32 | #endif //CONTENT_DEMO_SHELL_BROWSER_DEMO_SHELL_CONTENT_BROWSER_CLIENT_H_ -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_download_manager_delegate.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef CONTENT_DEMO_SHELL_BROWSER_SHELL_DOWNLOAD_MANAGER_DELEGATE_H_ 6 | #define CONTENT_DEMO_SHELL_BROWSER_SHELL_DOWNLOAD_MANAGER_DELEGATE_H_ 7 | 8 | #include 9 | 10 | #include "base/callback_forward.h" 11 | #include "base/compiler_specific.h" 12 | #include "base/macros.h" 13 | #include "base/memory/weak_ptr.h" 14 | #include "content/public/browser/download_manager_delegate.h" 15 | 16 | namespace content { 17 | 18 | class DownloadManager; 19 | 20 | class DemoShellDownloadManagerDelegate : public DownloadManagerDelegate { 21 | public: 22 | DemoShellDownloadManagerDelegate(); 23 | ~DemoShellDownloadManagerDelegate() override; 24 | 25 | void SetDownloadManager(DownloadManager* manager); 26 | 27 | void Shutdown() override; 28 | bool DetermineDownloadTarget(download::DownloadItem* download, 29 | const DownloadTargetCallback& callback) override; 30 | bool ShouldOpenDownload(download::DownloadItem* item, 31 | const DownloadOpenDelayedCallback& callback) override; 32 | void GetNextId(const DownloadIdCallback& callback) override; 33 | 34 | private: 35 | friend class base::RefCountedThreadSafe; 36 | 37 | using FilenameDeterminedCallback = 38 | base::OnceCallback; 39 | 40 | static void GenerateFilename(const GURL& url, 41 | const std::string& content_disposition, 42 | const std::string& suggested_filename, 43 | const std::string& mime_type, 44 | const base::FilePath& suggested_directory, 45 | FilenameDeterminedCallback callback); 46 | void OnDownloadPathGenerated(uint32_t download_id, 47 | const DownloadTargetCallback& callback, 48 | const base::FilePath& suggested_path); 49 | void ChooseDownloadPath(uint32_t download_id, 50 | const DownloadTargetCallback& callback, 51 | const base::FilePath& suggested_path); 52 | 53 | DownloadManager* download_manager_; 54 | base::FilePath default_download_path_; 55 | bool suppress_prompting_; 56 | base::WeakPtrFactory weak_ptr_factory_{this}; 57 | 58 | DISALLOW_COPY_AND_ASSIGN(DemoShellDownloadManagerDelegate); 59 | }; 60 | 61 | } // namespace content 62 | 63 | #endif // CONTENT_DEMO_SHELL_BROWSER_SHELL_DOWNLOAD_MANAGER_DELEGATE_H_ 64 | -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_permission_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef CONTENT_SHELL_BROWSER_SHELL_PERMISSION_MANAGER_H_ 6 | #define CONTENT_SHELL_BROWSER_SHELL_PERMISSION_MANAGER_H_ 7 | 8 | #include "base/callback_forward.h" 9 | #include "base/macros.h" 10 | #include "content/public/browser/permission_controller_delegate.h" 11 | 12 | namespace content { 13 | 14 | class DemoShellPermissionManager : public PermissionControllerDelegate { 15 | public: 16 | DemoShellPermissionManager(); 17 | ~DemoShellPermissionManager() override; 18 | 19 | // PermissionManager implementation. 20 | int RequestPermission(PermissionType permission, 21 | RenderFrameHost* render_frame_host, 22 | const GURL& requesting_origin, 23 | bool user_gesture, 24 | base::OnceCallback 25 | callback) override; 26 | int RequestPermissions( 27 | const std::vector& permission, 28 | RenderFrameHost* render_frame_host, 29 | const GURL& requesting_origin, 30 | bool user_gesture, 31 | base::OnceCallback< 32 | void(const std::vector&)> callback) 33 | override; 34 | void ResetPermission(PermissionType permission, 35 | const GURL& requesting_origin, 36 | const GURL& embedding_origin) override; 37 | blink::mojom::PermissionStatus GetPermissionStatus( 38 | PermissionType permission, 39 | const GURL& requesting_origin, 40 | const GURL& embedding_origin) override; 41 | blink::mojom::PermissionStatus GetPermissionStatusForFrame( 42 | content::PermissionType permission, 43 | content::RenderFrameHost* render_frame_host, 44 | const GURL& requesting_origin) override; 45 | int SubscribePermissionStatusChange( 46 | PermissionType permission, 47 | RenderFrameHost* render_frame_host, 48 | const GURL& requesting_origin, 49 | base::RepeatingCallback callback) 50 | override; 51 | void UnsubscribePermissionStatusChange(int subscription_id) override; 52 | 53 | private: 54 | DISALLOW_COPY_AND_ASSIGN(DemoShellPermissionManager); 55 | }; 56 | 57 | } // namespace content 58 | 59 | #endif // CONTENT_SHELL_BROWSER_SHELL_PERMISSION_MANAGER_H 60 | -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_platform_data_aura.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "demo/demo_shell/browser/demo_shell_platform_data_aura.h" 6 | 7 | #include "base/macros.h" 8 | #include "build/build_config.h" 9 | #include "ui/aura/client/default_capture_client.h" 10 | #include "ui/aura/env.h" 11 | #include "ui/aura/layout_manager.h" 12 | #include "ui/aura/test/test_focus_client.h" 13 | #include "ui/aura/test/test_screen.h" 14 | #include "ui/aura/test/test_window_parenting_client.h" 15 | #include "ui/aura/window.h" 16 | #include "ui/aura/window_event_dispatcher.h" 17 | #include "ui/ozone/public/ozone_platform.h" 18 | #include "ui/platform_window/platform_window_init_properties.h" 19 | #include "ui/wm/core/default_activation_client.h" 20 | 21 | #if defined(USE_OZONE) 22 | #include "ui/aura/screen_ozone.h" 23 | #endif 24 | 25 | #include "demo/demo_shell/browser/shell.h" 26 | 27 | namespace content { 28 | 29 | namespace { 30 | 31 | class FillLayout : public aura::LayoutManager { 32 | public: 33 | explicit FillLayout(aura::Window* root) 34 | : root_(root), has_bounds_(!root->bounds().IsEmpty()) {} 35 | 36 | ~FillLayout() override {} 37 | 38 | private: 39 | // aura::LayoutManager: 40 | void OnWindowResized() override { 41 | // If window bounds were not set previously then resize all children to 42 | // match the size of the parent. 43 | if (!has_bounds_) { 44 | has_bounds_ = true; 45 | for (aura::Window* child : root_->children()) 46 | SetChildBoundsDirect(child, gfx::Rect(root_->bounds().size())); 47 | } 48 | } 49 | 50 | void OnWindowAddedToLayout(aura::Window* child) override { 51 | child->SetBounds(root_->bounds()); 52 | } 53 | 54 | void OnWillRemoveWindowFromLayout(aura::Window* child) override {} 55 | 56 | void OnWindowRemovedFromLayout(aura::Window* child) override {} 57 | 58 | void OnChildWindowVisibilityChanged(aura::Window* child, 59 | bool visible) override {} 60 | 61 | void SetChildBounds(aura::Window* child, 62 | const gfx::Rect& requested_bounds) override { 63 | SetChildBoundsDirect(child, requested_bounds); 64 | } 65 | 66 | aura::Window* root_; 67 | bool has_bounds_; 68 | 69 | DISALLOW_COPY_AND_ASSIGN(FillLayout); 70 | }; 71 | 72 | } 73 | 74 | DemoShellPlatformDataAura::DemoShellPlatformDataAura(const gfx::Size& initial_size) { 75 | CHECK(aura::Env::GetInstance()); 76 | 77 | #if defined(USE_OZONE) 78 | // Setup global display::Screen singleton. 79 | if (!display::Screen::GetScreen()) { 80 | screen_ = std::make_unique(); 81 | display::Screen::SetScreenInstance(screen_.get()); 82 | } 83 | #endif // defined(USE_OZONE) 84 | 85 | ui::PlatformWindowInitProperties properties; 86 | properties.bounds = gfx::Rect(initial_size); 87 | 88 | host_ = aura::WindowTreeHost::Create(std::move(properties)); 89 | host_->InitHost(); 90 | host_->window()->Show(); 91 | host_->window()->SetLayoutManager(new FillLayout(host_->window())); 92 | 93 | focus_client_.reset(new aura::test::TestFocusClient()); 94 | aura::client::SetFocusClient(host_->window(), focus_client_.get()); 95 | 96 | new wm::DefaultActivationClient(host_->window()); 97 | capture_client_.reset( 98 | new aura::client::DefaultCaptureClient(host_->window())); 99 | window_parenting_client_.reset( 100 | new aura::test::TestWindowParentingClient(host_->window())); 101 | } 102 | 103 | DemoShellPlatformDataAura::~DemoShellPlatformDataAura() { 104 | if (screen_) 105 | display::Screen::SetScreenInstance(nullptr); 106 | } 107 | 108 | void DemoShellPlatformDataAura::ShowWindow() { 109 | host_->Show(); 110 | } 111 | 112 | void DemoShellPlatformDataAura::ResizeWindow(const gfx::Size& size) { 113 | host_->SetBoundsInPixels(gfx::Rect(size)); 114 | } 115 | 116 | } // namespace content 117 | -------------------------------------------------------------------------------- /demo_shell/browser/demo_shell_platform_data_aura.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef CONTENT_DEMO_SHELL_BROWSER_SHELL_PLATFORM_DATA_AURA_H_ 6 | #define CONTENT_DEMO_SHELL_BROWSER_SHELL_PLATFORM_DATA_AURA_H_ 7 | 8 | #include 9 | 10 | #include "base/macros.h" 11 | #include "ui/aura/window_tree_host.h" 12 | 13 | namespace aura { 14 | namespace client { 15 | class DefaultCaptureClient; 16 | class FocusClient; 17 | class WindowParentingClient; 18 | } 19 | } 20 | 21 | namespace display { 22 | class Screen; 23 | } 24 | 25 | namespace gfx { 26 | class Size; 27 | } 28 | 29 | namespace content { 30 | 31 | class DemoShellPlatformDataAura { 32 | public: 33 | explicit DemoShellPlatformDataAura(const gfx::Size& initial_size); 34 | ~DemoShellPlatformDataAura(); 35 | 36 | void ShowWindow(); 37 | void ResizeWindow(const gfx::Size& size); 38 | 39 | aura::WindowTreeHost* host() { return host_.get(); } 40 | 41 | private: 42 | std::unique_ptr screen_; 43 | 44 | std::unique_ptr host_; 45 | std::unique_ptr focus_client_; 46 | std::unique_ptr capture_client_; 47 | std::unique_ptr window_parenting_client_; 48 | 49 | DISALLOW_COPY_AND_ASSIGN(DemoShellPlatformDataAura); 50 | }; 51 | 52 | } // namespace content 53 | 54 | #endif // CONTENT_DEMO_SHELL_BROWSER_SHELL_PLATFORM_DATA_AURA_H_ 55 | -------------------------------------------------------------------------------- /demo_shell/browser/shell.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "demo/demo_shell/browser/shell.h" 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "base/command_line.h" 14 | #include "base/location.h" 15 | #include "base/macros.h" 16 | #include "base/no_destructor.h" 17 | #include "base/run_loop.h" 18 | #include "base/single_thread_task_runner.h" 19 | #include "base/strings/string_number_conversions.h" 20 | #include "base/strings/string_util.h" 21 | #include "base/strings/stringprintf.h" 22 | #include "base/strings/utf_string_conversions.h" 23 | #include "base/threading/thread_task_runner_handle.h" 24 | #include "build/build_config.h" 25 | #include "content/public/browser/web_contents.h" 26 | #include "content/public/common/content_switches.h" 27 | #include "content/public/browser/render_view_host.h" 28 | #include "content/public/browser/render_widget_host.h" 29 | 30 | namespace content { 31 | 32 | // Null until/unless the default main message loop is running. 33 | base::NoDestructor g_quit_main_message_loop; 34 | 35 | const int kDefaultTestWindowWidthDip = 800; 36 | const int kDefaultTestWindowHeightDip = 600; 37 | 38 | DemoShell::DemoShell(std::unique_ptr web_contents, 39 | bool should_set_delegate) 40 | : web_contents_(std::move(web_contents)), 41 | window_(nullptr), 42 | is_fullscreen_(false) { 43 | web_contents_->SetDelegate(this); 44 | } 45 | 46 | DemoShell::~DemoShell() { 47 | PlatformCleanUp(); 48 | 49 | // Always destroy WebContents before calling PlatformExit(). WebContents 50 | // destruction sequence may depend on the resources destroyed in 51 | // PlatformExit() (e.g. the display::Screen singleton). 52 | web_contents_->SetDelegate(nullptr); 53 | web_contents_.reset(); 54 | 55 | 56 | if (*g_quit_main_message_loop) 57 | std::move(*g_quit_main_message_loop).Run(); 58 | 59 | } 60 | 61 | DemoShell* DemoShell::CreateShell(std::unique_ptr web_contents, 62 | const gfx::Size& initial_size, 63 | bool should_set_delegate) { 64 | DemoShell* shell = new DemoShell(std::move(web_contents), should_set_delegate); 65 | shell->PlatformCreateWindow(initial_size.width(), initial_size.height()); 66 | shell->PlatformSetContents(); 67 | 68 | return shell; 69 | } 70 | 71 | void DemoShell::SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) { 72 | *g_quit_main_message_loop = std::move(quit_closure); 73 | } 74 | 75 | void DemoShell::Initialize() { 76 | PlatformInitialize(GetShellDefaultSize()); 77 | } 78 | 79 | DemoShell* DemoShell::CreateNewWindow(BrowserContext* browser_context, 80 | const GURL& url, 81 | const scoped_refptr& site_instance, 82 | const gfx::Size& initial_size) { 83 | WebContents::CreateParams create_params(browser_context, site_instance); 84 | std::unique_ptr web_contents = 85 | WebContents::Create(create_params); 86 | DemoShell* shell = 87 | CreateShell(std::move(web_contents), GetShellDefaultSize(), 88 | true /* should_set_delegate */); 89 | if (!url.is_empty()) 90 | shell->LoadURLForFrame(url, std::string(), ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)); 91 | return shell; 92 | } 93 | 94 | void DemoShell::LoadURLForFrame(const GURL& url, 95 | const std::string& frame_name, 96 | ui::PageTransition transition_type) { 97 | NavigationController::LoadURLParams params(url); 98 | params.frame_name = frame_name; 99 | params.transition_type = transition_type; 100 | web_contents_->GetController().LoadURLWithParams(params); 101 | web_contents_->Focus(); 102 | } 103 | 104 | gfx::Size DemoShell::GetShellDefaultSize() { 105 | return gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip); 106 | } 107 | 108 | void DemoShell::EnterFullscreenModeForTab( 109 | WebContents* web_contents, 110 | const GURL& origin, 111 | const blink::mojom::FullscreenOptions& options) { 112 | ToggleFullscreenModeForTab(web_contents, true); 113 | } 114 | 115 | void DemoShell::ExitFullscreenModeForTab(WebContents* web_contents) { 116 | ToggleFullscreenModeForTab(web_contents, false); 117 | } 118 | 119 | void DemoShell::ToggleFullscreenModeForTab(WebContents* web_contents, 120 | bool enter_fullscreen) { 121 | if (is_fullscreen_ != enter_fullscreen) { 122 | is_fullscreen_ = enter_fullscreen; 123 | web_contents->GetRenderViewHost() 124 | ->GetWidget() 125 | ->SynchronizeVisualProperties(); 126 | } 127 | } 128 | 129 | bool DemoShell::IsFullscreenForTabOrPending(const WebContents* web_contents) { 130 | return is_fullscreen_; 131 | } 132 | 133 | } // namespace content 134 | -------------------------------------------------------------------------------- /demo_shell/browser/shell.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | #ifndef CONTENT_DEMO_SHELL_BROWSER_SHELL_H_ 5 | #define CONTENT_DEMO_SHELL_BROWSER_SHELL_H_ 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "base/callback_forward.h" 14 | #include "base/memory/ref_counted.h" 15 | #include "base/strings/string_piece.h" 16 | #include "build/build_config.h" 17 | #include "content/public/browser/web_contents_delegate.h" 18 | #include "content/public/browser/session_storage_namespace.h" 19 | #include "content/public/browser/web_contents_observer.h" 20 | #include "ipc/ipc_channel.h" 21 | #include "ui/gfx/geometry/size.h" 22 | #include "ui/gfx/native_widget_types.h" 23 | 24 | #if defined(OS_ANDROID) 25 | #include "base/android/scoped_java_ref.h" 26 | #elif defined(USE_AURA) 27 | #if defined(OS_CHROMEOS) 28 | 29 | namespace wm { 30 | class WMTestHelper; 31 | } 32 | #endif // defined(OS_CHROMEOS) 33 | namespace views { 34 | class Widget; 35 | class ViewsDelegate; 36 | } 37 | namespace wm { 38 | class WMState; 39 | } 40 | #endif // defined(USE_AURA) 41 | 42 | class GURL; 43 | namespace content { 44 | 45 | #if defined(USE_AURA) 46 | class DemoShellPlatformDataAura; 47 | #endif 48 | 49 | class BrowserContext; 50 | class WebContents; 51 | 52 | // This represents one window of the Content DemoShell, i.e. all the UI including 53 | // buttons and url bar, as well as the web content area. 54 | class DemoShell : public content::WebContentsDelegate{ 55 | public: 56 | ~DemoShell(); 57 | 58 | // Do one time initialization at application startup. 59 | static void Initialize(); 60 | 61 | static DemoShell* CreateNewWindow( 62 | BrowserContext* browser_context, 63 | const GURL& url, 64 | const scoped_refptr& site_instance, 65 | const gfx::Size& initial_size); 66 | 67 | // Stores the supplied |quit_closure|, to be run when the last DemoShell instance 68 | // is destroyed. 69 | static void SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure); 70 | 71 | static gfx::Size GetShellDefaultSize(); 72 | void LoadURLForFrame(const GURL& url, 73 | const std::string& frame_name, 74 | ui::PageTransition); 75 | 76 | WebContents* web_contents() const { return web_contents_.get(); } 77 | 78 | void EnterFullscreenModeForTab( 79 | WebContents* web_contents, 80 | const GURL& origin, 81 | const blink::mojom::FullscreenOptions& options) override; 82 | void ExitFullscreenModeForTab(WebContents* web_contents) override; 83 | bool IsFullscreenForTabOrPending(const WebContents* web_contents) override; 84 | 85 | private: 86 | 87 | DemoShell(std::unique_ptr web_contents, bool should_set_delegate); 88 | 89 | // Helper to create a new DemoShell given a newly created WebContents. 90 | static DemoShell* CreateShell(std::unique_ptr web_contents, 91 | const gfx::Size& initial_size, 92 | bool should_set_delegate); 93 | 94 | // Helper for one time initialization of application 95 | static void PlatformInitialize(const gfx::Size& default_window_size); 96 | // Links the WebContents into the newly created window. 97 | void PlatformSetContents(); 98 | // Helper for one time deinitialization of platform specific state. 99 | static void PlatformExit(); 100 | 101 | void PlatformCleanUp(); 102 | // Creates the main window GUI. 103 | void PlatformCreateWindow(int width, int height); 104 | #if defined(OS_MACOSX) || defined(OS_ANDROID) 105 | // Resizes the web content view to the given dimensions. 106 | void SizeTo(const gfx::Size& content_size); 107 | #endif 108 | void ToggleFullscreenModeForTab(WebContents* web_contents, 109 | bool enter_fullscreen); 110 | std::unique_ptr web_contents_; 111 | 112 | gfx::NativeWindow window_; 113 | 114 | gfx::Size content_size_; 115 | 116 | bool is_fullscreen_; 117 | 118 | #if defined(OS_ANDROID) 119 | base::android::ScopedJavaGlobalRef java_object_; 120 | #elif defined(USE_AURA) 121 | static wm::WMState* wm_state_; 122 | #if defined(TOOLKIT_VIEWS) 123 | static views::ViewsDelegate* views_delegate_; 124 | 125 | views::Widget* window_widget_; 126 | #endif // defined(TOOLKIT_VIEWS) 127 | #endif // defined(USE_AURA) 128 | }; 129 | 130 | } // namespace content 131 | 132 | #endif // CONTENT_DEMO_SHELL_BROWSER_SHELL_H_ 133 | -------------------------------------------------------------------------------- /demo_shell/browser/shell_android.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "demo/demo_shell/browser/shell.h" 6 | 7 | #include 8 | 9 | #include "base/android/jni_string.h" 10 | #include "base/android/scoped_java_ref.h" 11 | #include "base/command_line.h" 12 | #include "base/logging.h" 13 | #include "base/strings/string_piece.h" 14 | #include "content/public/browser/web_contents.h" 15 | #include "content/public/common/content_switches.h" 16 | 17 | #include "demo/demo_shell/android/demo_shell_jni_headers/Shell_jni.h" 18 | #include "demo/demo_shell/android/demo_shell_manager.h" 19 | 20 | using base::android::AttachCurrentThread; 21 | using base::android::ConvertUTF8ToJavaString; 22 | using base::android::JavaParamRef; 23 | using base::android::ScopedJavaLocalRef; 24 | 25 | namespace content { 26 | 27 | void DemoShell::PlatformInitialize(const gfx::Size& default_window_size) { 28 | DLOG(INFO) << "=========PlatformInitialize"; 29 | } 30 | 31 | void DemoShell::PlatformExit() { 32 | DLOG(INFO) << "=========PlatformExit"; 33 | 34 | DestroyShellManager(); 35 | } 36 | 37 | void DemoShell::PlatformCleanUp() { 38 | DLOG(INFO) << "=========PlatformCleanUp"; 39 | 40 | JNIEnv* env = AttachCurrentThread(); 41 | if (java_object_.is_null()) 42 | return; 43 | Java_Shell_onNativeDestroyed(env, java_object_); 44 | } 45 | 46 | void DemoShell::PlatformCreateWindow(int width, int height) { 47 | DLOG(INFO) << "=========PlatformCreateWindow"; 48 | 49 | java_object_.Reset(CreateShellView(this)); 50 | } 51 | 52 | void DemoShell::PlatformSetContents() { 53 | DLOG(INFO) << "=========PlatformSetContents"; 54 | 55 | JNIEnv* env = AttachCurrentThread(); 56 | Java_Shell_initFromNativeTabContents(env, java_object_, 57 | web_contents()->GetJavaWebContents()); 58 | } 59 | 60 | void DemoShell::SizeTo(const gfx::Size& content_size) { 61 | DLOG(INFO) << "=========SizeTo"; 62 | 63 | JNIEnv* env = AttachCurrentThread(); 64 | Java_Shell_sizeTo(env, java_object_, content_size.width(), 65 | content_size.height()); 66 | } 67 | 68 | 69 | // static 70 | void JNI_Shell_CloseShell(JNIEnv* env, 71 | jlong shellPtr) { 72 | DLOG(INFO) << "=========JNI_Shell_CloseShell"; 73 | 74 | // DemoShell* shell = reinterpret_cast(shellPtr); 75 | 76 | } 77 | 78 | } // namespace content 79 | -------------------------------------------------------------------------------- /demo_shell/common/demo_shell_content_client.cc: -------------------------------------------------------------------------------- 1 | #include "demo/demo_shell/common/demo_shell_content_client.h" 2 | 3 | #include "content/public/common/user_agent.h" 4 | #include "ui/base/l10n/l10n_util.h" 5 | #include "ui/base/resource/resource_bundle.h" 6 | #include "content/public/common/content_switches.h" 7 | #include "base/command_line.h" 8 | #include "base/values.h" 9 | 10 | namespace content{ 11 | 12 | DemoShellContentClient::DemoShellContentClient() = default; 13 | 14 | DemoShellContentClient::~DemoShellContentClient() = default; 15 | 16 | base::string16 DemoShellContentClient::GetLocalizedString(int message_id) { 17 | return l10n_util::GetStringUTF16(message_id); 18 | } 19 | 20 | base::StringPiece DemoShellContentClient::GetDataResource( 21 | int resource_id, 22 | ui::ScaleFactor scale_factor) { 23 | return ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale( 24 | resource_id, scale_factor); 25 | } 26 | 27 | base::RefCountedMemory* DemoShellContentClient::GetDataResourceBytes( 28 | int resource_id) { 29 | return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes( 30 | resource_id); 31 | } 32 | 33 | gfx::Image& DemoShellContentClient::GetNativeImageNamed(int resource_id){ 34 | return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( 35 | resource_id); 36 | } 37 | 38 | base::DictionaryValue DemoShellContentClient::GetNetLogConstants() { 39 | base::DictionaryValue client_constants; 40 | client_constants.SetString("name", "demo_shell"); 41 | client_constants.SetString( 42 | "command_line", 43 | base::CommandLine::ForCurrentProcess()->GetCommandLineString()); 44 | base::DictionaryValue constants; 45 | constants.SetKey("clientInfo", std::move(client_constants)); 46 | return constants; 47 | } 48 | 49 | blink::OriginTrialPolicy* DemoShellContentClient::GetOriginTrialPolicy(){ 50 | // return &origin_trial_policy_; 51 | return nullptr; 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /demo_shell/common/demo_shell_content_client.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTENT_DEMO_SHELL_COMMON_DEMO_SHELL_CONTENT_CLIENT_H_ 2 | #define CONTENT_DEMO_SHELL_COMMON_DEMO_SHELL_CONTENT_CLIENT_H_ 3 | 4 | #include 5 | #include "content/public/common/content_client.h" 6 | #include "base/compiler_specific.h" 7 | // #include "demo_shell/common/demo_shell_origin_trial_policy.h" 8 | 9 | 10 | namespace content { 11 | std::string GetDemoShellUserAgent(); 12 | 13 | class DemoShellContentClient : public content::ContentClient { 14 | public: 15 | DemoShellContentClient(); 16 | ~DemoShellContentClient() override; 17 | 18 | base::string16 GetLocalizedString(int message_id) override; 19 | base::StringPiece GetDataResource( 20 | int resource_id, 21 | ui::ScaleFactor scale_factor) override; 22 | base::RefCountedMemory* GetDataResourceBytes( 23 | int resource_id) override; 24 | gfx::Image& GetNativeImageNamed(int resource_id) override; 25 | base::DictionaryValue GetNetLogConstants() override; 26 | blink::OriginTrialPolicy* GetOriginTrialPolicy() override; 27 | 28 | 29 | private: 30 | 31 | // DemoShellOriginTrialPolicy origin_trial_policy_; 32 | 33 | }; 34 | 35 | } 36 | 37 | #endif -------------------------------------------------------------------------------- /demo_shell/common/demo_shell_origin_trial_policy.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "demo/demo_shell/common/demo_shell_origin_trial_policy.h" 6 | 7 | #include "base/feature_list.h" 8 | #include "content/public/common/content_features.h" 9 | #include "content/public/common/origin_util.h" 10 | 11 | namespace content { 12 | 13 | namespace { 14 | 15 | // This is the public key which the content shell will use to enable origin 16 | // trial features. Trial tokens for use in layout tests can be created with the 17 | // tool in /tools/origin_trials/generate_token.py, using the private key 18 | // contained in /tools/origin_trials/eftest.key. 19 | static const uint8_t kOriginTrialPublicKey[] = { 20 | 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 21 | 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 22 | 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0, 23 | }; 24 | 25 | } // namespace 26 | 27 | DemoShellOriginTrialPolicy::DemoShellOriginTrialPolicy() 28 | : public_key_(base::StringPiece( 29 | reinterpret_cast(kOriginTrialPublicKey), 30 | arraysize(kOriginTrialPublicKey))) {} 31 | 32 | DemoShellOriginTrialPolicy::~DemoShellOriginTrialPolicy() {} 33 | 34 | bool DemoShellOriginTrialPolicy::IsOriginTrialsSupported() const { 35 | return base::FeatureList::IsEnabled(features::kOriginTrials); 36 | } 37 | 38 | base::StringPiece DemoShellOriginTrialPolicy::GetPublicKey() const { 39 | return public_key_; 40 | } 41 | 42 | bool DemoShellOriginTrialPolicy::IsOriginSecure(const GURL& url) const { 43 | return content::IsOriginSecure(url); 44 | } 45 | 46 | } // namespace content 47 | -------------------------------------------------------------------------------- /demo_shell/common/demo_shell_origin_trial_policy.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTENT_DEMO_SHELL_COMMON_DEMO_SHELL_ORIGIN_TRIAL_POLICY_H_ 2 | #define CONTENT_DEMO_SHELL_COMMON_DEMO_SHELL_ORIGIN_TRIAL_POLICY_H_ 3 | 4 | #include "third_party/blink/public/common/origin_trials/origin_trial_policy.h" 5 | #include "base/macros.h" 6 | #include "base/strings/string_piece.h" 7 | 8 | namespace content{ 9 | class DemoShellOriginTrialPolicy: public blink::OriginTrialPolicy{ 10 | public: 11 | DemoShellOriginTrialPolicy(); 12 | ~DemoShellOriginTrialPolicy() override; 13 | // blink::OriginTrialPolicy interface 14 | bool IsOriginTrialsSupported() const override; 15 | base::StringPiece GetPublicKey() const override; 16 | bool IsOriginSecure(const GURL& url) const override; 17 | 18 | private: 19 | base::StringPiece public_key_; 20 | 21 | DISALLOW_COPY_AND_ASSIGN(DemoShellOriginTrialPolicy); 22 | }; 23 | } 24 | 25 | #endif //CONTENT_DEMO_SHELL_COMMON_DEMO_SHELL_ORIGIN_TRIAL_POLICY_H_ -------------------------------------------------------------------------------- /demo_shell/common/demo_shell_switches.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "demo/demo_shell/common/demo_shell_switches.h" 6 | 7 | #include "base/command_line.h" 8 | #include "base/strings/string_split.h" 9 | 10 | namespace switches { 11 | 12 | // Makes Content Shell use the given path for its data directory. 13 | const char kContentShellDataPath[] = "data-path"; 14 | 15 | // The directory breakpad should store minidumps in. 16 | const char kCrashDumpsDir[] = "crash-dumps-dir"; 17 | 18 | // Exposes the window.internals object to JavaScript for interactive development 19 | // and debugging of web tests that rely on it. 20 | const char kExposeInternalsForTesting[] = "expose-internals-for-testing"; 21 | 22 | // Registers additional font files on Windows (for fonts outside the usual 23 | // %WINDIR%\Fonts location). Multiple files can be used by separating them 24 | // with a semicolon (;). 25 | const char kRegisterFontFiles[] = "register-font-files"; 26 | 27 | // Size for the content_shell's host window (i.e. "800x600"). 28 | const char kContentShellHostWindowSize[] = "content-shell-host-window-size"; 29 | 30 | // Hides toolbar from content_shell's host window. 31 | const char kContentShellHideToolbar[] = "content-shell-hide-toolbar"; 32 | 33 | 34 | } // namespace switches 35 | -------------------------------------------------------------------------------- /demo_shell/common/demo_shell_switches.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | // Defines all the "content_shell" command-line switches. 6 | 7 | #ifndef CONTENT_DEMO_SHELL_COMMON_SHELL_SWITCHES_H_ 8 | #define CONTENT_DEMO_SHELL_COMMON_SHELL_SWITCHES_H_ 9 | 10 | #include 11 | #include 12 | 13 | namespace switches { 14 | 15 | extern const char kContentShellDataPath[]; 16 | extern const char kCrashDumpsDir[]; 17 | extern const char kExposeInternalsForTesting[]; 18 | extern const char kRegisterFontFiles[]; 19 | extern const char kContentShellHostWindowSize[]; 20 | extern const char kContentShellHideToolbar[]; 21 | 22 | 23 | } // namespace switches 24 | 25 | #endif // CONTENT_DEMO_SHELL_COMMON_SHELL_SWITCHES_H_ 26 | -------------------------------------------------------------------------------- /demo_shell/demo_shell_resources.grd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /demo_shell/renderer/demo_shell_content_renderer_client.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "demo/demo_shell/renderer/demo_shell_content_renderer_client.h" 6 | 7 | #include 8 | 9 | #include "base/bind.h" 10 | #include "base/command_line.h" 11 | #include "base/logging.h" 12 | #include "base/macros.h" 13 | #include "base/strings/string_number_conversions.h" 14 | #include "components/cdm/renderer/external_clear_key_key_system_properties.h" 15 | #include "components/web_cache/renderer/web_cache_impl.h" 16 | #include "content/public/child/child_thread.h" 17 | #include "content/public/common/service_manager_connection.h" 18 | #include "mojo/public/cpp/bindings/pending_receiver.h" 19 | #include "mojo/public/cpp/bindings/receiver.h" 20 | #include "mojo/public/cpp/system/message_pipe.h" 21 | #include "net/base/net_errors.h" 22 | #include "ppapi/buildflags/buildflags.h" 23 | #include "services/service_manager/public/cpp/binder_registry.h" 24 | #include "third_party/blink/public/platform/web_url_error.h" 25 | #include "third_party/blink/public/web/web_testing_support.h" 26 | #include "third_party/blink/public/web/web_view.h" 27 | #include "v8/include/v8.h" 28 | 29 | #if BUILDFLAG(ENABLE_PLUGINS) 30 | #include "ppapi/shared_impl/ppapi_switches.h" // nogncheck 31 | #endif 32 | 33 | #if BUILDFLAG(ENABLE_MOJO_CDM) 34 | #include "base/feature_list.h" 35 | #include "media/base/media_switches.h" 36 | #endif 37 | 38 | namespace content { 39 | 40 | DemoShellContentRendererClient::DemoShellContentRendererClient() {} 41 | 42 | DemoShellContentRendererClient::~DemoShellContentRendererClient() { 43 | } 44 | 45 | void DemoShellContentRendererClient::RenderThreadStarted() { 46 | LOG(WARNING)<<"DemoShellContentRendererClient::RenderThreadStarted"; 47 | } 48 | 49 | void DemoShellContentRendererClient::ExposeInterfacesToBrowser(mojo::BinderMap* binders) { 50 | DVLOG(2)<<"DemoShellContentRendererClient::ExposeInterfacesToBrowser"; 51 | } 52 | 53 | void DemoShellContentRendererClient::RenderViewCreated(RenderView* render_view) { 54 | // new ShellRenderViewObserver(render_view); 55 | LOG(WARNING)<<"DemoShellContentRendererClient::RenderViewCreated"; 56 | 57 | } 58 | 59 | bool DemoShellContentRendererClient::HasErrorPage(int http_status_code) { 60 | LOG(WARNING)<<"DemoShellContentRendererClient::HasErrorPage"; 61 | return http_status_code >= 400 && http_status_code < 600; 62 | } 63 | 64 | void DemoShellContentRendererClient::PrepareErrorPage( 65 | RenderFrame* render_frame, 66 | const blink::WebURLError& error, 67 | const std::string& http_method, 68 | std::string* error_html) { 69 | LOG(WARNING)<<"DemoShellContentRendererClient::PrepareErrorPage"; 70 | if (error_html && error_html->empty()) { 71 | *error_html = 72 | "ErrorCould not load the requested " 73 | "resource.
Error code: " + 74 | base::NumberToString(error.reason()) + 75 | (error.reason() < 0 ? " (" + net::ErrorToString(error.reason()) + ")" 76 | : "") + 77 | ""; 78 | } 79 | } 80 | 81 | void DemoShellContentRendererClient::PrepareErrorPageForHttpStatusError( 82 | content::RenderFrame* render_frame, 83 | const GURL& unreachable_url, 84 | const std::string& http_method, 85 | int http_status, 86 | std::string* error_html) { 87 | LOG(WARNING)<<"DemoShellContentRendererClient::PrepareErrorPageForHttpStatusError"; 88 | if (error_html) { 89 | *error_html = 90 | "ErrorServer returned HTTP status " + 91 | base::NumberToString(http_status) + ""; 92 | } 93 | } 94 | 95 | bool DemoShellContentRendererClient::IsPluginAllowedToUseDevChannelAPIs() { 96 | LOG(WARNING)<<"DemoShellContentRendererClient::IsPluginAllowedToUseDevChannelAPIs"; 97 | return false; 98 | } 99 | 100 | void DemoShellContentRendererClient::DidInitializeWorkerContextOnWorkerThread( 101 | v8::Local context) { 102 | LOG(WARNING)<<"DemoShellContentRendererClient::DidInitializeWorkerContextOnWorkerThread"; 103 | } 104 | 105 | } // namespace content 106 | -------------------------------------------------------------------------------- /demo_shell/renderer/demo_shell_content_renderer_client.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef CONTENT_SHELL_RENDERER_SHELL_CONTENT_RENDERER_CLIENT_H_ 6 | #define CONTENT_SHELL_RENDERER_SHELL_CONTENT_RENDERER_CLIENT_H_ 7 | 8 | #include 9 | #include 10 | 11 | #include "base/compiler_specific.h" 12 | #include "build/build_config.h" 13 | #include "content/public/renderer/content_renderer_client.h" 14 | #include "media/mojo/buildflags.h" 15 | 16 | namespace web_cache { 17 | class WebCacheImpl; 18 | } 19 | 20 | namespace content { 21 | 22 | class DemoShellContentRendererClient : public ContentRendererClient { 23 | public: 24 | DemoShellContentRendererClient(); 25 | ~DemoShellContentRendererClient() override; 26 | 27 | // ContentRendererClient implementation. 28 | void RenderThreadStarted() override; 29 | void ExposeInterfacesToBrowser(mojo::BinderMap* binders) override; 30 | void RenderViewCreated(RenderView* render_view) override; 31 | bool HasErrorPage(int http_status_code) override; 32 | void PrepareErrorPage(RenderFrame* render_frame, 33 | const blink::WebURLError& error, 34 | const std::string& http_method, 35 | std::string* error_html) override; 36 | void PrepareErrorPageForHttpStatusError(content::RenderFrame* render_frame, 37 | const GURL& unreachable_url, 38 | const std::string& http_method, 39 | int http_status, 40 | std::string* error_html) override; 41 | 42 | // TODO(mkwst): These toggle based on the kEnablePepperTesting flag. Do we 43 | // need that outside of web tests? 44 | bool IsPluginAllowedToUseDevChannelAPIs() override; 45 | 46 | void DidInitializeWorkerContextOnWorkerThread( 47 | v8::Local context) override; 48 | 49 | }; 50 | 51 | } // namespace content 52 | 53 | #endif // CONTENT_SHELL_RENDERER_SHELL_CONTENT_RENDERER_CLIENT_H_ 54 | -------------------------------------------------------------------------------- /demo_shell/resource_ids: -------------------------------------------------------------------------------- 1 | { 2 | "SRCDIR": ".", 3 | # 31000之后的范围留给第三方,所以我们从31000开始 4 | "demo_shell_resources.grd": { 5 | "includes": [31000], 6 | }, 7 | 8 | } -------------------------------------------------------------------------------- /demo_shell/resources/README.txt: -------------------------------------------------------------------------------- 1 | missingImage.gif was created from Webkit data: WebCore/Resources/missingImage.tiff 2 | 3 | Licence text for missingImage.tiff from which missingImage.gif was generated: 4 | 5 | Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 1. Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | missingImage.png is the same as WebCore/Resources/missingImage.png and carries exactly the same license. 27 | -------------------------------------------------------------------------------- /demo_shell/resources/brokenCanvas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/demo_shell/resources/brokenCanvas.png -------------------------------------------------------------------------------- /demo_shell/resources/shell_devtools_discovery_page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Content shell remote debugging 4 | 6 | 7 | 49 | 50 | 51 |
Inspectable WebContents
52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /demo_shell/utility/demo_shell_content_utility_client.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "content/shell/utility/shell_content_utility_client.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "base/bind.h" 11 | #include "base/command_line.h" 12 | #include "base/files/scoped_temp_dir.h" 13 | #include "base/memory/ptr_util.h" 14 | #include "base/no_destructor.h" 15 | #include "base/process/process.h" 16 | #include "content/public/child/child_thread.h" 17 | #include "content/public/common/content_switches.h" 18 | #include "content/public/common/service_manager_connection.h" 19 | #include "content/public/common/simple_connection_filter.h" 20 | #include "content/public/test/test_service.h" 21 | #include "content/public/test/test_service.mojom.h" 22 | #include "content/public/utility/utility_thread.h" 23 | #include "content/shell/common/power_monitor_test.mojom.h" 24 | #include "content/shell/common/power_monitor_test_impl.h" 25 | #include "mojo/public/cpp/bindings/pending_receiver.h" 26 | #include "mojo/public/cpp/bindings/self_owned_receiver.h" 27 | #include "mojo/public/cpp/bindings/service_factory.h" 28 | #include "mojo/public/cpp/system/buffer.h" 29 | #include "services/service_manager/public/cpp/binder_registry.h" 30 | #include "services/test/echo/echo_service.h" 31 | 32 | namespace content { 33 | 34 | namespace { 35 | 36 | class TestUtilityServiceImpl : public mojom::TestService { 37 | public: 38 | static void Create(mojo::PendingReceiver receiver) { 39 | mojo::MakeSelfOwnedReceiver(base::WrapUnique(new TestUtilityServiceImpl), 40 | std::move(receiver)); 41 | } 42 | 43 | // mojom::TestService implementation: 44 | void DoSomething(DoSomethingCallback callback) override { 45 | std::move(callback).Run(); 46 | } 47 | 48 | void DoTerminateProcess(DoTerminateProcessCallback callback) override { 49 | base::Process::TerminateCurrentProcessImmediately(0); 50 | } 51 | 52 | void DoCrashImmediately(DoCrashImmediatelyCallback callback) override { 53 | IMMEDIATE_CRASH(); 54 | } 55 | 56 | void CreateFolder(CreateFolderCallback callback) override { 57 | // Note: This is used to check if the sandbox is disabled or not since 58 | // creating a folder is forbidden when it is enabled. 59 | std::move(callback).Run(base::ScopedTempDir().CreateUniqueTempDir()); 60 | } 61 | 62 | void GetRequestorName(GetRequestorNameCallback callback) override { 63 | NOTREACHED(); 64 | } 65 | 66 | void CreateSharedBuffer(const std::string& message, 67 | CreateSharedBufferCallback callback) override { 68 | mojo::ScopedSharedBufferHandle buffer = 69 | mojo::SharedBufferHandle::Create(message.size()); 70 | CHECK(buffer.is_valid()); 71 | 72 | mojo::ScopedSharedBufferMapping mapping = buffer->Map(message.size()); 73 | CHECK(mapping); 74 | std::copy(message.begin(), message.end(), 75 | reinterpret_cast(mapping.get())); 76 | 77 | std::move(callback).Run(std::move(buffer)); 78 | } 79 | 80 | private: 81 | explicit TestUtilityServiceImpl() {} 82 | 83 | DISALLOW_COPY_AND_ASSIGN(TestUtilityServiceImpl); 84 | }; 85 | 86 | auto RunEchoService(mojo::PendingReceiver receiver) { 87 | return std::make_unique(std::move(receiver)); 88 | } 89 | 90 | } // namespace 91 | 92 | ShellContentUtilityClient::ShellContentUtilityClient(bool is_browsertest) { 93 | if (is_browsertest && 94 | base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 95 | switches::kProcessType) == switches::kUtilityProcess) { 96 | network_service_test_helper_ = std::make_unique(); 97 | audio_service_test_helper_ = std::make_unique(); 98 | } 99 | } 100 | 101 | ShellContentUtilityClient::~ShellContentUtilityClient() { 102 | } 103 | 104 | void ShellContentUtilityClient::UtilityThreadStarted() { 105 | auto registry = std::make_unique(); 106 | content::ChildThread::Get() 107 | ->GetServiceManagerConnection() 108 | ->AddConnectionFilter( 109 | std::make_unique(std::move(registry))); 110 | } 111 | 112 | bool ShellContentUtilityClient::HandleServiceRequest( 113 | const std::string& service_name, 114 | service_manager::mojom::ServiceRequest request) { 115 | std::unique_ptr service; 116 | if (service_name == kTestServiceUrl) { 117 | service = std::make_unique(std::move(request)); 118 | } 119 | 120 | if (service) { 121 | service_manager::Service::RunAsyncUntilTermination( 122 | std::move(service), base::BindOnce([] { 123 | content::UtilityThread::Get()->ReleaseProcess(); 124 | })); 125 | return true; 126 | } 127 | 128 | return false; 129 | } 130 | 131 | mojo::ServiceFactory* ShellContentUtilityClient::GetIOThreadServiceFactory() { 132 | static base::NoDestructor factory{ 133 | RunEchoService, 134 | }; 135 | return factory.get(); 136 | } 137 | 138 | void ShellContentUtilityClient::RegisterNetworkBinders( 139 | service_manager::BinderRegistry* registry) { 140 | network_service_test_helper_->RegisterNetworkBinders(registry); 141 | } 142 | 143 | void ShellContentUtilityClient::RegisterAudioBinders( 144 | service_manager::BinderMap* binders) { 145 | audio_service_test_helper_->RegisterAudioBinders(binders); 146 | } 147 | 148 | } // namespace content 149 | -------------------------------------------------------------------------------- /demo_shell/utility/demo_shell_content_utility_client.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef CONTENT_DEMO_SHELL_UTILITY_SHELL_CONTENT_UTILITY_CLIENT_H_ 6 | #define CONTENT_DEMO_SHELL_UTILITY_SHELL_CONTENT_UTILITY_CLIENT_H_ 7 | 8 | #include "base/macros.h" 9 | #include "content/public/test/audio_service_test_helper.h" 10 | #include "content/public/test/network_service_test_helper.h" 11 | #include "content/public/utility/content_utility_client.h" 12 | 13 | namespace content { 14 | 15 | class DemoShellContentUtilityClient : public ContentUtilityClient { 16 | public: 17 | explicit DemoShellContentUtilityClient(); 18 | ~DemoShellContentUtilityClient() override; 19 | 20 | // ContentUtilityClient: 21 | 22 | private: 23 | 24 | 25 | DISALLOW_COPY_AND_ASSIGN(DemoShellContentUtilityClient); 26 | }; 27 | 28 | } // namespace content 29 | 30 | #endif // CONTENT_SHELL_UTILITY_SHELL_CONTENT_UTILITY_CLIENT_H_ 31 | -------------------------------------------------------------------------------- /demo_shell/version.h.in: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_WEBVIEW_VERSION_H_ 2 | #define DEMO_WEBVIEW_VERSION_H_ 3 | 4 | #define DEMO_WEBVIEW_VERSION "@VERSION_FULL@" 5 | 6 | #endif // DEMO_WEBVIEW_VERSION_H_ -------------------------------------------------------------------------------- /demo_skia/BUILD.gn: -------------------------------------------------------------------------------- 1 | 2 | import("//build/config/ui.gni") 3 | 4 | executable("demo_skia") { 5 | testonly = true 6 | 7 | sources = [ 8 | "demo_skia.cc", 9 | "skia_canvas.cc", 10 | "skia_canvas.h", 11 | "skia_canvas_gl.cc", 12 | "skia_canvas_gl.h", 13 | "skia_canvas_software.cc", 14 | "skia_canvas_software.h", 15 | ] 16 | 17 | deps = [ 18 | "//base", 19 | "//base:i18n", 20 | "//gpu", 21 | "//gpu:gles2", 22 | "//gpu:raster", 23 | "//gpu/command_buffer/client", 24 | "//gpu/command_buffer/client:gles2_cmd_helper", 25 | "//gpu/command_buffer/service", 26 | "//gpu/command_buffer/service:gles2", 27 | "//ui/base", 28 | "//ui/gl", 29 | "//ui/gl/init", 30 | "//ui/events", 31 | "//ui/events/platform", 32 | "//ui/platform_window", 33 | # 直接依赖它会导致和chromium中的变量定义冲突 34 | #"//third_party/skia", 35 | "//skia", 36 | ] 37 | 38 | if (use_x11) { 39 | deps += [ 40 | "//ui/events/platform/x11", 41 | "//ui/platform_window/x11", 42 | ] 43 | configs += [ "//build/config/linux:x11" ] 44 | } 45 | 46 | libs = ["EGL","GLESv2"] 47 | } 48 | -------------------------------------------------------------------------------- /demo_skia/README.md: -------------------------------------------------------------------------------- 1 | # demo_skia 2 | 3 | demo_skia 用于演示在 Linux 系统上使用 Skia 进行软件/硬件渲染。 4 | 5 | ```c++ 6 | ./out/Default/demo_skia // 使用 GLES2 进行渲染。 7 | ./out/Default/demo_skia --software // 使用 Software 进行渲染。 8 | ``` 9 | -------------------------------------------------------------------------------- /demo_skia/skia_canvas.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_DEMO_SKIA_SKIA_CANVAS_H 2 | #define DEMO_DEMO_SKIA_SKIA_CANVAS_H 3 | 4 | #include "base/threading/thread.h" 5 | #include "base/sequenced_task_runner.h" 6 | 7 | #include "ui/gfx/native_widget_types.h" 8 | 9 | #include "third_party/skia/include/core/SkBitmap.h" 10 | #include "third_party/skia/include/core/SkCanvas.h" 11 | #include "third_party/skia/include/core/SkPath.h" 12 | #include "third_party/skia/include/core/SkImageInfo.h" 13 | #include "third_party/skia/include/core/SkSurface.h" 14 | 15 | #include "base/timer/timer.h" 16 | 17 | namespace demo_jni { 18 | 19 | class SkiaCanvas { 20 | public: 21 | void OnTouch(int action, float x, float y); 22 | virtual ~SkiaCanvas() {} 23 | virtual void Resize(int width, int height) {} 24 | 25 | protected: 26 | SkiaCanvas(gfx::AcceleratedWidget widget,int width,int height); 27 | virtual void InitializeOnRenderThread(); 28 | virtual SkCanvas* BeginPaint() = 0; 29 | virtual void OnPaint(SkCanvas* canvas) {} 30 | virtual void SwapBuffer() = 0; 31 | void SetNeedsRedraw(bool need_redraw); 32 | void ShowInfo(std::string info); 33 | 34 | gfx::AcceleratedWidget nativeWindow_; 35 | int width_; 36 | int height_; 37 | base::Thread render_thread_; 38 | scoped_refptr render_task_runner_; 39 | 40 | sk_sp skSurface_ = nullptr; 41 | SkPaint pathPaint_; 42 | SkPaint circlePaint_; 43 | SkPath skPath_; 44 | SkScalar strokeWidth_ = 5.f; 45 | SkColor background_ = SK_ColorBLACK; 46 | std::string tag_; 47 | bool need_redraw_ = false; 48 | bool is_drawing_ = false; 49 | base::TimeDelta total_frame_time_; 50 | base::TimeTicks last_frame_time_; 51 | unsigned int frame_count_ = 0; 52 | base::TimeDelta total_paint_time_; 53 | base::TimeDelta total_swap_time_; 54 | 55 | unsigned int touch_count_ = 0; 56 | base::TimeTicks touch_start_time_; 57 | base::TimeDelta total_touch_time_; 58 | 59 | private: 60 | void OnTouchOnRenderThread(int action, float x, float y); 61 | void OnRenderOnRenderThread(); 62 | void ShowFrameRateOnRenderThread(); 63 | base::RepeatingTimer timer_; 64 | base::RepeatingClosure render_closure_; 65 | base::WeakPtrFactory weak_factory_{this}; 66 | }; 67 | 68 | } // namespace demo_jni 69 | 70 | #endif // DEMO_DEMO_SKIA_SKIA_CANVAS_H 71 | -------------------------------------------------------------------------------- /demo_skia/skia_canvas_gl.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_DEMO_SKIA_SKIA_CANVAS_GL_H 2 | #define DEMO_DEMO_SKIA_SKIA_CANVAS_GL_H 3 | 4 | #include 5 | #include 6 | #ifndef GL_GLEXT_PROTOTYPES 7 | #define GL_GLEXT_PROTOTYPES 8 | #endif 9 | // Chromium 在 gpu/GLES2/gl2chromium_autogen.h 中重定义了所有的 gles2 的方法 10 | // 到 GLES2xxx,这样来对接 command buffer,我们不需要使用 command buffer,因此 11 | // 使用绝对路径绕过这个逻辑 12 | //#include 13 | #include 14 | 15 | #include "demo/demo_skia/skia_canvas.h" 16 | 17 | #include "third_party/skia/include/gpu/GrContext.h" 18 | #include "third_party/skia/include/gpu/GrContextOptions.h" 19 | #include "third_party/skia/include/gpu/gl/GrGLInterface.h" 20 | #include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h" 21 | 22 | namespace demo_jni { 23 | 24 | class SkiaCanvasGL : public SkiaCanvas { 25 | public: 26 | SkiaCanvasGL(gfx::AcceleratedWidget widget,int width,int height); 27 | void Resize(int width, int height) override; 28 | 29 | ~SkiaCanvasGL() override; 30 | 31 | private: 32 | void InitializeOnRenderThread() override; 33 | SkCanvas* BeginPaint() override; 34 | void OnPaint(SkCanvas* canvas) override; 35 | void SwapBuffer() override; 36 | 37 | EGLDisplay display_; 38 | EGLContext context_; 39 | EGLSurface surface_; 40 | EGLint stencilBits_; 41 | EGLint sampleCount_; 42 | GLenum color_format_; 43 | sk_sp grGLInterface_; 44 | sk_sp grContext_; 45 | bool use_ddl_ = false; 46 | std::unique_ptr recorder_; 47 | }; 48 | 49 | } // namespace demo_jni 50 | 51 | #endif // DEMO_DEMO_SKIA_SKIA_CANVAS_GL_H 52 | -------------------------------------------------------------------------------- /demo_skia/skia_canvas_software.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "demo/demo_skia/skia_canvas_software.h" 3 | 4 | #include "base/bind.h" 5 | #include "base/lazy_instance.h" 6 | #include "base/trace_event/trace_event.h" 7 | 8 | namespace demo_jni { 9 | 10 | SkiaCanvasSoftware::SkiaCanvasSoftware(gfx::AcceleratedWidget widget,int width,int height) 11 | : SkiaCanvas(widget, width, height) { 12 | background_ = 0x8800DE96; 13 | tag_ = "SkiaCanvasSoftware"; 14 | } 15 | 16 | void SkiaCanvasSoftware::InitializeOnRenderThread() { 17 | TRACE_EVENT0("shell", "SkiaCanvasSoftware::InitializeOnRenderThread"); 18 | x11_presenter_ = std::make_unique( 19 | nativeWindow_, render_task_runner_.get(), nullptr); 20 | 21 | // 当 format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4 22 | // 时,一个像素占2个字节,所以x2 23 | // memset(buffer.bits, 0xAA, buffer.stride * buffer.height * 2); 24 | auto canvas = BeginPaint(); 25 | canvas->clear(background_); 26 | //canvas->drawCircle(20, 20, 20, circlePaint_); 27 | OnPaint(canvas); 28 | SwapBuffer(); 29 | SkiaCanvas::InitializeOnRenderThread(); 30 | } 31 | 32 | void SkiaCanvasSoftware::Resize(int width, int height) { 33 | width_ = width; 34 | height_ = height; 35 | } 36 | 37 | SkCanvas* SkiaCanvasSoftware::BeginPaint() { 38 | x11_presenter_->Resize(gfx::Size(width_, height_)); 39 | return x11_presenter_->GetSkCanvas(); 40 | } 41 | 42 | void SkiaCanvasSoftware::OnPaint(SkCanvas* canvas) { 43 | x11_presenter_->EndPaint(gfx::Rect(width_,height_)); 44 | } 45 | 46 | void SkiaCanvasSoftware::SwapBuffer() { 47 | x11_presenter_->OnSwapBuffers(base::BindOnce([](const gfx::Size&){})); 48 | } 49 | 50 | } // namespace demo_jni 51 | -------------------------------------------------------------------------------- /demo_skia/skia_canvas_software.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_DEMO_SKIA_SKIA_CANVAS_SOFTWARE_H 2 | #define DEMO_DEMO_SKIA_SKIA_CANVAS_SOFTWARE_H 3 | 4 | #include "demo/demo_skia/skia_canvas.h" 5 | 6 | #include "ui/base/x/x11_software_bitmap_presenter.h" 7 | 8 | namespace demo_jni { 9 | 10 | class SkiaCanvasSoftware : public SkiaCanvas { 11 | public: 12 | SkiaCanvasSoftware(gfx::AcceleratedWidget widget,int width,int height); 13 | void InitializeOnRenderThread() override; 14 | void Resize(int width, int height) override; 15 | void OnPaint(SkCanvas* canvas) override; 16 | 17 | private: 18 | SkCanvas* BeginPaint() override; 19 | void SwapBuffer() override; 20 | 21 | std::unique_ptr x11_presenter_; 22 | }; 23 | 24 | } // namespace demo_jni 25 | 26 | #endif // DEMO_DEMO_SKIA_SKIA_CANVAS_SOFTWARE_H 27 | -------------------------------------------------------------------------------- /demo_tasks.cc: -------------------------------------------------------------------------------- 1 | #include "base/logging.h" 2 | #include "base/message_loop/message_loop.h" 3 | #include "base/message_loop/message_loop_current.h" 4 | #include "base/task/post_task.h" 5 | #include "base/task/single_thread_task_executor.h" 6 | #include "base/task/thread_pool/thread_pool_impl.h" 7 | #include "base/task/thread_pool/thread_pool_instance.h" 8 | #include "base/threading/thread_task_runner_handle.h" 9 | #include "base/timer/timer.h" 10 | 11 | void Hello() { 12 | LOG(INFO) << "hello,demo!"; 13 | // CHECK(false); 14 | } 15 | #ifdef DEMO_MESSAGE_LOOP 16 | int main(int argc, char** argv) { 17 | // 创建消息循环 18 | base::MessageLoop message_loop; 19 | // 也可以使用下面的方法。它们的区别仅在于MessageLoop对外暴露了更多的内部接口。 20 | // 在当前线程创建一个可执行task的环境,同样需要使用RunLoop启动 21 | // base::SingleThreadTaskExecutor main_task_executer; 22 | 23 | base::RunLoop run_loop; 24 | 25 | // 使用message_loop对象直接创建任务 26 | message_loop.task_runner()->PostTask(FROM_HERE, base::BindOnce(&Hello)); 27 | // 获取当前线程的task runner 28 | base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, 29 | base::BindOnce(&Hello)); 30 | 31 | // 启动消息循环,即使没有任务也会阻塞程序运行。当前进程中只有一个线程。 32 | run_loop.Run(); 33 | 34 | return 0; 35 | } 36 | #else // DEMO_TASK 37 | int main(int argc, char** argv) { 38 | base::Thread thread("timer"); 39 | thread.Start(); 40 | base::RepeatingTimer timer_; 41 | timer_.SetTaskRunner(thread.task_runner()); 42 | 43 | // 初始化线程池,会创建新的线程,在新的线程中会创建消息循环MessageLoop 44 | base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Demo"); 45 | 46 | // 通过以下方法创建任务,默认在线程池中运行 47 | base::PostTask(FROM_HERE, base::BindOnce(&Hello)); 48 | // 或者通过创建新的TaskRunner来创建任务,TaskRunner可以控制任务执行的顺序以及是否在同一个线程中运行 49 | scoped_refptr task_runner_ = base::CreateTaskRunner({ 50 | base::ThreadPool(), 51 | base::TaskPriority::USER_VISIBLE, 52 | }); 53 | task_runner_->PostTask(FROM_HERE, base::BindOnce(&Hello)); 54 | 55 | // 由于线程池默认不会阻塞程序运行,因此这里为了看到结果使用getchar()阻塞主线程。当前进程中共有4个线程,1个主线程,1个线程池Service线程,2个Worker线程。 56 | getchar(); 57 | 58 | return 0; 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /demo_tracing/BUILD.gn: -------------------------------------------------------------------------------- 1 | 2 | import("//build/config/ui.gni") 3 | 4 | group("demo_tracing") { 5 | testonly = true 6 | 7 | deps = [ 8 | ":demo_tracing_console", 9 | ":demo_tracing_perfetto", 10 | ":demo_tracing_perfetto_content", 11 | ] 12 | } 13 | 14 | executable("demo_tracing_console") { 15 | sources = [ 16 | "demo_tracing_console.cc", 17 | ] 18 | 19 | deps = [ 20 | "//base", 21 | "//components/tracing:startup_tracing", 22 | ] 23 | } 24 | 25 | executable("demo_tracing_perfetto_content") { 26 | testonly = true 27 | 28 | sources = [ 29 | "demo_tracing_perfetto_content.cc" 30 | ] 31 | 32 | deps = [ 33 | "//base", 34 | "//components/tracing:startup_tracing", 35 | "//services/tracing:lib", 36 | "//services/tracing/public/cpp", 37 | "//content/test:test_support", 38 | ] 39 | } 40 | 41 | executable("demo_tracing_perfetto") { 42 | testonly = true 43 | 44 | sources = [ 45 | "demo_tracing_perfetto.cc" 46 | ] 47 | 48 | deps = [ 49 | "//base", 50 | "//components/tracing:startup_tracing", 51 | "//services/tracing:lib", 52 | "//services/tracing/public/cpp", 53 | "//mojo/public", 54 | "//mojo/core/embedder", 55 | "//services/tracing/public/cpp:traced_process", 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /demo_tracing/README.md: -------------------------------------------------------------------------------- 1 | 2 | # demo_tracing 3 | 4 | `vsync_auditor.html` 文件用于处理 `chrome://tracing` 页面上的 `Highlight VSync` 显示: 5 | 6 | ```c++ 7 | // third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor.html 8 | 9 | const VSYNC_SLICE_PRECISIONS = { 10 | // Android. 11 | 'RenderWidgetHostViewAndroid::OnVSync': 5, 12 | // Android. Very precise. Requires "gfx" systrace category to be enabled. 13 | 'VSYNC': 10, 14 | // Linux. Very precise. Requires "gpu" tracing category to be enabled. 15 | 'vblank': 10, 16 | // Mac. Derived from a Mac callback (CVDisplayLinkSetOutputCallback). 17 | 'DisplayLinkMac::GetVSyncParameters': 5 18 | }; 19 | 20 | const BEGIN_FRAME_SLICE_PRECISION = { 21 | 'DisplayScheduler::BeginFrame': 10 22 | }; 23 | ``` 24 | 25 | 当使用以上这些字符串作为 trace name 的时候,`chrome://tracing` 可以显示帧率信息,比如使用以下任意一种 trace 就可以让自己的程序支持在`chrome://tracing`中显示 vsync。 26 | 27 | ```c++ 28 | TRACE_EVENT0("shell", "VSYNC"); 29 | TRACE_EVENT0("shell", "vblank"); 30 | // 这个是 chromium 内部使用的 31 | TRACE_EVENT2("viz", "DisplayScheduler::BeginFrame", "args", args,"now", now); 32 | ``` 33 | -------------------------------------------------------------------------------- /demo_views/BUILD.gn: -------------------------------------------------------------------------------- 1 | import("//build/config/ui.gni") 2 | import("//tools/grit/repack.gni") 3 | 4 | executable("demo_views") { 5 | testonly=true 6 | sources = [ 7 | "demo_views.cc", 8 | ] 9 | 10 | deps = [ 11 | ":pak", 12 | "//base:i18n", 13 | "//base", 14 | "//build/win:default_exe_manifest", 15 | "//components/viz/host", 16 | "//components/viz/service", 17 | "//mojo/core/embedder", 18 | "//skia", 19 | "//third_party/icu", 20 | "//ui/aura", 21 | "//ui/base", 22 | "//ui/base/ime/init", 23 | "//ui/compositor:test_support", 24 | "//ui/compositor", 25 | "//ui/display", 26 | "//ui/events", 27 | "//ui/gfx", 28 | "//ui/gfx/geometry", 29 | "//ui/gl", 30 | "//ui/gl/init", 31 | "//ui/views:test_support", 32 | "//ui/views", 33 | ] 34 | 35 | if (use_x11) { 36 | deps += [ "//ui/gfx/x" ] 37 | } 38 | } 39 | 40 | repack("pak") { 41 | testonly = true 42 | sources = [ 43 | "$root_gen_dir/ui/resources/ui_resources_100_percent.pak", 44 | "$root_gen_dir/ui/resources/webui_resources.pak", 45 | "$root_gen_dir/ui/strings/app_locale_settings_en-US.pak", 46 | "$root_gen_dir/ui/strings/ui_strings_en-US.pak", 47 | ] 48 | 49 | deps = [ 50 | "//ui/resources", 51 | "//ui/strings", 52 | ] 53 | 54 | if (toolkit_views) { 55 | deps += [ "//ui/views/resources" ] 56 | sources += 57 | [ "$root_gen_dir/ui/views/resources/views_resources_100_percent.pak" ] 58 | } 59 | output = "$root_out_dir/demo_views.pak" 60 | } 61 | 62 | -------------------------------------------------------------------------------- /demo_views/README.md: -------------------------------------------------------------------------------- 1 | # demo_views 2 | 3 | demo_views 使用 `//ui/views` 来构建程序界面。 4 | 5 | ## `//ui/views` 6 | 7 | 主要用于桌面端的 UI 开发,比如 Windows/Linux 上的浏览器工具栏,地址栏等。它依赖 cc,aura 和 viz 等底层框架。 8 | 9 | TODO: 完善文档 10 | 11 | Views 在 OnPaint 中将自己所要呈现的内容绘制到 Canvas 中,这个 Canvas 将绘制操作记录到 PaintOpBuffer 中(并不立即进行真实的绘制)。 12 | 13 | 在以下文件中可以查看哪些绘制操作可以被记录,以及如何被记录。 14 | cc/paint/paint_op_buffer.h 15 | -------------------------------------------------------------------------------- /demo_viz/BUILD.gn: -------------------------------------------------------------------------------- 1 | 2 | import("//build/config/ui.gni") 3 | 4 | template("viz") { 5 | executable(target_name){ 6 | testonly = true 7 | forward_variables_from(invoker, "*") 8 | 9 | deps = [ 10 | "//base", 11 | "//base:i18n", 12 | "//build/win:default_exe_manifest", 13 | "//components/viz/host", 14 | "//components/viz/client", 15 | "//components/viz/service", 16 | "//components/viz/service/main", 17 | "//mojo/core/embedder", 18 | "//skia", 19 | "//ui/events", 20 | "//ui/events/platform", 21 | "//ui/platform_window", 22 | "//gpu", 23 | "//gpu/ipc/host", 24 | "//components/discardable_memory/service", 25 | "//components/discardable_memory/client", 26 | "//services/viz/public/cpp/gpu", 27 | ] 28 | 29 | if (use_x11) { 30 | deps += [ 31 | "//ui/events/platform/x11", 32 | "//ui/platform_window/x11", 33 | ] 34 | configs += [ "//build/config/linux:x11" ] 35 | } 36 | } 37 | } 38 | 39 | group("demo_viz") { 40 | testonly = true 41 | deps = [ 42 | ":demo_viz_gui", 43 | ":demo_viz_gui_gpu", 44 | ":demo_viz_offscreen", 45 | ":demo_viz_layer", 46 | ":demo_viz_layer_offscreen", 47 | ] 48 | } 49 | 50 | viz("demo_viz_gui") { 51 | sources = [ 52 | "demo_viz_gui.cc" 53 | ] 54 | } 55 | 56 | viz("demo_viz_gui_gpu") { 57 | sources = [ 58 | "demo_viz_gui_gpu.cc" 59 | ] 60 | } 61 | 62 | viz("demo_viz_offscreen") { 63 | sources = [ 64 | "demo_viz_offscreen.cc" 65 | ] 66 | } 67 | 68 | viz("demo_viz_layer") { 69 | sources = [ 70 | "demo_viz_layer.cc" 71 | ] 72 | } 73 | 74 | viz("demo_viz_layer_offscreen") { 75 | sources = [ 76 | "demo_viz_layer_offscreen.cc", 77 | "demo_viz_layer_offscreen_client.cc" 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /demo_viz/README.md: -------------------------------------------------------------------------------- 1 | # demo_viz 2 | 3 | ## demo_viz_offscreen 4 | 5 | demo_viz_offscreen 演示了直接使用 viz 内部的接口来进行离屏渲染。 6 | 7 | ## demo_viz_gui 8 | 9 | demo_viz_gui 演示了使用 viz 提供的 mojo 接口进行 GUI 软件渲染。 10 | 这些 mojo 接口内部包装了 demo_viz_offscreen 所演示的技术。 11 | 该 demo 还增加了 client raster 以及多 FrameSink 的演示。 12 | 13 | ## demo_viz_gui_gpu 14 | 15 | demo_viz_gui_gpu 在 demo_viz_gui 的基础上添加了对硬件渲染的支持。 16 | 重点在于如何初始化硬件渲染环境以及如何使用GPU资源,项目中需要注意资源的释放。 17 | 18 | TODO: 解决 client 端 raster 的偏色问题。 19 | 20 | ## demo_viz_layer 21 | 22 | demo_viz_layer 添加了用户交互控制,重点在于如何控制 UI 的局部刷新及 UI 没有改变的时候的不刷新。 23 | 同时该 demo 支持使用命令行切换渲染模式以及将渲染结果保存到文件。 24 | 25 | ## demo_viz_layer_offscreen 26 | 27 | demo_viz_layer 演示使用 CopyOutput/SkiaOutputDeviceOffscreen 接口来实现 viz 离屏渲染,然后再将离屏画面渲染到窗口上。 28 | 注意该demo需要先打 patch: patches/0001-*.path 29 | 30 | ## viz 调试技巧 31 | 32 | tracing categories: 33 | 34 | `viz,gpu,ipc,mojom,skia,disabled-by-default-toplevel.flow` 获取详细的 viz 以及 gpu 执行情况。 35 | `disabled-by-default-gpu.service` 获取 commandbuffer decoder的执行情况。 36 | 37 | 命令行参数: 38 | 39 | `--enable-gpu-service-tracing` 启动 gpu service tracing,每一个 GL 调用都会被记录到 Trace 中。 40 | `--use_virtualized_gl_contexts=0` 禁用 virtual GL Context,降低追踪的复杂度。 41 | -------------------------------------------------------------------------------- /demo_viz/demo_viz_layer_offscreen_client.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_DEMO_VIZ_DEMO_VIZ_LAYER_OFFSCREEN_CLIENT_H 2 | #define DEMO_DEMO_VIZ_DEMO_VIZ_LAYER_OFFSCREEN_CLIENT_H 3 | 4 | #include "gpu/command_buffer/service/shared_context_state.h" 5 | #include "gpu/config/gpu_preferences.h" 6 | #include "ui/gfx/geometry/size.h" 7 | #include "ui/gfx/native_widget_types.h" 8 | #include "ui/gl/gl_share_group.h" 9 | #include "components/viz/service/gl/gpu_service_impl.h" 10 | 11 | void InitHostMain(gfx::AcceleratedWidget widget, 12 | gfx::Size size, 13 | viz::GpuServiceImpl* gpu_service); 14 | 15 | void Redraw(); 16 | 17 | #endif // DEMO_DEMO_VIZ_DEMO_VIZ_LAYER_OFFSCREEN_CLIENT_H -------------------------------------------------------------------------------- /demo_x11/BUILD.gn: -------------------------------------------------------------------------------- 1 | 2 | import("//build/config/ui.gni") 3 | 4 | executable("demo_x11") { 5 | testonly = true 6 | 7 | sources = [ 8 | "demo_x11.cc", 9 | ] 10 | 11 | deps = [ 12 | "//base", 13 | "//base:i18n", 14 | "//gpu", 15 | "//gpu:gles2", 16 | "//gpu:raster", 17 | "//gpu/command_buffer/client", 18 | "//gpu/command_buffer/client:gles2_cmd_helper", 19 | "//gpu/command_buffer/service", 20 | "//gpu/command_buffer/service:gles2", 21 | "//ui/base", 22 | "//ui/gl", 23 | "//ui/gl/init", 24 | "//ui/events", 25 | "//ui/events/platform", 26 | "//ui/platform_window", 27 | # 直接依赖它会导致和chromium中的变量定义冲突 28 | #"//third_party/skia", 29 | "//skia", 30 | ":demo_x11_glx", 31 | ":demo_x11_egl", 32 | ] 33 | 34 | if (use_x11) { 35 | deps += [ 36 | "//ui/events/platform/x11", 37 | "//ui/platform_window/x11", 38 | ] 39 | configs += [ "//build/config/linux:x11" ] 40 | } 41 | 42 | libs = ["EGL","GLESv2"] 43 | } 44 | 45 | executable("demo_x11_glx") { 46 | testonly = true 47 | 48 | sources = [ 49 | "demo_x11_glx.cc", 50 | ] 51 | 52 | deps = [ 53 | "//base", 54 | "//base:i18n", 55 | "//gpu", 56 | "//gpu:gles2", 57 | "//gpu:raster", 58 | "//gpu/command_buffer/client", 59 | "//gpu/command_buffer/client:gles2_cmd_helper", 60 | "//gpu/command_buffer/service", 61 | "//gpu/command_buffer/service:gles2", 62 | "//ui/base", 63 | "//ui/gl", 64 | "//ui/gl/init", 65 | "//ui/events", 66 | "//ui/events/platform", 67 | "//ui/platform_window", 68 | # 直接依赖它会导致和chromium中的变量定义冲突 69 | #"//third_party/skia", 70 | "//skia", 71 | ] 72 | 73 | configs += [ "//build/config/linux:x11" ] 74 | 75 | libs = ["EGL","GLESv2","X11","GL"] 76 | } 77 | 78 | 79 | executable("demo_x11_egl") { 80 | testonly = true 81 | 82 | sources = [ 83 | "demo_x11_egl.cc", 84 | ] 85 | 86 | deps = [ 87 | "//base", 88 | "//base:i18n", 89 | "//gpu", 90 | "//gpu:gles2", 91 | "//gpu:raster", 92 | "//gpu/command_buffer/client", 93 | "//gpu/command_buffer/client:gles2_cmd_helper", 94 | "//gpu/command_buffer/service", 95 | "//gpu/command_buffer/service:gles2", 96 | "//ui/base", 97 | "//ui/gl", 98 | "//ui/gl/init", 99 | "//ui/events", 100 | "//ui/events/platform", 101 | "//ui/platform_window", 102 | # 直接依赖它会导致和chromium中的变量定义冲突 103 | #"//third_party/skia", 104 | "//skia", 105 | ] 106 | 107 | configs += [ "//build/config/linux:x11" ] 108 | 109 | libs = ["EGL","GLESv2","X11","GL"] 110 | } 111 | -------------------------------------------------------------------------------- /demo_x11/README.md: -------------------------------------------------------------------------------- 1 | # demo_x11 2 | 3 | 这个目录包含以下几个demo: 4 | 5 | - demo_x11: 演示在 Chromium 中使用 X11 创建透明窗口; 6 | - demo_x11_glx: 演示在透明窗口中使用 glx; 7 | - demo_x11_egl: 演示在透明窗口中使用 egl; 8 | -------------------------------------------------------------------------------- /demo_x11/demo_x11.cc: -------------------------------------------------------------------------------- 1 | #include "base/at_exit.h" 2 | #include "base/callback.h" 3 | #include "base/command_line.h" 4 | #include "base/files/file_path.h" 5 | #include "base/i18n/icu_util.h" 6 | #include "base/logging.h" 7 | #include "base/macros.h" 8 | #include "base/memory/ptr_util.h" 9 | #include "base/message_loop/message_loop.h" 10 | #include "base/message_loop/message_pump_type.h" 11 | #include "base/path_service.h" 12 | #include "base/power_monitor/power_monitor.h" 13 | #include "base/power_monitor/power_monitor_device_source.h" 14 | #include "base/run_loop.h" 15 | #include "base/task/single_thread_task_executor.h" 16 | #include "base/task/thread_pool/thread_pool_instance.h" 17 | #include "base/test/task_environment.h" 18 | #include "base/test/test_discardable_memory_allocator.h" 19 | #include "base/test/test_timeouts.h" 20 | #include "base/threading/thread.h" 21 | #include "build/build_config.h" 22 | #include "build/buildflag.h" 23 | #include "ui/base/hit_test.h" 24 | #include "ui/base/ime/init/input_method_initializer.h" 25 | #include "ui/base/material_design/material_design_controller.h" 26 | #include "ui/base/resource/resource_bundle.h" 27 | #include "ui/base/ui_base_paths.h" 28 | #include "ui/base/x/x11_util.h" 29 | #include "ui/display/screen.h" 30 | #include "ui/events/event.h" 31 | #include "ui/events/event_constants.h" 32 | #include "ui/events/platform/platform_event_source.h" 33 | 34 | #if defined(USE_AURA) 35 | #include "ui/aura/env.h" 36 | #include "ui/wm/core/wm_state.h" 37 | #endif 38 | 39 | #if defined(USE_X11) 40 | #include "ui/gfx/x/x11_connection.h" // nogncheck 41 | #include "ui/platform_window/x11/x11_window.h" // nogncheck 42 | #include "ui/base/x/x11_util_internal.h" 43 | #include "ui/gfx/x/x11_atom_cache.h" 44 | #endif 45 | 46 | 47 | int main(int argc, char** argv) { 48 | // 类似C++的 atexit() 方法,用于管理程序的销毁逻辑,base::Singleton类依赖它 49 | base::AtExitManager at_exit; 50 | // 初始化CommandLine 51 | base::CommandLine::Init(argc, argv); 52 | // 设置日志格式 53 | logging::SetLogItems(true, true, true, false); 54 | // 启动 Trace 55 | auto trace_config = 56 | base::trace_event::TraceConfig("startup" /*, "trace-to-console"*/); 57 | base::trace_event::TraceLog::GetInstance()->SetEnabled( 58 | trace_config, base::trace_event::TraceLog::RECORDING_MODE); 59 | // 创建主消息循环,等价于 MessagLoop 60 | base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI); 61 | // 初始化线程池,会创建新的线程,在新的线程中会创建新消息循环MessageLoop 62 | base::ThreadPoolInstance::CreateAndStartWithDefaultParams("DemoX11"); 63 | 64 | // 在Linux上,x11和aura都是默认开启的 65 | #if defined(USE_X11) 66 | // This demo uses InProcessContextFactory which uses X on a separate Gpu 67 | // thread. 68 | gfx::InitializeThreadedX11(); 69 | 70 | // 设置X11的异常处理回调,如果不设置在很多设备上会频繁出现崩溃。 71 | // 比如 ui::XWindow::Close() 和~SGIVideoSyncProviderThreadShim 的析构中 72 | // 都调用了 XDestroyWindow() ,并且是在不同的线程中调用的,当这两个窗口有 73 | // 父子关系的时候,如果先调用了父窗口的销毁再调用子窗口的销毁则会导致BadWindow 74 | // 错误,默认的Xlib异常处理会打印错误日志然后强制结束程序。 75 | // 这些错误大多是并发导致的代码执行顺序问题,所以修改起来没有那么容易。 76 | ui::SetDefaultX11ErrorHandlers(); 77 | #endif 78 | 79 | auto event_source_ = ui::PlatformEventSource::CreateDefault(); 80 | 81 | // This app isn't a test and shouldn't timeout. 82 | base::RunLoop::ScopedDisableRunTimeoutForTest disable_timeout; 83 | 84 | base::RunLoop run_loop; 85 | 86 | auto xdisplay = gfx::GetXDisplay(); 87 | 88 | // query Visual for "TrueColor" and 32 bits depth (RGBA) 89 | XVisualInfo visualinfo; 90 | if(XMatchVisualInfo(xdisplay, DefaultScreen(xdisplay), 32, TrueColor, &visualinfo)) { 91 | printf("TransparentVisualID: %d\n", visualinfo.visualid); 92 | } else if(XMatchVisualInfo(xdisplay, DefaultScreen(xdisplay), 24, TrueColor, &visualinfo)) { 93 | printf("OpaqueVisualID: %d\n", visualinfo.visualid); 94 | } else { 95 | auto* visual = DefaultVisual(xdisplay,DefaultScreen(xdisplay)); 96 | auto visualid = XVisualIDFromVisual(visual); 97 | // 在 Chromium 中 ui::XVisualManager 类封装了以下关于 Visual 的逻辑 98 | int visuals_len = 0; 99 | XVisualInfo visual_template; 100 | visual_template.screen = DefaultScreen(xdisplay); 101 | gfx::XScopedPtr visual_list(XGetVisualInfo( 102 | xdisplay, VisualScreenMask, &visual_template, &visuals_len)); 103 | 104 | for (int i = 0; i < visuals_len; ++i) { 105 | const XVisualInfo& info = visual_list[i]; 106 | if (info.visualid == visualid) { 107 | visualinfo = info; 108 | break; 109 | } 110 | } 111 | printf("Use default VisualID: %d\n", visualinfo.visualid); 112 | } 113 | 114 | Colormap colormap = XCreateColormap(xdisplay, DefaultRootWindow(xdisplay), 115 | visualinfo.visual, AllocNone); 116 | 117 | unsigned long attribute_mask = 0; 118 | XSetWindowAttributes swa; 119 | memset(&swa, 0, sizeof(swa)); 120 | 121 | attribute_mask |= CWBackPixel; 122 | swa.background_pixel = 0; 123 | 124 | attribute_mask |= CWColormap; 125 | swa.colormap = colormap; 126 | 127 | attribute_mask |= CWBorderPixel; 128 | swa.border_pixel = 0; 129 | 130 | // 创建一个透明窗口 131 | auto xwindow_ = 132 | XCreateWindow(xdisplay, DefaultRootWindow(xdisplay), 133 | 0, 0, 400, 300, 134 | 0, visualinfo.depth, InputOutput, visualinfo.visual, 135 | attribute_mask, &swa); 136 | 137 | // 控制窗口边框 138 | // ui::SetUseOSWindowFrame(xwindow_, false); 139 | XMapWindow(xdisplay, xwindow_); 140 | 141 | LOG(INFO) << "running..."; 142 | run_loop.Run(); 143 | 144 | return 0; 145 | } 146 | -------------------------------------------------------------------------------- /docs/content.md: -------------------------------------------------------------------------------- 1 | # content 2 | 3 | //content 模块可以分为以下几个相对独立的部分: 4 | 5 | 1. 负责多进程架构通用部分的初始化; 6 | 2. 负责 Browser/Renderer/Gpu/Utility 等进程专有部分的初始化; 7 | 3. Browser 进程负责的功能: 浏览器界面的创建,相关窗口句柄的维护,生成浏览器界面相关的CompositorFrame发送到Gpu进程,WebContents接口的调用,Renderer/Gpu进程的创建及相关通信通道的建立; 8 | 4. Renderer 进程负责的功能: Blink 的初始化,网页的渲染,生成网页相关的CompositorFrame发送到Gpu进程; 9 | 5. Gpu 进程负责的功能: CompositorFrame的渲染,提供Gpu Raster功能; 10 | 11 | TODO: 完善 content 模块的相关文档 12 | -------------------------------------------------------------------------------- /docs/images/2020-01-03-09-53-49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-01-03-09-53-49.png -------------------------------------------------------------------------------- /docs/images/2020-01-03-10-00-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-01-03-10-00-48.png -------------------------------------------------------------------------------- /docs/images/2020-01-03-10-01-55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-01-03-10-01-55.png -------------------------------------------------------------------------------- /docs/images/2020-01-03-13-48-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-01-03-13-48-06.png -------------------------------------------------------------------------------- /docs/images/2020-01-03-13-49-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-01-03-13-49-40.png -------------------------------------------------------------------------------- /docs/images/2020-01-03-14-13-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-01-03-14-13-56.png -------------------------------------------------------------------------------- /docs/images/2020-01-03-15-10-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-01-03-15-10-02.png -------------------------------------------------------------------------------- /docs/images/2020-01-03-17-09-31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-01-03-17-09-31.png -------------------------------------------------------------------------------- /docs/images/2020-05-22-17-09-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/2020-05-22-17-09-02.png -------------------------------------------------------------------------------- /docs/images/chromium-mojo-layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/chromium-mojo-layer.png -------------------------------------------------------------------------------- /docs/images/mojo_interface_pipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/mojo_interface_pipe.png -------------------------------------------------------------------------------- /docs/images/mojo_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aikuimail/chromium_demo/be722670e693d94414e9acdace54c0caf4284df5/docs/images/mojo_stack.png -------------------------------------------------------------------------------- /docs/startup.md: -------------------------------------------------------------------------------- 1 | # 浏览器启动流程简述 2 | 3 | 以下内容可以参考`demo_shell`的相关代码。 4 | 5 | 浏览器的启动流程可以简单分为以下几个阶段: 6 | 7 | 1. 初始化Content模块; 8 | 2. 初始化Browser进程; 9 | 3. 创建GPU进程; 10 | 4. 创建UI; 11 | 5. 创建Render进程; 12 | 13 | > content初始化相关类图见: 14 | 15 | ## 初始化Content模块(和Browser进程) 16 | 17 | content 通过被 services 模块启动。 18 | 19 | content实现了services 模块提供的接口,并且在 content::ContentMain() 中启动(services模块提供的) service_manager::Main() ,在这个函数中进行一些通用的初始化工作,最后(将content作为services的embedder)启动由content实现的RunEmbedderProcess()方法,至此servcies模块将控制权完全转移到content模块的ContentMainRunner。 20 | 21 | ContentMainRunner会启动ServiceManager,最后通过调用BrowserMain()将控制权转移到browser子模块。 22 | 23 | BrowserMain()通过BrowserMainRunner继续启动,BrowserMainRunner包装了BrowserMainLoop,BrowserMainLoop的主要功能包括: 24 | 25 | 1. 调用BrowserMainParts,以便允许用户的逻辑被执行; 26 | 1. 调用content::BrowserStartupComplete(),以便通知Android初始化完成; 27 | 1. 初始化主线程; 28 | 1. 创建IO线程; 29 | 1. 初始化Mojo; 30 | 1. 初始化音视频/麦克风/触摸屏等设备; 31 | 1. 初始化WebRTC; 32 | 1. 初始化剪切板相关服务; 33 | 1. 根据需求启动GPU进程; 34 | 1. 启动主线程的消息循环; 35 | 36 | BrowserMainParts作为Browser初始化的末端,用户在这里进行扩展,插入创建UI的逻辑。 37 | 38 | ``` 39 | #0 content/public/browser/browser_main_parts.cc:*() 40 | #1 content/browser/browser_main_loop.cc:*() 41 | #2 content/browser/browser_main_runner_impl.cc:*() 42 | #3 content/browser/browser_main.cc:43:BrowserMain() 43 | #4 content/app/content_main_runner_impl.cc529:RunBrowserProcessMain() 44 | #5 content/app/content_main_runner_impl.cc:978:RunServiceManager() 45 | #6 content/app/content_main_runner_impl.cc:878:Run() 46 | #7 content/app/content_service_manager_main_delegate.cc:52:RunEmbedderProcess() 47 | ``` 48 | 49 | 综上,Browser进程的初始化流程如下: 50 | content::ContentMain()->service_manager::Main()->SerivceManagerMainDelegate->ContentMainRunner->content::BrowserMain()->BrowserMainRunner->BrowserMainLoop->BrowserMainParts->(创建UI) 51 | 52 | ## 创建GPU进程 53 | 54 | TODO 55 | 56 | ## 创建UI 57 | 58 | Browser初始化完成之后,会在BrowserMainParts中创建UI。 59 | 60 | > 注意:并不是一定要在这里创建UI,因为创建UI是一个相对独立的过程,可以放在任何业务觉得合适的时机,比如放在用户打开某一个网页的时候再创建。 61 | 62 | 创建UI可以分为以下几步: 63 | 64 | 1. 创建Native窗口; 65 | 2. 创建WebContents,并将WebContents和Native窗口关联; 66 | 67 | 初始化OutputSurface 68 | 69 | ContentViewRenderView 用来显示网页内容,它内部维护了一个SurfaceView/TextureView,并且将他们的Surface传递到Native层,Native层使用它们创建OutputSurface,并且在该OutputSurface上绘制网页内容。 70 | 71 | TODO 72 | 73 | ## 创建Render进程 74 | 75 | Render进程并不会一开始就创建,而是在要打开某一个网页的时候才创建。 76 | 77 | Render进程的启动流程如下: 78 | WebContents->NavigationController->NavigationRequest->RenderFrameHostManager->SiteInstance->RenderProcessHost::Init()->ChildProcessLauncher 79 | 80 | 由于RenderProcess是按需启动的,因此它的启动流程比较复杂。 81 | 82 | TODO 83 | -------------------------------------------------------------------------------- /docs/ui.md: -------------------------------------------------------------------------------- 1 | # UI 2 | 3 | UI 分两部分,一部分是窗口,一部分是控件。 4 | 5 | chromium 中对窗口的包装包括: 6 | 7 | - aura 8 | - PlatformWindow 9 | - X11/Ozone/Windows 10 | 11 | chromium 中对UI控件的包装包括: 12 | 13 | - views 14 | - cc 15 | - viz 16 | 17 | chromium 中对渲染的包装包括: 18 | 19 | - skia 20 | - command buffer 21 | - angle 22 | - egl/opengl(es) 23 | 24 | TODO: 完善文档 25 | 26 | > views 和 WebContents 相关类图见: 27 | -------------------------------------------------------------------------------- /docs/viz.md: -------------------------------------------------------------------------------- 1 | # Viz (Visuals) 2 | 3 | > 最新文档见 [keyou.github.io/2020-07-29-how-viz-works.md](https://github.com/keyou/keyou.github.io/blob/master/_posts/2020-07-29-how-viz-works.md) 4 | 5 | `Viz` 用于 `compositing`,`gl`,`hit testing`,`media`。 6 | 7 | `Viz` 的代码在以下几个目录中: 8 | 9 | - `//services/viz`: 主要定义 viz 的 mojo 接口; 10 | - `//components/viz`: compositing 和 hit testing 部分的实现; 11 | - `//gpu`: gl 部分的实现; 12 | - `//media`: media 部分的实现; 13 | 14 | > 在 `//components/viz/demo` 下有一个官方提供的 Viz 的 demo, 这里的 demo_viz_gui 是参考那个 demo 完成的。在以上几个目录中也存放有关于 viz 的文档,这篇文档是对那些文档的总结和补充。 15 | 16 | Viz 涉及以下三个端: 17 | 18 | - `client`: 用于生成要显示的画面,至少有一个根 client,可以有多个子 client,它们组成了一个 client 树,每一个 Client 至少对应一个 FrameSinkId 和一个 LocalSurfaceId,如果父子 client 之间的 UI 需要嵌入,则子 client 作为 SurfaceDrawQuad 嵌入到父 client 中; 19 | - `host`: 用于注册 client 端,只能运行在特权端,负责协助 client 建立起和 service 的连接,从而建立 client 和 client 之间的树形关系; 20 | - `service`: 运行 Viz 的内核,进行UI合成以及最终的渲染,host 和 client 都需要和它交互。 21 | 22 | > 以上描述比较抽象,简单理解就是: 运行 `viz::mojom::FrameSinkMnagerClient` 的端叫做 host,运行 `viz::mojom::FrameSinkManager` 和 `viz::mojom::CompositorFrameSink` 的端叫 service, 运行 `viz::mojom::CompositorFrameSinkClient` 的端叫 client。 23 | 24 | ## 主要概念解释 25 | 26 | - `viz::mojom::CompositorFrameSinkClient (CFSC)` = Client:表示一个画面的来源; 27 | - `viz::mojom::CompositorFrameSink (CFS)` = FrameSink (FS):用于处理 CF 的地方,每一个 FrameSink 都单独处理某一部分的画面; 28 | - `viz::mojom::FrameSinkManager (FSM)` = FrameSinkManager:用于管理 CFS, 包括其创建和销毁; 29 | - `viz::CompositorFrame (CF)` = Frame:表示一个画面,可以是一帧完整的画面或者某一个区域的画面,它内部保存一个 `viz::RenderPass` 的列表; 30 | - `viz::RenderPass`:内部包含了一个 `viz::DrawQuad` 的列表; 31 | - `viz::DrawQuad`:包含具体的显示内容,目前共有 9 种显示内容,有简单的 DrawQuad,比如图片,视频,纯色等,也有用于嵌套的 DrawQuad,比如使用 `RenderPassDrawQuad` 可以嵌入其他的 RenderPass,使用 `SurfaceDrawQuad` 可以嵌入其他的 `viz::Surface` 等。 32 | - `viz::Surface`: 内部维护了 2 个 CompositorFrame 对象,分别为 ActiveFrame 和 PendingFrame,当 CF 所表示的画面的 size 或者 scale factor 改变的时候,会创建新的 Surface; 33 | 34 | > DrawQuad 类型列表:([draw_quad.h](https://source.chromium.org/chromium/chromium/src/+/master:components/viz/common/quads/draw_quad.h)) 35 | kPictureContent, 36 | kRenderPass, 37 | kSolidColor, 38 | kStreamVideoContent, 39 | kSurfaceContent, 40 | kTextureContent, 41 | kTiledContent, 42 | kYuvVideoContent, 43 | kVideoHole. 44 | 45 | ## Viz 的 Id 设计 46 | 47 | 每一个 client 都至少对应一个 `FrameSinkId` 和 `LocalSurfaceId`,在 client 的整个生命周期中所有 FrameSink 的 `client_id`(见下文)都是固定的,而 `LocalSurfaceId` 会根据 client 显示画面的 size 或 scale factor 的改变而改变。他们两个共同组成了 `SurfaceId`,用于在 service 端全局标识一个 `Surface` 对象。也就是说对于每一个 `Surface`,都可以获得它是由谁在什么 size 或 scale facotr 下产生的。 48 | 49 | ### `FrameSinkId` 50 | 51 | - `client_id` = uint32_t, 每个 client 都会有唯一的一个 ClientId 作为标识符,标识一个 CompositorFrame 是由哪个 client 产生的,也就是标识 CompositorFrame 的来源; 52 | - `sink_id` = uint32_t, 在 service 端标识一个 CompositorFrameSink 实例,Manager 会为每个 client 在 service 端创建一个 CompositorFrameSink,专门用于处理该 client 生成的 CompositorFrame,也就是标识 CompositorFrame 的处理端; 53 | - `FrameSinkId = client_id + sink_id`,将 CF 的来源和处理者关联起来。 54 | 55 | FrameSinkId 可以由 `FrameSinkIdAllocator` 辅助类生成。 56 | 57 | > 什么时候需要使用单 client 多 FrameSink? 58 | (以下为推测,没有验证。TODO: 验证以下想法。) 59 | 在实际使用中,往往一个进程就是一个 client,专门负责一个业务模块 UI 的实现,而一个业务往往由很多的 UI 元素组成,因此可以让每个 FrameSink 负责一部分的 UI,此时就需要单使用单 client 多 FrameSink 的机制了,这种机制可以实现 UI 的局部刷新。当然,多 client 也能实现这一点,从设计上来讲,此时 client_id 的设计意义以及允许单 client 多 FrameSink 的设计意义就没有那么大了。所以推测在 chrome 中浏览器主程序是一个 client,而每一个插件都是一个独立的 client。 60 | 61 | ### `LocalSurfaceId` 62 | 63 | - `parent_sequence_number` = uint32_t, 当自己作为父 client,并且 surface 的 size 和 device scale factor 改变的时候改变; 64 | - `child_sequence_number` = uint32_t, 当自己作为子 client,并且 surface 的 size 和 device scale factor 改变的时候改变; 65 | - `embed_token` = 可以理解为一个随机数, 用于避免 LocalSurafaceId 可猜测,当父 client 和子 client 的父子关系改变的时候改变; 66 | - `LocalSurfaceId = parent_sequence_number + child_sequence_number + embed_token`,当 client 的 size 当前 client 产生的画面改变。 67 | 68 | LocalSurfaceId 可以由 `ParentLocalSurfaceIdAllocator` 或者 `ChildLocalSurfaceIdAllocator` 这两个辅助类生成。前者用于由父 client 负责生成自己的 LocalSurfaceId 的时候,后者用于由子 client 自己负责生成自己的 LocalSurfaceId 的时候。使用哪种方式要看自己的 UI 组件之间的依赖关系的设计。 69 | 70 | LocalSurfaceId 在很多时候都包装在 `LocalSurfaceIdAllocation` 内,该类记录了 LocalSurfaceId 的创建时间。改时间在创建 CF 的时候需要用到。 71 | 72 | ### `SurfaceId` 73 | 74 | `SurfaceId = FrameSinkId + LocalSurfaceId` 75 | 76 | SurfaceId 全局唯一记录一个显示画面,它可以被嵌入其他的 CF 或者 RenderPass 中,从而实现显示界面的嵌入和局部刷新。 77 | 78 | ## Viz 的显示原理 79 | 80 | > Viz 和 cc 相关的类图见: 81 | 82 | ## 附录 83 | 84 | ### 背景及相关模块 85 | 86 | Mus = Mojo Ui Service 87 | 88 | 89 | -------------------------------------------------------------------------------- /mojom/consumer_service_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "consumer_service", 3 | "display_name": "Consumer Service", 4 | "interface_provider_specs": { 5 | "service_manager:connector": { 6 | "provides": { 7 | "root": ["demo.mojom.RootInterface"] 8 | }, 9 | "requires": { 10 | "test_service": ["test"] 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /mojom/test.mojom: -------------------------------------------------------------------------------- 1 | 2 | // Chromium 推荐将mojom文件放在单独的mojom目录下 3 | 4 | module demo.mojom; 5 | 6 | interface Test { 7 | Hello(string who); 8 | Hi() => (string who); 9 | }; -------------------------------------------------------------------------------- /mojom/test2.mojom: -------------------------------------------------------------------------------- 1 | 2 | // Chromium 推荐将mojom文件放在单独的mojom目录下 3 | 4 | module demo.mojom; 5 | 6 | interface Test2 { 7 | SendMessagePipeHandle(handle pipe_handle); 8 | }; 9 | -------------------------------------------------------------------------------- /mojom/test3.mojom: -------------------------------------------------------------------------------- 1 | 2 | // Chromium 推荐将mojom文件放在单独的mojom目录下 3 | 4 | module demo.mojom; 5 | 6 | interface Api { 7 | PrintApi(string data); 8 | }; 9 | 10 | interface Api2 { 11 | PrintApi2(string data); 12 | }; 13 | 14 | interface Test3 { 15 | GetApi(Api& api); 16 | SetApi2(Api2 api2); 17 | }; 18 | 19 | interface Test32 { 20 | GetApi(associated Api& api); 21 | SetApi2(associated Api2 api2); 22 | }; -------------------------------------------------------------------------------- /mojom/test4.mojom: -------------------------------------------------------------------------------- 1 | 2 | // Chromium 推荐将mojom文件放在单独的mojom目录下 3 | 4 | module demo.mojom; 5 | 6 | // generic_pending_receiver 在新版中才有 7 | // import "mojo/public/mojom/base/generic_pending_receiver.mojom"; 8 | 9 | // interface Test4 { 10 | // TTTT(mojo_base.mojom.GenericPendingReceiver receiver); 11 | // }; 12 | 13 | interface InterfaceBroker { 14 | GetInterface(string name,handle pipe_handle); 15 | }; 16 | 17 | interface Interface1 { 18 | Hello(string who); 19 | }; 20 | 21 | interface Interface2 { 22 | Hi(string who); 23 | }; 24 | -------------------------------------------------------------------------------- /mojom/test_service.mojom: -------------------------------------------------------------------------------- 1 | 2 | module demo.mojom; 3 | 4 | // const string kServiceName = "testservice"; 5 | // const string kTestCapability = "test"; 6 | 7 | interface TestInterface { 8 | Hello(string who); 9 | }; 10 | 11 | interface RootInterface { 12 | Hi(string who); 13 | }; 14 | -------------------------------------------------------------------------------- /mojom/test_service_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test_service", 3 | "display_name": "Test Service", 4 | "interface_provider_specs": { 5 | "service_manager:connector": { 6 | "provides": { 7 | "test": ["demo.mojom.TestInterface"] 8 | }, 9 | "requires": { 10 | "consumer_service":["root"] 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /patches/0001-demo_viz_layer_offscreen-add-GetOffscreenTextureId.patch: -------------------------------------------------------------------------------- 1 | From dcf992dac28c1d35803596ea8d59b6a737689ce3 Mon Sep 17 00:00:00 2001 2 | From: keyou 3 | Date: Sat, 1 Aug 2020 11:06:30 +0800 4 | Subject: [PATCH] demo_viz_layer_offscreen: add GetOffscreenTextureId 5 | 6 | --- 7 | .../viz/service/display/skia_output_surface.h | 3 +++ 8 | .../skia_output_device_offscreen.cc | 16 +++++++++++++++- 9 | 2 files changed, 18 insertions(+), 1 deletion(-) 10 | 11 | diff --git a/components/viz/service/display/skia_output_surface.h b/components/viz/service/display/skia_output_surface.h 12 | index 2f06602e9c0d..d014af23bdf2 100644 13 | --- a/components/viz/service/display/skia_output_surface.h 14 | +++ b/components/viz/service/display/skia_output_surface.h 15 | @@ -41,6 +41,9 @@ namespace copy_output { 16 | struct RenderPassGeometry; 17 | } // namespace copy_output 18 | 19 | +#define VIZ_GETOFFSCREENTEXTUREID 20 | +VIZ_SERVICE_EXPORT GrGLuint GetOffscreenTextureId(); 21 | + 22 | // This class extends the OutputSurface for SkiaRenderer needs. In future, the 23 | // SkiaRenderer will be the only renderer. When other renderers are removed, 24 | // we will replace OutputSurface with SkiaOutputSurface, and remove all 25 | diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_offscreen.cc 26 | index 9d38dda19d9d..721d09e20d97 100644 27 | --- a/components/viz/service/display_embedder/skia_output_device_offscreen.cc 28 | +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.cc 29 | @@ -8,6 +8,7 @@ 30 | 31 | #include "gpu/command_buffer/service/skia_utils.h" 32 | #include "third_party/skia/include/core/SkSurface.h" 33 | +#include "components/viz/service/display/skia_output_surface.h" 34 | 35 | namespace viz { 36 | 37 | @@ -16,9 +17,14 @@ namespace { 38 | // Some Vulkan drivers do not support kRGB_888x_SkColorType. Always use 39 | // kRGBA_8888_SkColorType instead and initialize surface to opaque as necessary. 40 | constexpr SkColorType kSurfaceColorType = kRGBA_8888_SkColorType; 41 | +GrGLuint g_offscreen_texture_id = 0; 42 | 43 | } // namespace 44 | 45 | +GrGLuint GetOffscreenTextureId() { 46 | + return g_offscreen_texture_id; 47 | +} 48 | + 49 | SkiaOutputDeviceOffscreen::SkiaOutputDeviceOffscreen( 50 | scoped_refptr context_state, 51 | bool flipped, 52 | @@ -55,8 +61,16 @@ void SkiaOutputDeviceOffscreen::SwapBuffers( 53 | std::vector latency_info) { 54 | // Reshape should have been called first. 55 | DCHECK(backend_texture_.isValid()); 56 | - 57 | + TRACE_EVENT0("viz", "SkiaOutputDeviceOffscreen::SwapBuffers"); 58 | StartSwapBuffers(std::move(feedback)); 59 | + 60 | + GrBackendTexture skia_texture = 61 | + sk_surface_->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess); 62 | + GrGLTextureInfo gl_texture_info; 63 | + skia_texture.getGLTextureInfo(&gl_texture_info); 64 | + g_offscreen_texture_id = gl_texture_info.fID; 65 | + DCHECK(g_offscreen_texture_id); 66 | + 67 | FinishSwapBuffers(gfx::SwapResult::SWAP_ACK, 68 | gfx::Size(size_.width(), size_.height()), 69 | std::move(latency_info)); 70 | -- 71 | 2.17.1 72 | 73 | --------------------------------------------------------------------------------