sudo apt install git python
depot_tools
is a toolkit for Chromium development. To install it you need to run: git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:/path/to/depot_tools"
depot_tools
were downloaded to the home folder, then do not use ~
in the PATH
variable, otherwise problems may occur. You must use the $HOME
variable: export PATH="$PATH:${HOME}/depot_tools"
mkdir ~/chromium && cd ~/chromium
fetch
utility from depot_tools
: fetch --nohooks --no-history chromium
--no-history
flag is used. With the story will be even longer.src
folder, go to it: cd src
./build/install-build-deps.sh
gclient runhooks
.ninja
files.example
in the src
folder: mkdir example
src/example
folder you need to create a BUILD.gn
file that contains: executable("example") { sources = [ "example.cc", ] }
BUILD.gn
consists of a target (an executable example
file) and a list of files that are needed to build a target.example.cc
. To begin with, I propose to make the classic application “Hello world”: #include <iostream> int main(int argc, char **argv) { std::cout << "Hello world" << std::endl; return 0; }
"//example"
in the deps
section in the BUILD.gn
file that is located in src
: ... group("gn_all") { testonly = true deps = [ ":gn_visibility", "//base:base_perftests", "//base:base_unittests", "//base/util:base_util_unittests", "//chrome/installer", "//chrome/updater", "//net:net_unittests", "//services:services_unittests", "//services/service_manager/public/cpp", "//skia:skia_unittests", "//sql:sql_unittests", "//third_party/flatbuffers:flatbuffers_unittests", "//tools/binary_size:binary_size_trybot_py", "//tools/ipc_fuzzer:ipc_fuzzer_all", "//tools/metrics:metrics_metadata", "//ui/base:ui_base_unittests", "//ui/gfx:gfx_unittests", "//url:url_unittests", # ↓↓↓↓↓↓↓↓ "//example", ] ...
src
folder and generate the project using the command: gn gen out/Default
gn help gen
example
project in QtCreator, you need to run the command: gn gen --ide=qtcreator --root-target=example out/Default
qtcreator out/Default/qtcreator_project/all.creator
autoninja -C out/Default example
./out/Default/example
#include "base/command_line.h"
base
in BUILD.gn
. BUILD.gn
should look like this: executable("example") { sources = [ "example.cc", ] deps = [ "//base", ] }
example
.base::CommandLine
. To get a link to it, you must use the static base::CommandLine::ForCurrentProcess
, but first you need to initialize it using the base::CommandLine::Init
method: base::CommandLine::Init(argc, argv); auto *cmd_line = base::CommandLine::ForCurrentProcess();
-
returned as base::SwitchMap
(essentially, map<string, string>
) using the GetSwitches
method. All other arguments are returned in the form of base::StringVector
(in fact, vectr<strig>
). This knowledge is enough to implement the code for the task: for (const auto &sw : cmd_line->GetSwitches()) { std::cout << "Switch " << sw.first << ": " << sw.second << std::endl; } for (const auto &arg: cmd_line->GetArgs()) { std::cout << "Arg " << arg << std::endl; }
autoninja -C out/Default example ./out/Default/example arg1 --sw1=val1 --sw2 arg2
Switch sw1: val1 Switch sw2: Arg arg1 Arg arg2
URLRequest
, which already determines which client to use. A simplified diagram looks like this:URLRequest
you must use a URLRequestContext
. Creating a context is a rather complicated operation, so it is recommended to use URLRequestContextBuilder
. It initializes all necessary variables with default values, but, if you wish, you can change them for your own, for example: net::URLRequestContextBuilder context_builder; context_builder.DisableHttpCache(); context_builder.SetSpdyAndQuicEnabled(true /* http2 */, false /* quic */); context_builder.SetCookieStore(nullptr);
base::Callback
, which can be created using base::Bind
.pthread
on POSIX or CreateThread()
on Windows). Implemented in the base::PlatformThread
class, do not use directly.base::ThreadPool
class. As a rule, create one copy. Tasks are sent to it using functions from base/task/post_task.h
.base::TaskRunner
.base::SequencedTaskRunner
class.base::SingleThreadTaskRunner
.base::AtExitManager
- this is the class that allows you to register the operations that must be performed when the application terminates. Using it is very simple; you need to create an object on the stack: base::AtExitManager exit_manager;
exit_manager
goes out of scope, all registered callbacks will be executed.Thread pool
, Message loop
with the TYPE_IO
type for processing network messages, and the Run loop
is the main program loop: base::ThreadPool::CreateAndStartWithDefaultParams("downloader"); base::MessageLoop msg_loop(base::MessageLoop::TYPE_IO); base::RunLoop run_loop;
Context builder
to create a Context
: auto ctx = net::URLRequestContextBuilder().Build();
CreateRequest
method of the ctx
object to create a URLRequest
object. The following parameters are passed as parameters:net::URLRequest::Delegate
interface. For this task, it might look like this: class MyDelegate : public net::URLRequest::Delegate { public: explicit MyDelegate(base::Closure quit_closure) : quit_closure_(std::move(quit_closure)), buf_(base::MakeRefCounted<net::IOBuffer>(BUF_SZ)) {} void OnReceivedRedirect(net::URLRequest *request, const net::RedirectInfo &redirect_info, bool *defer_redirect) override { std::cerr << "redirect to " << redirect_info.new_url << std::endl; } void OnAuthRequired(net::URLRequest* request, const net::AuthChallengeInfo& auth_info) override { std::cerr << "auth req" << std::endl; } void OnCertificateRequested(net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info) override { std::cerr << "cert req" << std::endl; } void OnSSLCertificateError(net::URLRequest* request, int net_error, const net::SSLInfo& ssl_info, bool fatal) override { std::cerr << "cert err" << std::endl; } void OnResponseStarted(net::URLRequest *request, int net_error) override { std::cerr << "resp started" << std::endl; while (true) { auto n = request->Read(buf_.get(), BUF_SZ); std::cerr << "resp read " << n << std::endl; if (n == net::ERR_IO_PENDING) return; if (n <= 0) { OnReadCompleted(request, n); return; } std::cout << std::string(buf_->data(), n) << std::endl; } } void OnReadCompleted(net::URLRequest *request, int bytes_read) override { std::cerr << "completed" << std::endl; quit_closure_.Run(); } private: base::Closure quit_closure_; scoped_refptr<net::IOBuffer> buf_; };
OnResponseStarted
event OnResponseStarted
: the contents of the response are read until an error occurs or there is nothing to read. Since after reading the response, you need to terminate the application, the delegate must have access to the function that will interrupt the main Run loop
, in this case, callback of type base::Closure
. MyDelegate delegate(run_loop.QuitClosure()); auto req = ctx->CreateRequest(GURL(args[0]), net::RequestPriority::DEFAULT_PRIORITY, &delegate); req->Start();
Run loop
: run_loop.Run();
autoninja -C out/Default example out/Default/example "https://example.com/"
base::TaskScheduler
turned into base::ThreadPool
, thankfully, without changing the API.Source: https://habr.com/ru/post/455956/
All Articles