chromium blink core outline

chromium blink core outline_51CTO博客_switchyomega_chromium.crx

Multi-process architecture, there is one browser process and N sandbox renderer processes, Blink runs in sandbox rendering. Browser tabs and iframes can share the same renderer process.

Sandbox operation: In the sandbox, the parent browser process must be used to schedule and use resources (file access, network, audio and video playback, user configuration file reading (cookie, password), etc. Blink abstracts the browser process into a group Services, use Mojo to interact with services and browser processes.

threads in the rendering process

1 main thread: run JavaScript, DOM, CSS, style, layout calculation
N worker threads: run Web Worker, ServiceWorker, Worklet
internal thread: Blink and V8 will create several threads to handle
cross-thread communication such as web audio, database, GC, etc. : You must use the PostTask API to use messaging. Shared memory programming is discouraged unless there are a few places where it is needed for performance reasons. This is why you don't see many MutexLocks in the Blink codebase.

Page, Frame, Document, ExecutionContext and DOMWindow are the following concepts:

Page: A page corresponds to the concept of a tab (if OOPIF explained below is not enabled). Each renderer process may contain multiple tabs.
Frame: A frame corresponds to the concept of a frame (main frame or iframe). Each page may contain one or more frames arranged in a tree hierarchy. 1:n
DOMWindow corresponds to the windows object in JavaScript. Each Frame has only one DOMWindow. 1:1
Document corresponds to the window.document object in JavaScript. Each iframe has only one Document. 1:1
ExecutionContext is a concept that abstracts Document (for main thread) and WorkerGlobalScope (for worker thread).


Renderer process : Page = 1 : N In the case of a single process, in the case of multiple processes, it needs to be distinguished according to the mode.

Page : Frame = 1 : M

Frame : DOMWindow : Document (or ExecutionContext) = 1 : 1 : 1

page is a tab or a background page in a chromium extension.

Execution context ExecutionContext is the execution context of JS. A page corresponds to multiple: After each frame is attached to the DOM, there will be an implicit execution context; the extension has another execution context. ​​​​

DOMWindow (js windows object) and Document (js window.document) (or ExecutionContext) are used for interactive control in JS.

Frames that are local to the renderer process are represented by LocalFrame, while frames that are not local to the renderer process are represented by RemoteFrame.

From the perspective of the main frame, the main frame is LocalFrame, and <iframe> is RemoteFrame. From the perspective of <iframe>, the main frame is RemoteFrame, and <iframe> is LocalFrame.

Communication between LocalFrame and RemoteFrame (which may exist in different renderer processes) is handled through the browser process.

It is very important to understand the concepts of Isolate, Context and World when writing code for the V8 API. They are represented by v8::Isolate, v8::Context and DOMWrapperWorld respectively in the codebase.

Isolate corresponds to a physical thread. Isolate : physical thread in Blink = 1 : 1. The main thread has its own isolation. Worker threads have their own isolation.

An instance of V8 is called Isolate, and each isolate has its own stack space for GC. This means that JavaScript objects in one Isolate cannot directly access objects in another Isolate.

In Chrome, each rendering process has a V8 Isolate, and all JavaScript codes of sites processed by the same rendering process run in the same Isolate. But for Web workers, each worker has its own Isolate.

In Isolate, there are one or more JavaScript contexts (JavaScript content). Chrome creates a JavaScript environment for each iframe. Also, each Chrome extension has its own JavaScript environment for an iframe. Blink usually uses the ScriptState object as a reference to the JavaScript environment, and blink::ScriptState has a 1:1 relationship with v8::Context. (Reference: https://zhuanlan.zhihu.com/p/279920830​​)

Context corresponds to the global object (in the case of Frame, it's the Frame's window object). Since each frame has its own window object, there are multiple contexts in the renderer process. When you call the V8 API, you must ensure that you are in the correct context. Otherwise, v8::Isolate::GetCurrentContext() will return the wrong context, and in the worst case, it will end up leaking objects and causing security issues.

World is a concept that supports Chrome extension content scripts. The world doesn't correspond to anything in web standards. Content scripts want to share the DOM with the web page, but for security reasons the content script's JavaScript objects must be isolated from the web page's JavaScript heap. (Another content script's JavaScript heap must be isolated from another content script's JavaScript heap.) To achieve isolation, the main thread creates a main world for the web page and an isolated world for each content script. The main world and the isolated world have access to the same C++ DOM objects, but their JavaScript objects are isolated. This isolation is achieved by creating multiple V8 wrappers for one C++ DOM object. i.e. one V8 wrapper per world.

What is the relationship between Context, World and Frame?

Imagine that there are N worlds on the mainline (one main world + (N - 1) isolated worlds). Then a Frame should have N window objects, and each window object is for one world. A context is a concept corresponding to a window object. This means that when we have M frames and N worlds, we have M * N contexts (but contexts are created lazily).

For workers, there is only one world and one global object. Therefore, there is only one context.

Also, when you use the V8 API, you should be very careful to use the correct context. Otherwise, you end up leaking JavaScript objects between isolated worlds and causing a security disaster (e.g. an extension from A.com can manipulate an extension from B.com).

By Jeff Mony

Link: https://www.jianshu.com/p/2a2424bdc057

Source: Jianshu

Copyright belongs to the author. For commercial reprint, please contact the author for authorization, for non-commercial reprint, please indicate the source.

The browser's rendering process is multi-threaded (if you don't understand this, please look back at the distinction between processes and threads)

Finally arrived at the concept of thread????, so kind. Then let's see which threads it contains (list some main resident threads):

1. GUI rendering thread

Responsible for rendering browser interface, parsing HTML, CSS, building DOM tree and RenderObject tree, layout and drawing, etc.

When the interface needs to be repainted (Repaint) or reflow (reflow) is triggered by some operation, the thread will execute

Note that the GUI rendering thread and the JS engine thread are mutually exclusive. When the JS engine executes, the GUI thread will be suspended (equivalent to being frozen), and the GUI update will be saved in a queue and executed immediately when the JS engine is idle. .

2. JS engine thread

Also known as the JS kernel, it is responsible for processing Javascript script programs. (e.g. V8 engine)

The JS engine thread is responsible for parsing Javascript scripts and running code.

The JS engine has been waiting for the arrival of the task in the task queue, and then processed it. There is only one JS thread running the JS program in a Tab page (renderer process) at any time.

Also note that the GUI rendering thread and the JS engine thread are mutually exclusive, so if the execution time of JS is too long, the rendering of the page will be incoherent, resulting in blocking of page rendering and loading.

3. Event trigger thread

Belonging to the browser rather than the JS engine, it is used to control the event loop (it is understandable that the JS engine itself is too busy, and the browser needs to open another thread to assist)

When the JS engine executes code blocks such as setTimeOut (or other threads from the browser kernel, such as mouse clicks, AJAX asynchronous requests, etc.), it will add the corresponding task to the event thread

When the corresponding event meets the trigger conditions and is triggered, the thread will add the event to the end of the queue to be processed, waiting for the processing of the JS engine

Note that due to the single-threaded relationship of JS, the events in these pending queues have to be queued for processing by the JS engine (they will be executed when the JS engine is idle)

4. Timing trigger thread

The thread where the legendary setInterval and setTimeout are located

The browser timing counter is not counted by the JavaScript engine (because the JavaScript engine is single-threaded, if it is in a blocked thread state, it will affect the accuracy of the timing)

So use a separate thread to time and trigger the timing (after the timing is over, add it to the event queue, wait for the JS engine to be idle and execute it)

Note that W3C stipulates in the HTML standard that a time interval lower than 4ms in setTimeout is required to be counted as 4ms.

5. Asynchronous http request thread

After XMLHttpRequest is connected, a new thread request is opened through the browser

When a state change is detected, if a callback function is set, the asynchronous thread will generate a state change event, and then put this callback into the event queue. Then executed by JavaScript engine.

The GUI rendering thread and the JS engine thread are mutually exclusive.
Since JavaScript can manipulate the DOM, if the interface is rendered while modifying the properties of these elements (that is, the JS thread and the UI thread run at the same time), the element data obtained before and after the rendering thread may be inconsistent.

Therefore, in order to prevent unpredictable rendering results, the browser sets the GUI rendering thread and the JS engine as a mutually exclusive relationship. When the JS engine executes, the GUI thread will be suspended.

GUI updates will be stored in a queue and executed immediately when the JS engine thread is idle.

JS blocks page loading
From the above mutual exclusion relationship, it can be deduced that if JS executes for too long, it will block the page.

For example, assuming that the JS engine is doing a huge amount of calculations, even if the GUI is updated at this time, it will be saved in the queue and executed after the JS engine is idle.

Then, due to the huge amount of calculations, the JS engine is likely to be idle for a long time, and it will naturally feel that the huge card is extremely large.

Therefore, try to avoid JS execution time being too long, which will cause incoherent rendering of the page, resulting in the feeling of page rendering and loading blocking.

WebWorker, multithreading for JS?
As mentioned in the previous article, the JS engine is single-threaded, and if the JS execution time is too long, it will block the page, so is JS really helpless for CPU-intensive calculations?

Therefore, Web Worker was supported in HTML5 later.

MDN's official explanation is:

Web Workers provide an easy way for web content to run scripts in background threads. Threads can perform tasks without interfering with the user interface. A worker is an object created using a constructor (eg Worker()) that runs a named JavaScript file. This file contains the code that will run in the worker thread; workers run in another global The context is different from the current window. Therefore, using the window shortcut to get the current global scope (instead of self) will return an error within a Worker

Understood this way:

When creating a Worker, the JS engine applies to the browser to open a sub-thread (the sub-thread is opened by the browser and is completely controlled by the main thread, and cannot operate the DOM)

The JS engine thread communicates with the worker thread in a specific way (postMessage API needs to serialize objects to interact with the thread for specific data)

Therefore, if you have very time-consuming work, please open a Worker thread separately, so that no matter how earth-shaking it is, it will not affect the main thread of the JS engine.

Just after calculating the result, communicate the result to the main thread, perfect!

And note that the JS engine is single-threaded, and the essence of this has not changed. It can be understood that Worker is opened by the browser for the JS engine, and it is specially used to solve those massive calculation problems.

In addition, the detailed explanation of Worker is beyond the scope of this article, so I won’t repeat it here.

Now that both WebWorker and SharedWorker
are here, let’s mention SharedWorker again (to avoid confusing these two concepts later)

WebWorker only belongs to a certain page and will not be shared with the Render process (browser kernel process) of other pages

So Chrome creates a new thread in the Render process (each Tab page is a render process) to run the JavaScript program in the Worker.

SharedWorker is shared by all pages of the browser and cannot be implemented in the same way as Worker, because it does not belong to a Render process and can be shared by multiple Render processes

So the Chrome browser creates a separate process for SharedWorker to run JavaScript programs. There is only one SharedWorker process for each identical JavaScript in the browser, no matter how many times it is created.

Seeing this, it should be easy to understand that it is essentially the difference between a process and a thread. SharedWorker is managed by an independent process, and WebWorker is just a thread under the render process

Author: Jony0114

Link: https://www.jianshu.com/p/f1e5ad3b4afb

Source: Jianshu

Copyright belongs to the author. For commercial reprint, please contact the author for authorization, for non-commercial reprint, please indicate the source.

Frame and WebFrame
There is a one-to-one correspondence between Frame and WebFrame. Frame can find WebFrame through client, and WebFrame can also find Frame through Client.

Other Web** encapsulated classes can refer to this

 IFrame, window, document get each other

LocalFrame* frame = node_->GetDocument().GetFrame();
  if (frame && frame->DomWindow())//Get domwindow in frame
    eventTiming = EventTiming::Create(frame->DomWindow(), *event_);
  event_->GetEventPath().EnsureWindowEventContext(); //Get the domWindow send event from the event

//Send events from context
auto* window = To<LocalDOMWindow>(GetExecutionContext());
window->DispatchEvent(*Event::Create(event_name));

Get domwindow in frame Send event 
    frame_? frame_->DomWindow()
    frame_->DomWindow() is null??
   frame_->DomWindow()->DispatchEvent(unload_event, this);

Get frame    
1, get current frame
LocalFrame* Document: :ExecutingFrame() {   LocalDOMWindow* window = ExecutingWindow();   if (!window)     return nullptr;   return window->GetFrame(); }




2. Find the top frame. Frame has window and document js object
Frame& top = GetFrame()->Tree().Top();
  KURL top_document_url;
  auto* top_local_frame = DynamicTo<LocalFrame>(&top);

3. Get frame from domwindow
1.
LocalDOMWindow* executing_window = ExecutingWindow();
1.
LocalFrame* frame = executing_window->GetFrame();

Get the document js object
frame_->GetDocument() in the frame
 


 

localDomWindow sends event, prototype: DispatchEventResult LocalDOMWindow::DispatchEvent(Event& event,EventTarget* target)

 DispatchEvent(*Event::Create(event_type_names::kLanguagechange));

DispatchEvent(*PageTransitionEvent::Create(event_type_names::kPageshow,false /* persisted */),document_.Get());

 
-----------------------------------
chromium blink core outline
https://blog.51cto.com/u_15057855/4536130

Guess you like

Origin blog.csdn.net/juruiyuan111/article/details/128427393
Recommended