Chromium網絡請求

Chromium 編譯調試

Chromium Android編譯只支持linux,因此搞了個ubuntu虛擬機(Parallels Desktop,其實mvware也挺好用,不知道爲啥後面上不了網了)python

  1. git clone chromium.googlesource.com/chromium/to…
  2. 配置環境變量 depot_tools對應的下載目錄, 或者執行export PATH="$PATH:/home/test/Donloads/depot_tools"
  3. 拉取源代碼,先切換到chromium目錄 mkdir ~/chromium && cd ~/chromium ,再執行fetch --nohooks android,一共要下載了60多個G內容,除了chromium源碼還有各類第三方庫(最好一次性下載完,斷了後,會從新開始下載,並且會出現各類問題)
  4. 執行gclient sync,先確認過chromium目錄下.gclient文件是否配置了target_os = ["android"],通常執行了第三步,都會自動添加,沒有的話,在最後追加
  5. 源碼下載完成後會在chromium下生成src目錄,cd到該目錄 執行build/install-build-deps-android.sh
  6. gclient runhooks
  7. 設置編譯參數,先執行gn args out/Default,打開out/Default/args.gn文件設置編譯配置,例如
target_os = "android"
target_cpu = "arm"  # See "Figuring out target_cpu" below
is_component_build=true
symbol_level=2
enable_nacl=false
is_debug=true
v8_android_log_stdout=true
複製代碼
  1. 執行ninja -C out/Default chrome_public_apk,開始編譯,確認安裝了python3, 安裝dataclasses pip3 install dataclasses
  2. 編譯過程很是漫長,我這邊花了 14個多小時
  3. 安裝apk(out/Default/apks/ChromePublic.apk)
  4. 打開chromuim,執行 ./out/Default/bin/chrome_public_apk gdb,就能夠進入gdb調試了!!!

網絡請求流程

網絡請求從HttpCache::Transaction::Start開始linux

詳細調用棧
#0  net::HttpCache::Transaction::Start(net::HttpRequestInfo const*, base::OnceCallback<void (int)>, net::NetLogWithSource const&) at ../../net/http/http_cache_transaction.cc:242
#1  0xbd8d9952 in net::URLRequestHttpJob::StartTransactionInternal (this=0xb0f11000) at ../../net/url_request/url_request_http_job.cc:484
#2  0xbd8d9636 in net::URLRequestHttpJob::StartTransaction (this=0xb0f11000) at ../../net/url_request/url_request_http_job.cc:405
#3  0xbd8d9f9c in net::URLRequestHttpJob::SetCookieHeaderAndStart (this=0x9bf7dc00, options=..., cookies_with_access_result_list=..., excluded_list=...) at ../../net/url_request/url_request_http_job.cc:694
#4  0xbd8dc31c in base::internal::InvokeHelper... at ../../base/bind_internal.h:668
#5  0xbd8dc2f6 in base::internal::Invoker... at ../../base/bind_internal.h:721
#6  0xbd7c946c in base::OnceCallback  at ../../base/callback.h:98
#7  0xbd7c4522 in (anonymous namespace)::MaybeRunCookieCallback<...>(base::OnceCallback<void (...)  at ../../net/cookies/cookie_monster.cc:134
#8  net::CookieMonster::GetCookieListWithOptions(...) at ../../net/cookies/cookie_monster.cc:628
#9  0xbd7c818a in base::internal::FunctorTraits<...>::Invoke<void (net::CookieMonster::*), net::CookieMonster*, GURL, net::CookieOptions, base::OnceCallback<void > > (...) at ../../base/bind_internal.h:509
#10 0xbd7c8162 in base::internal::InvokeHelper<false, void>::MakeItSo<void (net::CookieMonster::*)(GURL const&, net::CookieOptions const&, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)>), net::CookieMonster*, GURL, net::CookieOptions, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)> >(void (net::CookieMonster::*&&)(GURL const&, net::CookieOptions const&, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)>), net::CookieMonster*&&, GURL&&, net::CookieOptions&&, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)>&&) (functor=<optimized out>, args=..., args=..., args=..., args=...) at ../../base/bind_internal.h:648
#11 0xbd7c8148 in base::internal::Invoker<base::internal::BindState<void (net::CookieMonster::*)(GURL const&, net::CookieOptions const&, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)>), base::internal::UnretainedWrapper<net::CookieMonster>, GURL, net::CookieOptions, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)> >, void ()>::RunImpl<void (net::CookieMonster::*)(GURL const&, net::CookieOptions const&, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)>), std::__Cr::tuple<base::internal::UnretainedWrapper<net::CookieMonster>, GURL, net::CookieOptions, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)> >, 0u, 1u, 2u, 3u>(void (net::CookieMonster::*&&)(GURL const&, net::CookieOptions const&, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)>), std::__Cr::tuple<base::internal::UnretainedWrapper<net::CookieMonster>, GURL, net::CookieOptions, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)> >&&, std::__Cr::integer_sequence<unsigned int, 0u, 1u, 2u, 3u>) (functor=@0x9bf7dc00: &virtual table offset -1113271444, bound=...) at ../../base/bind_internal.h:721
#12 0xbd796968 in base::OnceCallback<void ()>::Run() && (this=<optimized out>) at ../../base/callback.h:98
#13 0xbd7c3dc8 in net::CookieMonster::DoCookieCallbackForHostOrDomain(base::OnceCallback<void ()>, base::BasicStringPiece<char, std::__Cr::char_traits<char> >) (this=0xc2c99c80, callback=..., host_or_domain=...) at ../../net/cookies/cookie_monster.cc:1908
#14 0xbd7c444a in net::CookieMonster::DoCookieCallbackForURL(base::OnceCallback<void ()>, GURL const&) (this=0x9bf7dc00, callback=..., url=...) at ../../net/cookies/cookie_monster.cc:1869
#15 0xbd7c4418 in net::CookieMonster::GetCookieListWithOptionsAsync(GURL const&, net::CookieOptions const&, base::OnceCallback<void (std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&, std::__Cr::vector<net::CookieWithAccessResult, std::__Cr::allocator<net::CookieWithAccessResult> > const&)>) (this=0x9bf7dc00, url=..., options=..., callback=...) at ../../net/cookies/cookie_monster.cc:402
#16 0xbd8d9124 in net::URLRequestHttpJob::AddCookieHeaderAndStart (this=<optimized out>) at ../../net/url_request/url_request_http_job.cc:597
#17 0xbd8d8dce in net::URLRequestHttpJob::Start (this=0x9bf7dc00) at ../../net/url_request/url_request_http_job.cc:316
#18 0xbd8d3bb6 in net::URLRequest::StartJob (this=0xa2952c00, job=...) at ../../net/url_request/url_request.cc:685
#19 0xbd8d3908 in net::URLRequest::BeforeRequestComplete (this=0x9bf7dc00, error=0) at ../../net/url_request/url_request.cc:602
#20 0xbd8d3786 in net::URLRequest::Start (this=0x9bf7dc00) at ../../net/url_request/url_request.cc:534
#21 0xb450109c in network::URLLoader::ScheduleStart (this=0xb1b88080) at ../../services/network/url_loader.cc:914
#22 0xb44ffda0 in network::URLLoader::URLLoader(net::URLRequestContext*, network::URLLoaderFactory*, network::mojom::NetworkContextClient*, base::OnceCallback<void (network::mojom::URLLoader*)>, mojo::PendingReceiver<network::mojom::URLLoader>, int, network::ResourceRequest const&, mojo::PendingRemote<network::mojom::URLLoaderClient>, net::NetworkTrafficAnnotationTag const&, network::mojom::URLLoaderFactoryParams const*, network::mojom::CrossOriginEmbedderPolicyReporter*, unsigned int, int, bool, scoped_refptr<network::ResourceSchedulerClient>, base::WeakPtr<network::KeepaliveStatisticsRecorder>, network::mojom::TrustedURLLoaderHeaderClient*, network::mojom::OriginPolicyManager*, std::__Cr::unique_ptr<network::TrustTokenRequestHelperFactory, std::__Cr::default_delete<network::TrustTokenRequestHelperFactory> >, network::cors::OriginAccessList const&, mojo::PendingRemote<network::mojom::CookieAccessObserver>, mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>, mojo::PendingRemote<network::mojom::DevToolsObserver>, mojo::PendingRemote<network::mojom::AcceptCHFrameObserver>) (this=0xb1b88080, url_request_context=<optimized out>, url_loader_factory=<optimized out>, network_context_client=<optimized out>, delete_callback=..., url_loader_receiver=..., options=0, request=..., url_loader_client=..., traffic_annotation=..., factory_params=0xa297a080, coep_reporter=0x0, request_id=0, keepalive_request_size=0, require_network_isolation_key=true, resource_scheduler_client=scoped_refptr((network::ResourceSchedulerClient *)0x0), keepalive_statistics_recorder=base::WeakPtr((uintptr_t)0), url_loader_header_client=0x0, origin_policy_manager=0xb1bd8b80, trust_token_helper_factory=..., origin_access_list=..., cookie_observer=..., url_loader_network_observer=..., devtools_observer=..., accept_ch_frame_observer=...) at ../../services/network/url_loader.cc:654
#23 0xb4509bca in std::__Cr::make_unique<network::URLLoader, net::URLRequestContext*, network::URLLoaderFactory*, network::mojom::NetworkContextClient*, base::OnceCallback<void (network::mojom::URLLoader*)>, mojo::PendingReceiver<network::mojom::URLLoader>, unsigned int&, network::ResourceRequest const&, mojo::PendingRemote<network::mojom::URLLoaderClient>, net::NetworkTrafficAnnotationTag, network::mojom::URLLoaderFactoryParams*, network::mojom::CrossOriginEmbedderPolicyReporterProxy*, int&, int&, bool, scoped_refptr<network::ResourceSchedulerClient>&, base::WeakPtr<network::KeepaliveStatisticsRecorder>, network::mojom::TrustedURLLoaderHeaderClientProxy*, network::mojom::OriginPolicyManager*, std::__Cr::unique_ptr<network::TrustTokenRequestHelperFactory, std::__Cr::default_delete<network::TrustTokenRequestHelperFactory> >, network::cors::OriginAccessList const&, mojo::PendingRemote<network::mojom::CookieAccessObserver>, mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>, mojo::PendingRemote<network::mojom::DevToolsObserver>, mojo::PendingRemote<network::mojom::AcceptCHFrameObserver> >(net::URLRequestContext*&&, network::URLLoaderFactory*&&, network::mojom::NetworkContextClient*&&, base::OnceCallback<void (network::mojom::URLLoader*)>&&, mojo::PendingReceiver<network::mojom::URLLoader>&&, unsigned int&, network::ResourceRequest const&, mojo::PendingRemote<network::mojom::URLLoaderClient>&&, net::NetworkTrafficAnnotationTag&&, network::mojom::URLLoaderFactoryParams*&&, network::mojom::CrossOriginEmbedderPolicyReporterProxy*&&, int&, int&, bool&&, scoped_refptr<network::ResourceSchedulerClient>&, base::WeakPtr<network::KeepaliveStatisticsRecorder>&&, network::mojom::TrustedURLLoaderHeaderClientProxy*&&, network::mojom::OriginPolicyManager*&&, std::__Cr::unique_ptr<network::TrustTokenRequestHelperFactory, std::__Cr::default_delete<network::TrustTokenRequestHelperFactory> >&&, network::cors::OriginAccessList const&, mojo::PendingRemote<network::mojom::CookieAccessObserver>&&, mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>&&, mojo::PendingRemote<network::mojom::DevToolsObserver>&&, mojo::PendingRemote<network::mojom::AcceptCHFrameObserver>&&) (__args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=..., __args=...) at ../../buildtools/third_party/libc++/trunk/include/__memory/unique_ptr.h:725
#24 0xb4509806 in network::URLLoaderFactory::CreateLoaderAndStart (this=0xa1e4d200, receiver=..., request_id=0, options=0, url_request=..., client=..., traffic_annotation=...) at ../../services/network/url_loader_factory.cc:238
#25 0xb44b4c02 in network::cors::CorsURLLoader::StartNetworkRequest (this=0xc9432c00, error_code=<optimized out>, status=..., has_authorization_covered_by_wildcard=<optimized out>) at ../../services/network/cors/cors_url_loader.cc:545
#26 0xb44b3638 in network::cors::CorsURLLoader::StartRequest (this=0x9bf7dc00) at ../../services/network/cors/cors_url_loader.cc:490
#27 0xb44b3436 in network::cors::CorsURLLoader::Start (this=0x9bf7dc00) at ../../services/network/cors/cors_url_loader.cc:126
#28 0xb44b6c5a in network::cors::CorsURLLoaderFactory::CreateLoaderAndStart (this=<optimized out>, receiver=..., request_id=0, options=0, resource_request=..., client=..., traffic_annotation=...) at ../../services/network/cors/cors_url_loader_factory.cc:291
#29 0xb458cb38 in network::mojom::URLLoaderFactoryStubDispatch::Accept (impl=0x9bf7dc00, message=<optimized out>) at gen/services/network/public/mojom/url_loader_factory.mojom.cc:238
#30 0xbd1622f6 in mojo::InterfaceEndpointClient::HandleValidatedMessage (this=0xa2041500, message=0xa31fab28) at ../../mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:898
#31 0xbd166188 in mojo::MessageDispatcher::Accept (this=0xa20415a4, message=0xa31fab28) at ../../mojo/public/cpp/bindings/lib/message_dispatcher.cc:48
#32 0xbd162f96 in mojo::InterfaceEndpointClient::HandleIncomingMessage (this=0xa2041500, message=0xa31fab28) at ../../mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:655
#33 0xbd168ac0 in mojo::internal::MultiplexRouter::ProcessIncomingMessage (this=0xa297ad00, message_wrapper=0xa31fac0c, client_call_behavior=mojo::internal::MultiplexRouter::ALLOW_DIRECT_CLIENT_CALLS, current_task_runner=<optimized out>) at ../../mojo/public/cpp/bindings/lib/multiplex_router.cc:1099
#34 0xbd1687bc in mojo::internal::MultiplexRouter::Accept (this=0xa297ad00, message=0xa31fad48) at ../../mojo/public/cpp/bindings/lib/multiplex_router.cc:719
#35 0xbd1661ae in mojo::MessageDispatcher::Accept (this=0xa297ad24, message=0xa31fad48) at ../../mojo/public/cpp/bindings/lib/message_dispatcher.cc:43
#36 0xbd15e134 in mojo::Connector::DispatchMessage (this=0xa297ad3c, message=...) at ../../mojo/public/cpp/bindings/lib/connector.cc:546
#37 0xbd15e704 in mojo::Connector::ReadAllAvailableMessages (this=0xa297ad3c) at ../../mojo/public/cpp/bindings/lib/connector.cc:604
#38 0xbd15e5e0 in mojo::Connector::OnHandleReadyInternal (this=0x9bf7dc00, result=0) at ../../mojo/public/cpp/bindings/lib/connector.cc:439
#39 0xbd15f26e in base::internal::Invoker<base::internal::BindState<void (mojo::Connector::*)(unsigned int), base::internal::UnretainedWrapper<mojo::Connector> >, void (unsigned int)>::RunImpl<void (mojo::Connector::* const&)(unsigned int), std::__Cr::tuple<base::internal::UnretainedWrapper<mojo::Connector> > const&, 0u>(void (mojo::Connector::* const&)(unsigned int), std::__Cr::tuple<base::internal::UnretainedWrapper<mojo::Connector> > const&, std::__Cr::integer_sequence<unsigned int, 0u>, unsigned int&&) (functor=@0x9bf7dc00: &virtual table offset -1113271444, bound=..., unbound_args=@0xa31f90f0: 2737913856) at ../../base/bind_internal.h:721
#40 0xbd15f260 in base::internal::Invoker<base::internal::BindState<void (mojo::Connector::*)(unsigned int), base::internal::UnretainedWrapper<mojo::Connector> >, void (unsigned int)>::Run(base::internal::BindStateBase*, unsigned int) (base=<optimized out>, unbound_args=0) at ../../base/bind_internal.h:703
#41 0xbdaf3420 in mojo::SimpleWatcher::OnHandleReady (this=0xb1bf8bf8, watch_id=<optimized out>, result=0, state=...) at ../../mojo/public/cpp/system/simple_watcher.cc:278
#42 0xbdaf378e in base::internal::InvokeHelper<true, void>::MakeItSo<void (mojo::SimpleWatcher::*)(int, unsigned int, mojo::HandleSignalsState const&), base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState> (functor=@0xa1dcf69c: (void (mojo::SimpleWatcher::*)(mojo::SimpleWatcher * const, int, unsigned int, const mojo::HandleSignalsState &)) 0xbdaf33b1 <mojo::SimpleWatcher::OnHandleReady(int, unsigned int, mojo::HandleSignalsState const&)>, weak_ptr=base::WeakPtr((uintptr_t)2982120440), args=..., args=..., args=...) at ../../base/bind_internal.h:668
#43 0xbdaf3768 in base::internal::Invoker<base::internal::BindState<void (mojo::SimpleWatcher::*)(int, unsigned int, mojo::HandleSignalsState const&), base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>, void ()>::RunImpl<void (mojo::SimpleWatcher::*)(int, unsigned int, mojo::HandleSignalsState const&), std::__Cr::tuple<base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>, 0u, 1u, 2u, 3u>(void (mojo::SimpleWatcher::*&&)(int, unsigned int, mojo::HandleSignalsState const&), std::__Cr::tuple<base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>&&, std::__Cr::integer_sequence<unsigned int, 0u, 1u, 2u, 3u>) (functor=@0x9bf7dc00: &virtual table offset -1113271444, bound=...) at ../../base/bind_internal.h:721
#44 0xbdd45af0 in base::OnceCallback<void ()>::Run() && (this=<optimized out>) at ../../base/callback.h:98
#45 0xbdda24ce in base::TaskAnnotator::RunTask (this=<optimized out>, trace_event_name=<optimized out>, pending_task=0x9bf7dc00) at ../../base/task/common/task_annotator.cc:178
#46 0xbddb2362 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl (this=0xb0e3ba40, continuation_lazy_now=<optimized out>) at ../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:360
#47 0xbddb2156 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork (this=0xb0e3ba40) at ../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:260
#48 0xbddb2624 in non-virtual thunk to base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() () at ../../buildtools/third_party/libc++/trunk/include/__memory/unique_ptr.h:725
#49 0xbde108f0 in base::MessagePumpLibevent::Run (this=0xb1bf69d8, delegate=0xb0e3ba44) at ../../base/message_loop/message_pump_libevent.cc:207
#50 0xbddb2808 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run (this=0xb0e3ba40, application_tasks_allowed=true, timeout=...) at ../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:467
#51 0xbdd8bc42 in base::RunLoop::Run (this=0xa31fb1bc, location=...) at ../../base/run_loop.cc:134
#52 0xbddcd084 in base::Thread::Run (this=<optimized out>, run_loop=0x9bf7dc00) at ../../base/threading/thread.cc:341
#53 0xbddcd284 in base::Thread::ThreadMain (this=0xa9ae7148 <content::(anonymous namespace)::GetNetworkServiceDedicatedThread()::thread>) at ../../base/threading/thread.cc:412
#54 0xbdde7062 in base::(anonymous namespace)::ThreadFunc (params=<optimized out>) at ../../base/threading/platform_thread_posix.cc:95
#55 0xed42709c in __pthread_start(void*) () from /tmp/adb-gdb-support-didi/23064bed-/apex/com.android.runtime/lib/bionic/libc.so
#56 0xed3de114 in __start_thread () from /tmp/adb-gdb-support-didi/23064bed-/apex/com.android.runtime/lib/bionic/libc.so

複製代碼
int HttpCache::Transaction::Start(const HttpRequestInfo* request,
                                  CompletionOnceCallback callback,
                                  const NetLogWithSource& net_log) {
  ...
  if (!cache_.get())
    return ERR_UNEXPECTED;

  initial_request_ = request;
  SetRequest(net_log);

  // We have to wait until the backend is initialized so we start the SM.
  next_state_ = STATE_GET_BACKEND;
  //1
  int rv = DoLoop(OK);
  ...
}

複製代碼

1處開啓循環,HttpCache的傳輸過程也是狀態改變的過程,所謂的狀態機的形式

DoLoop註釋,狀態變化的描述android

//-----------------------------------------------------------------------------

// A few common patterns: (Foo* means Foo -> FooComplete)
//
// 1. Not-cached entry:
//   Start():
//   GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
//   SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
//   CacheWriteResponse* -> TruncateCachedData* -> PartialHeadersReceived ->
//   FinishHeaders*
//
//   Read():
//   NetworkReadCacheWrite*/CacheReadData* (if other writers are also writing to
//   the cache)
//
// 2. Cached entry, no validation:
//   Start():
//   GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
//   CacheReadResponse* -> CacheDispatchValidation ->
//   BeginPartialCacheValidation() -> BeginCacheValidation() ->
//   SetupEntryForRead() -> FinishHeaders*
//
//   Read():
//   CacheReadData*
//
// 3. Cached entry, validation (304):
//   Start():
//   GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
//   CacheReadResponse* -> CacheDispatchValidation ->
//   BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
//   SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteUpdatedResponse*
//   -> UpdateCachedResponseComplete -> OverwriteCachedResponse ->
//   PartialHeadersReceived -> FinishHeaders*
//
//   Read():
//   CacheReadData*
//
// 4. Cached entry, validation and replace (200):
//   Start():
//   GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
//   CacheReadResponse* -> CacheDispatchValidation ->
//   BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
//   SuccessfulSendRequest -> OverwriteCachedResponse -> CacheWriteResponse* ->
//   DoTruncateCachedData* -> PartialHeadersReceived -> FinishHeaders*
//
//   Read():
//   NetworkReadCacheWrite*/CacheReadData* (if other writers are also writing to
//   the cache)
//
// 5. Sparse entry, partially cached, byte range request:
//   Start():
//   GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
//   CacheReadResponse* -> CacheDispatchValidation ->
//   BeginPartialCacheValidation() -> CacheQueryData* ->
//   ValidateEntryHeadersAndContinue() -> StartPartialCacheValidation ->
//   CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
//   SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteUpdatedResponse*
//   -> UpdateCachedResponseComplete -> OverwriteCachedResponse ->
//   PartialHeadersReceived -> FinishHeaders*
//
//   Read() 1:
//   NetworkReadCacheWrite*
//
//   Read() 2:
//   NetworkReadCacheWrite* -> StartPartialCacheValidation ->
//   CompletePartialCacheValidation -> CacheReadData* ->
//
//   Read() 3:
//   CacheReadData* -> StartPartialCacheValidation ->
//   CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
//   SuccessfulSendRequest -> UpdateCachedResponse* -> OverwriteCachedResponse
//   -> PartialHeadersReceived -> NetworkReadCacheWrite*
//
// 6. HEAD. Not-cached entry:
//   Pass through. Don't save a HEAD by itself.
//   Start():
//   GetBackend* -> InitEntry -> OpenOrCreateEntry* -> SendRequest*
//
// 7. HEAD. Cached entry, no validation:
//   Start():
//   The same flow as for a GET request (example #2)
//
//   Read():
//   CacheReadData (returns 0)
//
// 8. HEAD. Cached entry, validation (304):
//   The request updates the stored headers.
//   Start(): Same as for a GET request (example #3)
//
//   Read():
//   CacheReadData (returns 0)
//
// 9. HEAD. Cached entry, validation and replace (200):
//   Pass through. The request dooms the old entry, as a HEAD won't be stored by
//   itself.
//   Start():
//   GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
//   CacheReadResponse* -> CacheDispatchValidation ->
//   BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
//   SuccessfulSendRequest -> OverwriteCachedResponse -> FinishHeaders*
//
// 10. HEAD. Sparse entry, partially cached:
//   Serve the request from the cache, as long as it doesn't require
//   revalidation. Ignore missing ranges when deciding to revalidate. If the
//   entry requires revalidation, ignore the whole request and go to full pass
//   through (the result of the HEAD request will NOT update the entry).
//
//   Start(): Basically the same as example 7, as we never create a partial_
//   object for this request.
//
// 11. Prefetch, not-cached entry:
//   The same as example 1. The "unused_since_prefetch" bit is stored as true in
//   UpdateCachedResponse.
//
// 12. Prefetch, cached entry:
//   Like examples 2-4, only CacheWriteUpdatedPrefetchResponse* is inserted
//   between CacheReadResponse* and CacheDispatchValidation if the
//   unused_since_prefetch bit is unset.
//
// 13. Cached entry less than 5 minutes old, unused_since_prefetch is true:
//   Skip validation, similar to example 2.
//   GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
//   CacheReadResponse* -> CacheToggleUnusedSincePrefetch* ->
//   CacheDispatchValidation -> BeginPartialCacheValidation() ->
//   BeginCacheValidation() -> SetupEntryForRead() -> FinishHeaders*
//
//   Read():
//   CacheReadData*
//
// 14. Cached entry more than 5 minutes old, unused_since_prefetch is true:
//   Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between
//   CacheReadResponse* and CacheDispatchValidation.

複製代碼

接下來咱們大概走一走nocache的鏈路c++

// nocache狀態機請求部分
int HttpCache::Transaction::DoLoop(int result) {
do {
    state = next_state_;
    switch (state) {
      case STATE_GET_BACKEND:
        DCHECK_EQ(OK, rv);
        rv = DoGetBackend();
        break;
      case STATE_INIT_ENTRY:
        DCHECK_EQ(OK, rv);
        rv = DoInitEntry();
        break;
      case STATE_OPEN_OR_CREATE_ENTRY:
        DCHECK_EQ(OK, rv);
        rv = DoOpenOrCreateEntry();
        break;
      case STATE_ADD_TO_ENTRY:
        DCHECK_EQ(OK, rv);
        rv = DoAddToEntry();
        break;  
      case STATE_SEND_REQUEST:
        DCHECK_EQ(OK, rv);
        rv = DoSendRequest();
        break;
      case STATE_SUCCESSFUL_SEND_REQUEST:
        DCHECK_EQ(OK, rv);
        rv = DoSuccessfulSendRequest();
        break;
      case STATE_OVERWRITE_CACHED_RESPONSE:
        DCHECK_EQ(OK, rv);
        rv = DoOverwriteCachedResponse();
        break;
      case STATE_CACHE_WRITE_RESPONSE:
        DCHECK_EQ(OK, rv);
        rv = DoCacheWriteResponse();
        break;
      case STATE_TRUNCATE_CACHED_DATA:
        DCHECK_EQ(OK, rv);
        rv = DoTruncateCachedData();
        break;
      case STATE_PARTIAL_HEADERS_RECEIVED:
        DCHECK_EQ(OK, rv);
        rv = DoPartialHeadersReceived();
        break;
      case STATE_FINISH_HEADERS:
        rv = DoFinishHeaders(rv);
        break;
        ...
    }while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
}
複製代碼

GetBackend,獲取disk_cache(Backend本地持久化實現)git

int HttpCache::Transaction::DoGetBackend() {
  cache_pending_ = true;
  TransitionToState(STATE_GET_BACKEND_COMPLETE);
  net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_GET_BACKEND);
  return cache_->GetBackendForTransaction(this);
}
複製代碼

DoInitEntry(切換狀態)web

int HttpCache::Transaction::DoInitEntry() {
  ...
  if (mode_ == WRITE) {
    TransitionToState(STATE_DOOM_ENTRY);
    return OK;
  }

 // 切換到DoOpenOrCreateEntry
  TransitionToState(STATE_OPEN_OR_CREATE_ENTRY);
  return OK;
}
複製代碼

DoOpenOrCreateEntry(建立一個,緩存實例Entry)chrome

int HttpCache::Transaction::DoOpenOrCreateEntry() {
  // 嘗試獲取entry
  new_entry_ = cache_->FindActiveEntry(cache_key_);
  if (new_entry_)
   return OK;
   ...
  // cache_key_ 對應資源url連接
  return cache_->OpenOrCreateEntry(cache_key_, &new_entry_, this);
}
複製代碼

打印cache_key_內容 image.png DoAddToEntry(設置entry)ubuntu

int HttpCache::Transaction::DoAddToEntry() {
  ...
  int rv = cache_->AddTransactionToEntry(new_entry_, this);
  DCHECK_EQ(rv, ERR_IO_PENDING);

  // If headers phase is already done then we are here because of validation not
  // matching and creating a new entry. This transaction should be the
  // first transaction of that new entry and thus it will not have cache lock
  // delays, thus returning early from here.
  if (done_headers_create_new_entry_) {
    DCHECK_EQ(mode_, WRITE);
    TransitionToState(STATE_DONE_HEADERS_ADD_TO_ENTRY_COMPLETE);
    return rv;
  }

  TransitionToState(STATE_ADD_TO_ENTRY_COMPLETE);

  entry_lock_waiting_since_ = TimeTicks::Now();
  AddCacheLockTimeoutHandler(new_entry_);
  return rv;
}

複製代碼

DoSendRequest發出請求緩存

int HttpCache::Transaction::DoSendRequest() {
  send_request_since_ = TimeTicks::Now();
  // Create a network transaction.
  int rv =
      cache_->network_layer_->CreateTransaction(priority_, &network_trans_);
  // 設置一堆回調
  network_trans_->SetBeforeNetworkStartCallback(
      std::move(before_network_start_callback_));
  network_trans_->SetConnectedCallback(connected_callback_);
  network_trans_->SetRequestHeadersCallback(request_headers_callback_);
  network_trans_->SetEarlyResponseHeadersCallback(
      early_response_headers_callback_);
  network_trans_->SetResponseHeadersCallback(response_headers_callback_);

  // Old load timing information, if any, is now obsolete.
  network_transaction_info_.old_network_trans_load_timing.reset();
  network_transaction_info_.old_remote_endpoint = IPEndPoint();

  if (websocket_handshake_stream_base_create_helper_)
    network_trans_->SetWebSocketHandshakeStreamCreateHelper(
        websocket_handshake_stream_base_create_helper_);

  TransitionToState(STATE_SEND_REQUEST_COMPLETE);
  // 開始網絡請求
  rv = network_trans_->Start(request_, io_callback_, net_log_);
  return rv;
}
複製代碼

DoSuccessfulSendRequest(網絡請求響應過程)websocket

// We received the response headers and there is no error.
int HttpCache::Transaction::DoSuccessfulSendRequest() {
  TRACE_EVENT0("io", "HttpCacheTransaction::DoSuccessfulSendRequest");
  DCHECK(!new_response_);
  const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();

  if (new_response->headers->response_code() == 401 ||
      new_response->headers->response_code() == 407) {
    SetAuthResponse(*new_response);
    if (!reading_) {
      TransitionToState(STATE_FINISH_HEADERS);
      return OK;
    }

  new_response_ = new_response;
  if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
    // We have stored the full entry, but it changed and the server is
    // sending a range. We have to delete the old entry.
    UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
    DoneWithEntry(false);
  }

  if (mode_ == WRITE &&
      cache_entry_status_ != CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) {
    UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_NOT_IN_CACHE);
  }

  // Invalidate any cached GET with a successful PUT, DELETE, or PATCH.
  if (mode_ == WRITE &&
      (method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH")) {
    if (NonErrorResponse(new_response_->headers->response_code()) &&
        (entry_ && !entry_->doomed)) {
      int ret = cache_->DoomEntry(cache_key_, nullptr);
      DCHECK_EQ(OK, ret);
    }
    // Do not invalidate the entry if the request failed.
    DoneWithEntry(true);
  }

  // Invalidate any cached GET with a successful POST. If the network isolation
  // key isn't populated with the split cache active, there will be nothing to
  // invalidate in the cache.
  if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) && method_ == "POST" &&
      NonErrorResponse(new_response_->headers->response_code()) &&
      (!HttpCache::IsSplitCacheEnabled() ||
       request_->network_isolation_key.IsFullyPopulated())) {
    cache_->DoomMainEntryForUrl(request_->url, request_->network_isolation_key,
                                request_->is_subframe_document_resource);
  }

  RecordNoStoreHeaderHistogram(request_->load_flags, new_response_);

  if (new_response_->headers->response_code() == 416 &&
      (method_ == "GET" || method_ == "POST")) {
    // If there is an active entry it may be destroyed with this transaction.
    SetResponse(*new_response_);
    TransitionToState(STATE_FINISH_HEADERS);
    return OK;
  }

  // Are we expecting a response to a conditional query?
  if (mode_ == READ_WRITE || mode_ == UPDATE) {
    if (new_response->headers->response_code() == 304 || handling_206_) {
      UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED);
      TransitionToState(STATE_UPDATE_CACHED_RESPONSE);
      return OK;
    }
    UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED);
    mode_ = WRITE;
  }

  TransitionToState(STATE_OVERWRITE_CACHED_RESPONSE);
  return OK;
}

複製代碼

DoCacheWriteResponse(response持久化)

int HttpCache::Transaction::DoCacheWriteResponse() {
  TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse");
  TransitionToState(STATE_CACHE_WRITE_RESPONSE_COMPLETE);
  
  // 緩存response
  return WriteResponseInfoToEntry(response_, truncated_);
}

int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
  ...
  緩存過濾
  // Do not cache no-store content.  Do not cache content with cert errors
  // either.  This is to prevent not reporting net errors when loading a
  // resource from the cache.  When we load a page over HTTPS with a cert error
  // we show an SSL blocking page.  If the user clicks proceed we reload the
  // resource ignoring the errors.  The loaded resource is then cached.  If that
  // resource is subsequently loaded from the cache, no net error is reported
  // (even though the cert status contains the actual errors) and no SSL
  // blocking page is shown.  An alternative would be to reverse-map the cert
  // status to a net error and replay the net error.
  if ((response.headers->HasHeaderValue("cache-control", "no-store")) ||
      IsCertStatusError(response.ssl_info.cert_status) ||
      ShouldDisableCaching(response.headers.get())) {
    if (partial_)
      partial_->FixResponseHeaders(response_.headers.get(), true);

    bool stopped = StopCachingImpl(false);
    DCHECK(stopped);
    if (net_log_.IsCapturing())
      net_log_.EndEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO);
    return OK;
  }
  io_buf_len_ = data->pickle()->size();
  // 持久化
  return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
                                       io_buf_len_, io_callback_, true);
}

int SimpleEntryImpl::WriteData(int stream_index,
                               int offset,
                               net::IOBuffer* buf,
                               int buf_len,
                               CompletionOnceCallback callback,
                               bool truncate) {
  ...
  // 寫入數據,默認最大緩存大小209715200
  // Stream 0 data is kept in memory, so can be written immediatly if there are
  // no IO operations pending.
  if (stream_index == 0 && state_ == STATE_READY &&
      pending_operations_.size() == 0)
    return SetStream0Data(buf, offset, buf_len, truncate);
  ...  
}

複製代碼

一個HttpCache::Transaction對應一次請求的處理,內部經過狀態切換,實現整個網絡請求過程。

相關文章
相關標籤/搜索