Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: content/browser/loader/async_resource_handler.cc

Issue 2702503002: Block renderer-initiated main frame navigations to data URLs (Closed)
Patch Set: Fix downloads, plugin handling and browser side navigations Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/loader/async_resource_handler.h" 5 #include "content/browser/loader/async_resource_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/containers/hash_tables.h" 11 #include "base/containers/hash_tables.h"
12 #include "base/debug/alias.h" 12 #include "base/debug/alias.h"
13 #include "base/feature_list.h" 13 #include "base/feature_list.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
17 #include "base/memory/shared_memory.h" 17 #include "base/memory/shared_memory.h"
18 #include "base/metrics/histogram_macros.h" 18 #include "base/metrics/histogram_macros.h"
19 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/stringprintf.h"
20 #include "base/time/time.h" 21 #include "base/time/time.h"
22 #include "content/browser/frame_host/navigation_handle_impl.h"
23 #include "content/browser/frame_host/render_frame_host_impl.h"
21 #include "content/browser/loader/netlog_observer.h" 24 #include "content/browser/loader/netlog_observer.h"
22 #include "content/browser/loader/resource_buffer.h" 25 #include "content/browser/loader/resource_buffer.h"
23 #include "content/browser/loader/resource_controller.h" 26 #include "content/browser/loader/resource_controller.h"
24 #include "content/browser/loader/resource_dispatcher_host_impl.h" 27 #include "content/browser/loader/resource_dispatcher_host_impl.h"
25 #include "content/browser/loader/resource_message_filter.h" 28 #include "content/browser/loader/resource_message_filter.h"
26 #include "content/browser/loader/resource_request_info_impl.h" 29 #include "content/browser/loader/resource_request_info_impl.h"
27 #include "content/browser/loader/upload_progress_tracker.h" 30 #include "content/browser/loader/upload_progress_tracker.h"
28 #include "content/common/resource_messages.h" 31 #include "content/common/resource_messages.h"
29 #include "content/common/resource_request_completion_status.h" 32 #include "content/common/resource_request_completion_status.h"
30 #include "content/common/view_messages.h" 33 #include "content/common/view_messages.h"
34 #include "content/public/browser/render_frame_host.h"
35 #include "content/public/browser/web_contents.h"
31 #include "content/public/common/content_features.h" 36 #include "content/public/common/content_features.h"
32 #include "content/public/common/resource_response.h" 37 #include "content/public/common/resource_response.h"
33 #include "ipc/ipc_message_macros.h" 38 #include "ipc/ipc_message_macros.h"
34 #include "net/base/io_buffer.h" 39 #include "net/base/io_buffer.h"
35 #include "net/base/load_flags.h" 40 #include "net/base/load_flags.h"
36 #include "net/base/upload_progress.h" 41 #include "net/base/upload_progress.h"
37 #include "net/url_request/redirect_info.h" 42 #include "net/url_request/redirect_info.h"
38 43
39 using base::TimeDelta; 44 using base::TimeDelta;
40 using base::TimeTicks; 45 using base::TimeTicks;
41 46
42 namespace content { 47 namespace content {
43 namespace { 48 namespace {
44 49
45 static int kBufferSize = 1024 * 512; 50 static int kBufferSize = 1024 * 512;
46 static int kMinAllocationSize = 1024 * 4; 51 static int kMinAllocationSize = 1024 * 4;
47 static int kMaxAllocationSize = 1024 * 32; 52 static int kMaxAllocationSize = 1024 * 32;
48 53
49 // Used when kOptimizeLoadingIPCForSmallResources is enabled. 54 // Used when kOptimizeLoadingIPCForSmallResources is enabled.
50 // Small resource typically issues two Read call: one for the content itself 55 // Small resource typically issues two Read call: one for the content itself
51 // and another for getting zero response to detect EOF. 56 // and another for getting zero response to detect EOF.
52 // Inline these two into the IPC message to avoid allocating an expensive 57 // Inline these two into the IPC message to avoid allocating an expensive
53 // SharedMemory for small resources. 58 // SharedMemory for small resources.
54 const int kNumLeadingChunk = 2; 59 const int kNumLeadingChunk = 2;
55 const int kInlinedLeadingChunkSize = 2048; 60 const int kInlinedLeadingChunkSize = 2048;
56 61
62 const char kDataUrlConsoleError[] =
63 "Not allowed to top-level navigate to resource: %s";
64
57 void GetNumericArg(const std::string& name, int* result) { 65 void GetNumericArg(const std::string& name, int* result) {
58 const std::string& value = 66 const std::string& value =
59 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name); 67 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
60 if (!value.empty()) 68 if (!value.empty())
61 base::StringToInt(value, result); 69 base::StringToInt(value, result);
62 } 70 }
63 71
64 void InitializeResourceBufferConstants() { 72 void InitializeResourceBufferConstants() {
65 static bool did_init = false; 73 static bool did_init = false;
66 if (did_init) 74 if (did_init)
67 return; 75 return;
68 did_init = true; 76 did_init = true;
69 77
70 GetNumericArg("resource-buffer-size", &kBufferSize); 78 GetNumericArg("resource-buffer-size", &kBufferSize);
71 GetNumericArg("resource-buffer-min-allocation-size", &kMinAllocationSize); 79 GetNumericArg("resource-buffer-min-allocation-size", &kMinAllocationSize);
72 GetNumericArg("resource-buffer-max-allocation-size", &kMaxAllocationSize); 80 GetNumericArg("resource-buffer-max-allocation-size", &kMaxAllocationSize);
73 } 81 }
74 82
83 // Determines if the current navigation pointed by |render_process_id| and
84 // |render_frame_host_id| is renderer initiated and calls |callback| with
85 // the result.
86 void CheckNavigationIsRendererInitiated(
meacer 2017/03/16 19:53:21 This is probably very wrong to do, so suggestions
87 int render_process_id,
88 int render_frame_host_id,
89 const base::Callback<void(bool)>& callback) {
90 DCHECK_CURRENTLY_ON(BrowserThread::UI);
91 RenderFrameHostImpl* rfh =
92 RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
93 DCHECK(rfh);
94 const bool should_cancel = rfh->navigation_handle()->IsRendererInitiated();
95 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
96 base::Bind(callback, should_cancel));
97 }
98
99 void AddConsoleMessage(
100 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
101 const GURL& url) {
102 DCHECK_CURRENTLY_ON(BrowserThread::UI);
103 WebContents* contents = web_contents_getter.Run();
104 DCHECK(contents);
105 if (contents) {
106 contents->GetMainFrame()->AddMessageToConsole(
107 CONSOLE_MESSAGE_LEVEL_ERROR,
108 base::StringPrintf(kDataUrlConsoleError, url.spec().c_str()));
109 }
110 }
111
75 // This enum is used for logging a histogram and should not be reordered. 112 // This enum is used for logging a histogram and should not be reordered.
76 enum ExpectedContentSizeResult { 113 enum ExpectedContentSizeResult {
77 EQ_RESPONSE_BODY = 0, 114 EQ_RESPONSE_BODY = 0,
78 EQ_RESPONSE_BODY_GT_EQ_BUFFER_SIZE = 1, 115 EQ_RESPONSE_BODY_GT_EQ_BUFFER_SIZE = 1,
79 GT_EQ_BUFFER_SIZE = 2, 116 GT_EQ_BUFFER_SIZE = 2,
80 LT_RESPONSE_BODY = 3, 117 LT_RESPONSE_BODY = 3,
81 GT_RESPONSE_BODY = 4, 118 GT_RESPONSE_BODY = 4,
82 UNKNOWN = 5, 119 UNKNOWN = 5,
83 EXPECTED_CONTENT_MAX, 120 EXPECTED_CONTENT_MAX,
84 }; 121 };
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 void AsyncResourceHandler::OnResponseStarted( 326 void AsyncResourceHandler::OnResponseStarted(
290 ResourceResponse* response, 327 ResourceResponse* response,
291 std::unique_ptr<ResourceController> controller) { 328 std::unique_ptr<ResourceController> controller) {
292 // For changes to the main frame, inform the renderer of the new URL's 329 // For changes to the main frame, inform the renderer of the new URL's
293 // per-host settings before the request actually commits. This way the 330 // per-host settings before the request actually commits. This way the
294 // renderer will be able to set these precisely at the time the 331 // renderer will be able to set these precisely at the time the
295 // request commits, avoiding the possibility of e.g. zooming the old content 332 // request commits, avoiding the possibility of e.g. zooming the old content
296 // or of having to layout the new content twice. 333 // or of having to layout the new content twice.
297 DCHECK(!has_controller()); 334 DCHECK(!has_controller());
298 335
336 // Block renderer-initiated, top-frame, non-download data URL navigations.
337 // Renderer-initiated check is done on the UI thread.
338 ResourceRequestInfoImpl* info = GetRequestInfo();
339 if (request()->url().SchemeIs("data") &&
340 info->requester_info()->IsRenderer() && info->IsMainFrame() &&
341 !info->IsDownload()) {
342 int render_process_id, render_frame_id;
343 if (info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id)) {
344 BrowserThread::PostTask(
345 BrowserThread::UI, FROM_HERE,
346 base::Bind(
347 &CheckNavigationIsRendererInitiated, render_process_id,
348 render_frame_id,
349 base::Bind(&AsyncResourceHandler::OnResponseStartedInternal,
350 base::Unretained(this), response,
351 base::Passed(std::move(controller)))));
352 return;
353 }
354 }
355 OnResponseStartedInternal(response, std::move(controller), false);
356 }
357
358 void AsyncResourceHandler::OnResponseStartedInternal(
359 ResourceResponse* response,
360 std::unique_ptr<ResourceController> controller,
361 bool should_cancel) {
362 DCHECK_CURRENTLY_ON(BrowserThread::IO);
363 ResourceRequestInfoImpl* info = GetRequestInfo();
364
365 if (should_cancel) {
366 BrowserThread::PostTask(
367 BrowserThread::UI, FROM_HERE,
368 base::Bind(&AddConsoleMessage, info->GetWebContentsGetterForRequest(),
369 request()->url()));
370 controller->Cancel();
371 return;
372 }
373
299 response_started_ticks_ = base::TimeTicks::Now(); 374 response_started_ticks_ = base::TimeTicks::Now();
300 375
301 // We want to send a final upload progress message prior to sending the 376 // We want to send a final upload progress message prior to sending the
302 // response complete message even if we're waiting for an ack to to a 377 // response complete message even if we're waiting for an ack to to a
303 // previous upload progress message. 378 // previous upload progress message.
304 if (upload_progress_tracker_) { 379 if (upload_progress_tracker_) {
305 upload_progress_tracker_->OnUploadCompleted(); 380 upload_progress_tracker_->OnUploadCompleted();
306 upload_progress_tracker_ = nullptr; 381 upload_progress_tracker_ = nullptr;
307 } 382 }
308 383
309 const ResourceRequestInfoImpl* info = GetRequestInfo();
310 ResourceMessageFilter* filter = GetFilter(); 384 ResourceMessageFilter* filter = GetFilter();
311 if (!filter) { 385 if (!filter) {
312 controller->Cancel(); 386 controller->Cancel();
313 return; 387 return;
314 } 388 }
315 389
316 NetLogObserver::PopulateResponseInfo(request(), response); 390 NetLogObserver::PopulateResponseInfo(request(), response);
317 response->head.encoded_data_length = request()->raw_header_size(); 391 response->head.encoded_data_length = request()->raw_header_size();
318 392
319 // If the parent handler downloaded the resource to a file, grant the child 393 // If the parent handler downloaded the resource to a file, grant the child
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 void AsyncResourceHandler::SendUploadProgress( 695 void AsyncResourceHandler::SendUploadProgress(
622 const net::UploadProgress& progress) { 696 const net::UploadProgress& progress) {
623 ResourceMessageFilter* filter = GetFilter(); 697 ResourceMessageFilter* filter = GetFilter();
624 if (!filter) 698 if (!filter)
625 return; 699 return;
626 filter->Send(new ResourceMsg_UploadProgress( 700 filter->Send(new ResourceMsg_UploadProgress(
627 GetRequestID(), progress.position(), progress.size())); 701 GetRequestID(), progress.position(), progress.size()));
628 } 702 }
629 703
630 } // namespace content 704 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/async_resource_handler.h ('k') | content/browser/web_contents/web_contents_impl_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698