Currently the NetworkDelegate observer callbacks OnNetworkBytesSent and OnNetworkBytesReceived can fire after OnComplete for the same request. This makes it hard to reason about the life-cycle of a request.
Data use callbacks should fire before OnComplete.
An example stack trace for when OnNetworkBytesSent fires before OnComplete:
#6 0x7f6b3c7d6f29 net::LayeredNetworkDelegate::OnNetworkBytesSent()
#7 0x7f6b3c82acad net::NetworkDelegate::NotifyNetworkBytesSent()
#8 0x7f6b3c7d6f49 net::LayeredNetworkDelegate::OnNetworkBytesSent()
#9 0x7f6b3c82acad net::NetworkDelegate::NotifyNetworkBytesSent()
#10 0x7f6b3cfe4c28 net::URLRequestJob::MaybeNotifyNetworkBytes()
#11 0x7f6b3cfe53d5 net::URLRequestJob::NotifyDone()
#12 0x7f6b3cfe2f0e net::URLRequestJob::NotifyCanceled()
#13 0x7f6b3cfe2ebe net::URLRequestJob::Kill()
#14 0x7f6b3cfd7469 net::URLRequestHttpJob::Kill()
#15 0x7f6b3cfac6f6 net::URLRequest::OrphanJob()
#16 0x7f6b3cfac3c2 net::URLRequest::~URLRequest()
#17 0x7f6b3cfac739 net::URLRequest::~URLRequest()
#18 0x7f6b351b544f std::default_delete<>::operator()()
#19 0x7f6b35b7222c std::unique_ptr<>::reset()
#20 0x7f6b35b6c179 std::unique_ptr<>::~unique_ptr()
#21 0x7f6b3621b89d content::ResourceLoader::~ResourceLoader()
#22 0x7f6b3621b959 content::ResourceLoader::~ResourceLoader()
#23 0x7f6b35235a0f std::default_delete<>::operator()()
#24 0x7f6b3620828c std::unique_ptr<>::reset()
#25 0x7f6b361f5739 std::unique_ptr<>::~unique_ptr()
#26 0x7f6b361fcdb9 std::pair<>::~pair()
#27 0x7f6b361fcd99 std::_Rb_tree_node<>::~_Rb_tree_node()
#28 0x7f6b361fcd79 __gnu_cxx::new_allocator<>::destroy()
#29 0x7f6b361fcd4c std::_Rb_tree<>::_M_destroy_node()
#30 0x7f6b361ff4ac std::_Rb_tree<>::_M_erase_aux()
#31 0x7f6b361ff455 std::_Rb_tree<>::erase()
#32 0x7f6b361ff2b5 std::__cxx1998::map<>::erase()
#33 0x7f6b361fefac std::__debug::map<>::erase()
#34 0x7f6b361f105f std::__debug::map<>::erase()
#35 0x7f6b361ecddc content::ResourceDispatcherHostImpl::RemovePendingLoader()
#36 0x7f6b361e4f0e content::ResourceDispatcherHostImpl::RemovePendingRequest()
#37 0x7f6b361e4974 content::ResourceDispatcherHostImpl::DidFinishLoading()
#38 0x7f6b36220aa3 content::ResourceLoader::CallDidFinishLoading()
#39 0x7f6b3621ebb2 content::ResourceLoader::ResponseCompleted()
#40 0x7f6b3621e772 content::ResourceLoader::OnResponseStarted()
#41 0x7f6b3cfac202 net::URLRequest::Delegate::OnResponseStarted()
#42 0x7f6b3cfb2347 net::URLRequest::NotifyResponseStarted()
#43 0x7f6b3cfe5eb8 net::URLRequestJob::NotifyStartError()
#44 0x7f6b3cfd5a6b net::URLRequestHttpJob::OnStartCompleted()
#4 0x7ff026a39fb9 net::LayeredNetworkDelegate::OnCompleted()
#5 0x7ff026a8e23f net::NetworkDelegate::NotifyCompleted()
#6 0x7ff026a39fe4 net::LayeredNetworkDelegate::OnCompleted()
#7 0x7ff026a8e23f net::NetworkDelegate::NotifyCompleted()
#8 0x7ff027214a2e net::URLRequest::NotifyRequestCompleted()
#9 0x7ff027215320 net::URLRequest::NotifyResponseStarted()
#10 0x7ff027248eb8 net::URLRequestJob::NotifyStartError()
#11 0x7ff027238a6b net::URLRequestHttpJob::OnStartCompleted()
#12 0x7ff0269bc39c _ZN4base8internal13FunctorTraitsIMN3net18ClientSocketHandleEFviEvE6InvokeIPS3_JiEEEvS5_OT_DpOT0_
#13 0x7ff027242776 _ZN4base8internal12InvokeHelperILb0EvE8MakeItSoIRKMN3net17URLRequestHttpJobEFviEJPS5_iEEEvOT_DpOT0_
#14 0x7ff027242707 _ZN4base8internal7InvokerINS0_9BindStateIMN3net17URLRequestHttpJobEFviEJNS0_17UnretainedWrapperIS4_EEEEEFviEE7RunImplIRKS6_RKSt5tupleIJS8_EEJLm0EEEEvOT_OT0_NS_13IndexSequenceIJXspT1_EEEEOi
#15 0x7ff02724263c _ZN4base8internal7InvokerINS0_9BindStateIMN3net17URLRequestHttpJobEFviEJNS0_17UnretainedWrapperIS4_EEEEEFviEE3RunEPNS0_13BindStateBaseEOi
#16 0x7ff0269bbd7f base::internal::RunMixin<>::Run()
#17 0x7ff026d4ed84 net::HttpCache::Transaction::DoLoop()
#18 0x7ff026d4cdfb net::HttpCache::Transaction::OnIOComplete()
Comment 1 by bugdroid1@chromium.org
, Nov 8 2016