URLRequestFileJob

文件资源的加载过程

URLRequestFileJob

我们在浏览器的地址栏中输入一个文件的绝对路径,激发浏览器获取加载这个文件的内容。在net层,实际的请求是通过URLRequestFileJob来控制和加载文件的工作

启动

0:021> kL
 # Child-SP          RetAddr           Call Site
00 00000000`0566def8 000007fe`eef50ead chrome_7feee360000!net::URLRequestFileJob::Start
01 00000000`0566df00 000007fe`eef4e675 chrome_7feee360000!net::URLRequest::StartJob+0x2c1
02 00000000`0566e210 000007fe`eef50b6c chrome_7feee360000!net::URLRequest::BeforeRequestComplete+0x1d5
03 00000000`0566e340 000007fe`ef5089e3 chrome_7feee360000!net::URLRequest::Start+0x160
04 00000000`0566e490 000007fe`ef5086f5 chrome_7feee360000!content::ResourceLoader::StartRequestInternal+0x27
05 00000000`0566e4c0 000007fe`ef5151b9 chrome_7feee360000!content::ResourceLoader::Resume+0x2a5
06 00000000`0566e5e0 000007fe`ef514f1c chrome_7feee360000!content::ThrottlingResourceHandler::ResumeStart+0x89
07 00000000`0566e720 000007fe`f061affa chrome_7feee360000!content::ThrottlingResourceHandler::Resume+0x60
08 (Inline Function) --------`-------- chrome_7feee360000!base::internal::RunnableAdapter<void (__cdecl extensions::NativeMessageProcessHost::*)(int)>::Run+0xe
09 (Inline Function) --------`-------- chrome_7feee360000!base::internal::InvokeHelper<1,void,base::internal::RunnableAdapter<void (__cdecl extensions::NativeMessageProcessHost::*)(int)> >::MakeItSo+0x33
0a 00000000`0566e750 000007fe`eeca58bc chrome_7feee360000!base::internal::Invoker<base::IndexSequence<0>,base::internal::BindState<base::internal::RunnableAdapter<void (__cdecl extensions::NativeMessageProcessHost::*)(int) __ptr64>,void __cdecl(extensions::NativeMessageProcessHost * __ptr64,int),base::WeakPtr<extensions::NativeMessageProcessHost> >,base::internal::InvokeHelper<1,void,base::internal::RunnableAdapter<void (__cdecl extensions::NativeMessageProcessHost::*)(int) __ptr64> >,void __cdecl(int const & __ptr64)>::Run+0x5e
0b (Inline Function) --------`-------- chrome_7feee360000!base::Callback<void __cdecl(std::list<content::IndexedDBInfo,std::allocator<content::IndexedDBInfo> > const &)>::Run+0xd
0c (Inline Function) --------`-------- chrome_7feee360000!base::internal::InvokeHelper<0,void,base::Callback<void __cdecl(std::list<content::IndexedDBInfo,std::allocator<content::IndexedDBInfo> > const &)> >::MakeItSo+0xd
0d 00000000`0566e790 000007fe`ee402ead chrome_7feee360000!base::internal::Invoker<base::IndexSequence<0>,base::internal::BindState<base::Callback<void __cdecl(std::list<content::IndexedDBInfo,std::allocator<content::IndexedDBInfo> > const & __ptr64)>,void __cdecl(std::list<content::IndexedDBInfo,std::allocator<content::IndexedDBInfo> > const & __ptr64),std::list<content::IndexedDBInfo,std::allocator<content::IndexedDBInfo> > & __ptr64>,base::internal::InvokeHelper<0,void,base::Callback<void __cdecl(std::list<content::IndexedDBInfo,std::allocator<content::IndexedDBInfo> > const & __ptr64)> >,void __cdecl(void)>::Run+0x24
0e (Inline Function) --------`-------- chrome_7feee360000!base::Callback<void __cdecl(void)>::Run+0x8
0f 00000000`0566e7d0 000007fe`ee39eb95 chrome_7feee360000!base::debug::TaskAnnotator::RunTask+0x13d
10 00000000`0566e8b0 000007fe`ee39f6d4 chrome_7feee360000!base::MessageLoop::RunTask+0x3f5
11 (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::DeferOrRunPendingTask+0x147
12 00000000`0566f990 000007fe`ee40226a chrome_7feee360000!base::MessageLoop::DoWork+0x484
13 00000000`0566fb60 000007fe`ee401732 chrome_7feee360000!base::MessagePumpForIO::DoRunLoop+0xaa
14 00000000`0566fb90 000007fe`ee3edd83 chrome_7feee360000!base::MessagePumpWin::Run+0x42
15 (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::RunHandler+0x15
16 00000000`0566fbd0 000007fe`ee3c4381 chrome_7feee360000!base::RunLoop::Run+0x83
17 (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::Run+0x35
18 00000000`0566fc20 000007fe`ef3d84fa chrome_7feee360000!base::Thread::Run+0x41
19 00000000`0566fc80 000007fe`ef3d8cfd chrome_7feee360000!content::BrowserThreadImpl::IOThreadRun+0x36
1a 00000000`0566fdd0 000007fe`ee3c46d8 chrome_7feee360000!content::BrowserThreadImpl::Run+0x89
1b 00000000`0566fe00 000007fe`ee3d7e9d chrome_7feee360000!base::Thread::ThreadMain+0x338
1c 00000000`0566fe70 00000000`76ed652d chrome_7feee360000!base::`anonymous namespace'::ThreadFunc+0x15d
1d 00000000`0566fee0 00000000`7710c541 kernel32!BaseThreadInitThunk+0xd
1e 00000000`0566ff10 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

在content层有个ResourceLoader类,负责content的各种类型数据的加载,这里分析文件的加载,文件的加载比较简单,但也是五脏俱全,通过文件的加载的简要了解来进一步去了解http资源的加载,为其做一个铺垫

class NET_EXPORT URLRequestFileJob : public URLRequestJob {
·····
}

所有的资源加载job都是继承自URLRequestJob,进行资源加载的具体操作。

void URLRequestFileJob::Start() {
  FileMetaInfo* meta_info = new FileMetaInfo();
  file_task_runner_->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&URLRequestFileJob::FetchMetaInfo, file_path_,
                 base::Unretained(meta_info)),
      base::Bind(&URLRequestFileJob::DidFetchMetaInfo,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Owned(meta_info)));
}

对于文件加载来说,上层启动我们的文件加载,在启动的函数中,我们创建文件元信息,接着想任务线程投递任务。

本身URLRequestFileJob::Start就运行在IO线程中,为了不堵塞IO线程,将文件信息的获取任务投递到一个浏览器的工作线程中去
这里使用了PostTaskAndReply函数来设置完成回调。

void URLRequestFileJob::FetchMetaInfo(const base::FilePath& file_path,
                                      FileMetaInfo* meta_info) {
  base::File::Info file_info;
  meta_info->file_exists = base::GetFileInfo(file_path, &file_info);
  if (meta_info->file_exists) {
    meta_info->file_size = file_info.size;
    meta_info->is_directory = file_info.is_directory;
  }
  // On Windows GetMimeTypeFromFile() goes to the registry. Thus it should be
  // done in WorkerPool.
  meta_info->mime_type_result = GetMimeTypeFromFile(file_path,
                                                    &meta_info->mime_type);
}

启动的开始,进行了文件元信息的获取,包括文件长度与是否存在,是否是个路径,等等信息。
获取结束后调用我们的回调函数

void URLRequestFileJob::DidFetchMetaInfo(const FileMetaInfo* meta_info) {
  meta_info_ = *meta_info;

  // We use URLRequestFileJob to handle files as well as directories without
  // trailing slash.
  // If a directory does not exist, we return ERR_FILE_NOT_FOUND. Otherwise,
  // we will append trailing slash and redirect to FileDirJob.
  // A special case is "\" on Windows. We should resolve as invalid.
  // However, Windows resolves "\" to "C:\", thus reports it as existent.
  // So what happens is we append it with trailing slash and redirect it to
  // FileDirJob where it is resolved as invalid.
  if (!meta_info_.file_exists) {
    DidOpen(ERR_FILE_NOT_FOUND);
    return;
  }
  if (meta_info_.is_directory) {
    DidOpen(OK);
    return;
  }

  int flags = base::File::FLAG_OPEN |
              base::File::FLAG_READ |
              base::File::FLAG_ASYNC;
  int rv = stream_->Open(file_path_, flags,
                         base::Bind(&URLRequestFileJob::DidOpen,
                                    weak_ptr_factory_.GetWeakPtr()));
  if (rv != ERR_IO_PENDING)
    DidOpen(rv);
}

在回调函数中判断是否存在以及是否是个目录,如果是的话,返回。如果不是,那么使用stream_文件操作流来具体的执行打开操作,并设置了回调DidOpen的操作
DidOpen中设置seek的指针。

读取

那么我们如何读取数据呢
我们实现ReadRawData供上层读取数据。

0:021> kL
 # Child-SP          RetAddr           Call Site
00 00000000`0566e508 000007fe`eefa14d7 chrome_7feee360000!net::URLRequestFileJob::ReadRawData
01 00000000`0566e510 000007fe`eefa0fe2 chrome_7feee360000!net::URLRequestJob::ReadRawDataHelper+0x57
02 00000000`0566e540 000007fe`eef501f2 chrome_7feee360000!net::URLRequestJob::Read+0x32
03 00000000`0566e580 000007fe`ef507f94 chrome_7feee360000!net::URLRequest::Read+0x5e
04 00000000`0566e5b0 000007fe`ef50882f chrome_7feee360000!content::ResourceLoader::ReadMore+0xb4
05 00000000`0566e640 000007fe`ef5087f1 chrome_7feee360000!content::ResourceLoader::StartReading+0x27
06 00000000`0566e6f0 000007fe`f07bfdd0 chrome_7feee360000!content::ResourceLoader::ResumeReading+0xf1
07 (Inline Function) --------`-------- chrome_7feee360000!base::internal::RunnableAdapter<void (__cdecl syncer_v2::SharedModelTypeProcessor::*)(void)>::Run+0x16
08 (Inline Function) --------`-------- chrome_7feee360000!base::internal::InvokeHelper<1,void,base::internal::RunnableAdapter<void (__cdecl syncer_v2::SharedModelTypeProcessor::*)(void)> >::MakeItSo+0x3b
09 00000000`0566e780 000007fe`ee402ead chrome_7feee360000!base::internal::Invoker<base::IndexSequence<0>,base::internal::BindState<base::internal::RunnableAdapter<void (__cdecl syncer_v2::SharedModelTypeProcessor::*)(void) __ptr64>,void __cdecl(syncer_v2::SharedModelTypeProcessor * __ptr64),base::WeakPtr<syncer_v2::SharedModelTypeProcessor> >,base::internal::InvokeHelper<1,void,base::internal::RunnableAdapter<void (__cdecl syncer_v2::SharedModelTypeProcessor::*)(void) __ptr64> >,void __cdecl(void)>::Run+0x60
0a (Inline Function) --------`-------- chrome_7feee360000!base::Callback<void __cdecl(void)>::Run+0x8
0b 00000000`0566e7d0 000007fe`ee39eb95 chrome_7feee360000!base::debug::TaskAnnotator::RunTask+0x13d
0c 00000000`0566e8b0 000007fe`ee39f6d4 chrome_7feee360000!base::MessageLoop::RunTask+0x3f5
0d (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::DeferOrRunPendingTask+0x147
0e 00000000`0566f990 000007fe`ee40226a chrome_7feee360000!base::MessageLoop::DoWork+0x484
0f 00000000`0566fb60 000007fe`ee401732 chrome_7feee360000!base::MessagePumpForIO::DoRunLoop+0xaa
10 00000000`0566fb90 000007fe`ee3edd83 chrome_7feee360000!base::MessagePumpWin::Run+0x42
11 (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::RunHandler+0x15
12 00000000`0566fbd0 000007fe`ee3c4381 chrome_7feee360000!base::RunLoop::Run+0x83
13 (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::Run+0x35
14 00000000`0566fc20 000007fe`ef3d84fa chrome_7feee360000!base::Thread::Run+0x41
15 00000000`0566fc80 000007fe`ef3d8cfd chrome_7feee360000!content::BrowserThreadImpl::IOThreadRun+0x36
16 00000000`0566fdd0 000007fe`ee3c46d8 chrome_7feee360000!content::BrowserThreadImpl::Run+0x89
17 00000000`0566fe00 000007fe`ee3d7e9d chrome_7feee360000!base::Thread::ThreadMain+0x338
18 00000000`0566fe70 00000000`76ed652d chrome_7feee360000!base::`anonymous namespace'::ThreadFunc+0x15d
19 00000000`0566fee0 00000000`7710c541 kernel32!BaseThreadInitThunk+0xd
1a 00000000`0566ff10 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

ResourceLoader在启动一个URL的请求后,会控制URLRequest来读取数据,实际的任务交给URLRequestFileJob,针对于文件加载job来具体的完成任务。

int URLRequestFileJob::ReadRawData(IOBuffer* dest, int dest_size) {
  DCHECK_NE(dest_size, 0);
  DCHECK_GE(remaining_bytes_, 0);

  if (remaining_bytes_ < dest_size)
    dest_size = remaining_bytes_;

  // If we should copy zero bytes because |remaining_bytes_| is zero, short
  // circuit here.
  if (!dest_size)
    return 0;

  int rv = stream_->Read(dest,
                         dest_size,
                         base::Bind(&URLRequestFileJob::DidRead,
                                    weak_ptr_factory_.GetWeakPtr(),
                                    make_scoped_refptr(dest)));
  if (rv >= 0) {
    remaining_bytes_ -= rv;
    DCHECK_GE(remaining_bytes_, 0);
  }

  return rv;
}

在读取原始数据中,使用文件流来读取文件到IO缓冲区IOBuffer中,并这是读取完成回调函数

void URLRequestFileJob::DidRead(scoped_refptr<IOBuffer> buf, int result) {
  if (result >= 0) {
    remaining_bytes_ -= result;
    DCHECK_GE(remaining_bytes_, 0);
  }

  OnReadComplete(buf.get(), result);
  buf = NULL;

  ReadRawDataComplete(result);
}

一个读取操作完成后,读取回调被调用,接着开始回调ReadRawDataComplete来通知上层,让上层来判断是否继续读取。

0:021> kL
 # Child-SP          RetAddr           Call Site
00 00000000`0566e388 000007fe`eefa14d7 chrome_7feee360000!net::URLRequestFileJob::ReadRawData
01 00000000`0566e390 000007fe`eefa0fe2 chrome_7feee360000!net::URLRequestJob::ReadRawDataHelper+0x57
02 00000000`0566e3c0 000007fe`eef501f2 chrome_7feee360000!net::URLRequestJob::Read+0x32
03 00000000`0566e400 000007fe`ef507f94 chrome_7feee360000!net::URLRequest::Read+0x5e
04 00000000`0566e430 000007fe`ef50882f chrome_7feee360000!content::ResourceLoader::ReadMore+0xb4
05 00000000`0566e4c0 000007fe`ef50794b chrome_7feee360000!content::ResourceLoader::StartReading+0x27
06 00000000`0566e570 000007fe`eefa1425 chrome_7feee360000!content::ResourceLoader::OnReadCompleted+0x5b
07 00000000`0566e600 000007fe`eefc220a chrome_7feee360000!net::URLRequestJob::ReadRawDataComplete+0x115
08 00000000`0566e6a0 000007fe`eefc1d04 chrome_7feee360000!net::URLRequestFileJob::DidRead+0x4e
09 (Inline Function) --------`-------- chrome_7feee360000!base::internal::RunnableAdapter<void (__cdecl net::URLRequestFileJob::*)(scoped_refptr<net::IOBuffer>,int)>::Run+0x25
0a 00000000`0566e6d0 000007fe`eefc2716 chrome_7feee360000!base::internal::InvokeHelper<1,void,base::internal::RunnableAdapter<void (__cdecl net::URLRequestFileJob::*)(scoped_refptr<net::IOBuffer>,int) __ptr64> >::MakeItSo<base::WeakPtr<net::URLRequestFileJob>,net::IOBuffer * __ptr64,int const & __ptr64>+0x74
0b 00000000`0566e710 000007fe`ef065345 chrome_7feee360000!base::internal::Invoker<base::IndexSequence<0,1>,base::internal::BindState<base::internal::RunnableAdapter<void (__cdecl net::URLRequestFileJob::*)(scoped_refptr<net::IOBuffer>,int) __ptr64>,void __cdecl(net::URLRequestFileJob * __ptr64,scoped_refptr<net::IOBuffer>,int),base::WeakPtr<net::URLRequestFileJob>,scoped_refptr<net::IOBuffer> >,base::internal::InvokeHelper<1,void,base::internal::RunnableAdapter<void (__cdecl net::URLRequestFileJob::*)(scoped_refptr<net::IOBuffer>,int) __ptr64> >,void __cdecl(int const & __ptr64)>::Run+0x4a
0c (Inline Function) --------`-------- chrome_7feee360000!base::Callback<void __cdecl(int)>::Run+0x10
0d 00000000`0566e750 000007fe`ef0656e6 chrome_7feee360000!net::FileStream::Context::InvokeUserCallback+0x99
0e 00000000`0566e790 000007fe`ee402ead chrome_7feee360000!net::FileStream::Context::ReadAsyncResult+0x56
0f (Inline Function) --------`-------- chrome_7feee360000!base::Callback<void __cdecl(void)>::Run+0x8
10 00000000`0566e7d0 000007fe`ee39eb95 chrome_7feee360000!base::debug::TaskAnnotator::RunTask+0x13d
11 00000000`0566e8b0 000007fe`ee39f6d4 chrome_7feee360000!base::MessageLoop::RunTask+0x3f5
12 (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::DeferOrRunPendingTask+0x147
13 00000000`0566f990 000007fe`ee40226a chrome_7feee360000!base::MessageLoop::DoWork+0x484
14 00000000`0566fb60 000007fe`ee401732 chrome_7feee360000!base::MessagePumpForIO::DoRunLoop+0xaa
15 00000000`0566fb90 000007fe`ee3edd83 chrome_7feee360000!base::MessagePumpWin::Run+0x42
16 (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::RunHandler+0x15
17 00000000`0566fbd0 000007fe`ee3c4381 chrome_7feee360000!base::RunLoop::Run+0x83
18 (Inline Function) --------`-------- chrome_7feee360000!base::MessageLoop::Run+0x35
19 00000000`0566fc20 000007fe`ef3d84fa chrome_7feee360000!base::Thread::Run+0x41
1a 00000000`0566fc80 000007fe`ef3d8cfd chrome_7feee360000!content::BrowserThreadImpl::IOThreadRun+0x36
1b 00000000`0566fdd0 000007fe`ee3c46d8 chrome_7feee360000!content::BrowserThreadImpl::Run+0x89
1c 00000000`0566fe00 000007fe`ee3d7e9d chrome_7feee360000!base::Thread::ThreadMain+0x338
1d 00000000`0566fe70 00000000`76ed652d chrome_7feee360000!base::`anonymous namespace'::ThreadFunc+0x15d
1e 00000000`0566fee0 00000000`7710c541 kernel32!BaseThreadInitThunk+0xd
1f 00000000`0566ff10 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

ReadRawDataComplete回调到上层后,上层发现还要再次读取数据,那么接着读取。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值