"Chromium Chinese Document" Profile schema (see the refactoring of Google home)

Source: Internet
Author: User

Process Model

Reprint Please specify source: https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Profile_Architecture.html

Book Address
Chromium Chinese document for Https://www.chromium.org/developers/design-documents
Continuous update ing, welcome to star
Gitbook Address: https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//
GitHub Address: Https://github.com/ahangchen/Chromium_doc_zh

Profile architecture

This article describes an ongoing design refactoring that began in January 2012.

Note: After June 2013, this post needs to be updated. The related classes are renamed (s/profilekeyed/browsercontextkeyed/) and moved to Components/browser_context_keyed_service.

Chromium has many profile -linked features, called profiles, which are some of the current chrome sessions with the current user and across multiple browser windows. At the beginning of the chromium, profile had only a few dynamic parts: The cookie jar package, the history database, the bookmark database, and something related to the user's preferences. In the chromium project for three years, profile became the connection point for each feature, deriving something like profile::getinstantpromocounter () or profile: Gethostcontentsettingsmap (). Until this article is complete, there are already 58 pure virtual functions in profile.

A profile should be a minimal reference, a handle object that does not own an entity.

Design goals
    • we must be able to move to the new architecture in a segmented manner. each time a service and feature is transferred. We cannot stop the rotation of the Earth and transform everything in a moment. Writing down these things, we've moved 19 of our services out of profile.
    • We should only swap small modifications on the end, and at the end of the call, profile is used to get the service in the problem.
    • We have to fix the profile removal issue. When we started this work, there were only a small number of objects outside profile, and it was acceptable to manually collate them for split purposes. But now that we have 75 components, we know that it is wrong to manually split the collation, as written here. With so many components, we can no longer rely on manual sorting.
    • We must allow the addition of new features or remove old ones. Now that we have some chromium branches that don't contain all of the features in Windows/mac/linux Google Chrome standard build, we should allow such a way for these branches to be able to do without #ifdef Profile.h and Profile_impl.h made a mess of the case, compiled successfully. These branches also have the services they need to provide. (allowing chromium branches to add their own services also touches on why we cannot rely on manual grooming in the profile removal process.) )
    • Extension goal: Isolate different features into their own. A or. So files to further reduce the compilation link time for our wonderful flowers.
Browsercontextkeyedservicefactory

Browser Context Critical Service factory

The old way: Profile interface and PROFILEIMPL implementation

In previous designs, services were usually obtained using an accessor in profile:

classProfileImpl{  public:    virtual FooService* GetFooService();  private:    scoped_ptr<FooService> foo_service_;};

In the previous system, profile was made up of mostly pure virtual accessors. Normal, Incognito (anonymous) and testing (test) profile.

In this world, profile is the center of all activities. Profile is useful for all of its services and is delivered to the outside world. The profile split follows any principle of ordering services in Profileimpl. Another branch is not possible if you want to add your own services or remove unwanted services without modifying the profile interface.

New Way: Browsercontextkeyedservicefactory

Instead of having a service for profile, we designed a dedicated singleton fooservicefactory, such as a minimal implementation:

class fooservicefactory:   Public  browsercontextkeyedservicefactory {public : static   fooservice* getforprofile  (profile* profile); static  fooservicefactory* getinstance (); private : Friend struct  defaultsingletontraits  <FooServiceFactory>;  Fooservicefactory ();  virtual  ~fooservicefactory ();  //browsercontextkeyedservicefactory:  virtual  browsercontextkeyedservice* buildserviceinstancefor (content::browsercontext* context)  const  OVERRIDE;};  

We have a generic browsercontextkeyedservicefactory, which uses an object provided by your Buildserviceinstancefor () method to perform most of the work related to profile. Browsercontextkeyedservicefactory provides you with a rewrite interface that lets you manage the lifecycle of your service objects in response to the profile lifecycle events, and before service-dependent service shuts down, Close it itself.

An absolute minimum factory will provide the following methods:
-A static getinstance () method, with a single case pointing to your factory.
-a constructor that associates the Browsercontextkeyedservicefactory and Profiledependencymanager instances, and makes a DependsOn () declaration.
-A Getforprofile () method that wraps the Browsercontextkeyedservicefactory and converts the returned result to the return value you want.
-A Buildserviceinstancefor () method, the framework calls this method once for each |profile|, and it must return a suitable instance of your service.

In addition, Browsercontextkeyedservicefactory provides these additional assistance for your control behavior:

    • Registeruserprefs (): Each profile is called once when it is initialized and where the user's preference is registered
    • By default, BCKSF returns NULL when given a incognito profile
      • If you override the Serviceredirectedinincognito () method and return True, it returns the service associated with the normal profile.
      • If you rewrite Servicehasowninstanceinincognito () and return True, it will create a new service for Incognito profile.
    • By default, BCKSF will delay the creation of your service, and if you rewrite Serviceiscreatedwithprofile () and return True, your service will be created with profile.

    • BCKSF provides you with a variety of ways to control behavior during unit testing. See the header file for more information.

    • BCKSF provides a way for you to add and fix the removed and released behavior in a way.
Several factories

Not all objects have the same lifecycle and memory management. The preceding paragraph is a major simplified version; the base class browsercontextkeyedbasefactory defines most common dependencies, and Browsercontextkeyedservicefactory is a factory that specifically handles the usual objects. The other refcountedbrowsercontextkeyedservicefactory has a slight difference in semantics and in the storage of Refcountedthreadsafe objects.

A little episode of Complexity

This is a lot more complicated than the previous version of the implementation, is it worth it?

Yes.

We should definitely emphasize the independence of our services. As it is today, after the multi-profile mode is no longer necessary, we do not immediately remove profile, because our crash rate is too high to be accepted by the user when we remove it. We have 75 components inserted into the profile life cycle, and their dependency graphs are so complex that our simple manual collation cannot handle this complexity. All of the above overridable behavior exists because it is implemented by each service, specific ad, and copy-paste.

We also need to allow other chromium branches to easily add their own features, or to exclude features beyond their build.

Dependency Management Overview

With that in mind, let's look at how dependency management works. We have a single example of Profiledependencymanager, which is associated with profile creation and destruction. A PKSF is registered by Profiledependencymanager and logged out. Profiledependencymanager's job is to ensure that each service is created and destroyed in a secure manner.

Consider the following example of a three service factory:

alphaservicefactory ::  alphaservicefactory () : Browsercontextkeyedservicefactory ( Profiledependencymanager::  getinstance ()) {}betaservicefactory::  Betaservicefactory () : Browsercontextkeyedservicefactory (Profiledependencymanager::  getinstance ()) { DependsOn (alphaservicefactory::  getinstance ())  }gammaservicefactory::  gammaservicefactory () :  Browsercontextkeyedservicefactory (Profiledependencymanager::  getinstance ()) {     DependsOn (betaservicefactory::  getinstance ()) ;  }

In this simplified code structure, the explicit declaration of dependency means that the only valid creation order for these services is [Alpha, beta, Gamma], the only valid destroy order is [Gamma, Beta, Alpha]. These are the dependencies that you, the user of this framework, must specify.

Behind the scenes, Profiledependencymanager manages the declared dependency relationships, showing a Kahn topological sort, which is applied in createprofileservices () and destroyprofileservices ().

Five min to learn how to convert your code
  1. Let your existing fooservice inherit browsercontextkeyedservice.
  2. if possible, don't let your fooservice get a reference count anymore. Most reference-counted objects that are related to the profile seem to need to use their own data in multithreading because they do not use base::bind/weakptrfactory. (In this case, thread-safe reference counting is necessary, for example, when multithreaded access allows your factory to inherit from Refcountedbrowsercontextkeyedservicefactory, so everything works.) )
  3. build a simple fooservicefactory that inherits from Browsercontextkeyedservicefactory. when a consumer requests Fooservice, your fooservicefactory will be the primary access point.
    1. browsercontextkeyedservice* Browsercontextkeyedservicefactory::buildserviceinstancefor (content::BrowserContext* Context) is the only function required. Passes in a browsercontext handle, returning a valid fooservice.
    2. You can control incognito behavior with Serviceredirectedinincognito () and Servicehasowninstanceinincognito ().
  4. Add your service to the ensurebrowsercontextkeyedservicefactoriesbuilt in *chrome_browser_main_extra_parts_profiles.cc ( ) list *.
  5. understand shutdown behavior. for historical reasons, we have to do two phases of shutdown operation:
    1. Each browsercontextkeyedservice first calls its shutdown () method. Use this method to remove a weak reference to a profile or other service object.
    2. Remove each browsercontextkeyedservice, and run it's destructor. Minimizing the work needs to be done here. Call any *servicefactory::getforprofile () to trigger an assertion in debug mode.
  6. Change each "Profile_->getfooservice ()" Instance to "Fooservicefactory::getforprofile (Profile_)".

If you need examples of these steps above, you can look at these patches:
-r100516: A simple example that adds a new profilekeyedservice. This shows a minimal subclass of Servicefactory.
-R104806:plugin_prefs_factory.h gives an example of how to handle (must) reference counting things. This patch also shows how to move your preferences to your profilekeyedservicefactory.

Debugging tips using dependent abstractions

Chrome has a built-in way to export the profile dependency graph and generate a file in a Graphviz format. When you run Chrome on the command line with the –dump-browser-context-graph tag, Chrome writes the dependency information to your/path/to/profile/ Browser-context-dependencies.dot file. Then you can use Dot to transform this file, Dot is a part of Graphviz:

-Tpng /path/to/profile/browser-context-dependencies.> png-file.png

This will give you an abstract image like the one below (generated on January 23, 2012, click to view larger image):

Shutdown when the crash

If there is a stack like this:

ProfileDependencyManager::AssertProfileWasntDestroyed()ProfileKeyedServiceFactory::GetServiceForProfile()MyServiceFactory::GetForProfile()......OtherService::~OtherService()ProfileKeyedServiceFactory::ProfileDestroyed()ProfileDependencyManager::DestroyProfileServices()ProfileImpl::~ProfileImpl()

The problem is that Otherservice is not properly dependent on myservice. When you use the shutdown () component, the framework triggers an assert.

"Chromium Chinese Document" Profile schema (see the refactoring of Google home)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.