| Index: chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
|
| diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
|
| index 1a745b2501a511c0222bf81e89164910f8bf6da1..8495f373b81c70fdfda1e023337a7c2c2015c5eb 100644
|
| --- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
|
| +++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
|
| @@ -4,18 +4,37 @@
|
|
|
| #include "chrome/browser/data_use_measurement/chrome_data_use_ascriber.h"
|
|
|
| +#include "base/memory/ptr_util.h"
|
| +#include "components/data_use_measurement/core/data_use_recorder.h"
|
| +#include "components/data_use_measurement/core/data_use_user_data.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/navigation_handle.h"
|
| #include "content/public/browser/render_frame_host.h"
|
| +#include "content/public/browser/resource_request_info.h"
|
| +#include "content/public/common/browser_side_navigation_policy.h"
|
| +#include "net/url_request/url_request.h"
|
|
|
| namespace data_use_measurement {
|
|
|
| +// static
|
| +const void* ChromeDataUseAscriber::DataUseRecorderEntryAsUserData::
|
| + kUserDataKey = static_cast<void*>(
|
| + &ChromeDataUseAscriber::DataUseRecorderEntryAsUserData::kUserDataKey);
|
| +
|
| +ChromeDataUseAscriber::DataUseRecorderEntryAsUserData::
|
| + DataUseRecorderEntryAsUserData(DataUseRecorderEntry entry)
|
| + : entry_(entry) {}
|
| +
|
| +ChromeDataUseAscriber::DataUseRecorderEntryAsUserData::
|
| + ~DataUseRecorderEntryAsUserData() {}
|
| +
|
| ChromeDataUseAscriber::ChromeDataUseAscriber() {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| }
|
|
|
| ChromeDataUseAscriber::~ChromeDataUseAscriber() {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + DCHECK_EQ(0u, data_use_recorders_.size());
|
| }
|
|
|
| DataUseRecorder* ChromeDataUseAscriber::GetDataUseRecorder(
|
| @@ -24,11 +43,86 @@ DataUseRecorder* ChromeDataUseAscriber::GetDataUseRecorder(
|
| return nullptr;
|
| }
|
|
|
| +void ChromeDataUseAscriber::OnBeforeUrlRequest(net::URLRequest* request) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| +
|
| + // TODO(kundaji): Handle PlzNavigate.
|
| + if (content::IsBrowserSideNavigationEnabled())
|
| + return;
|
| +
|
| + auto service = static_cast<DataUseUserData*>(
|
| + request->GetUserData(DataUseUserData::kUserDataKey));
|
| + if (service)
|
| + return;
|
| +
|
| + const content::ResourceRequestInfo* request_info =
|
| + content::ResourceRequestInfo::ForRequest(request);
|
| + content::ResourceType resource_type = request_info
|
| + ? request_info->GetResourceType()
|
| + : content::RESOURCE_TYPE_LAST_TYPE;
|
| +
|
| + if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME)
|
| + return;
|
| +
|
| + int render_process_id = -1;
|
| + int render_frame_id = -1;
|
| + bool has_valid_render_frame_id =
|
| + content::ResourceRequestInfo::GetRenderFrameForRequest(
|
| + request, &render_process_id, &render_frame_id);
|
| + DCHECK(has_valid_render_frame_id);
|
| + // Browser tests may not set up DataUseWebContentsObservers in which case
|
| + // this class never sees navigation and frame events so DataUseRecorders
|
| + // will never be destroyed. To avoid this, we ignore requests whose
|
| + // render frames don't have a record. However, this can also be caused by
|
| + // URLRequests racing the frame create events.
|
| + // TODO(kundaji): Add UMA.
|
| + if (render_frame_data_use_map_.find(
|
| + RenderFrameHostID(render_process_id, render_frame_id)) ==
|
| + render_frame_data_use_map_.end()) {
|
| + return;
|
| + }
|
| +
|
| + // If this request is already being tracked, do not create a new entry.
|
| + auto user_data = static_cast<DataUseRecorderEntryAsUserData*>(
|
| + request->GetUserData(DataUseRecorderEntryAsUserData::kUserDataKey));
|
| + if (user_data)
|
| + return;
|
| +
|
| + DataUseRecorderEntry entry = data_use_recorders_.insert(
|
| + data_use_recorders_.end(), base::MakeUnique<DataUseRecorder>());
|
| + request->SetUserData(DataUseRecorderEntryAsUserData::kUserDataKey,
|
| + new DataUseRecorderEntryAsUserData(entry));
|
| + pending_navigation_data_use_map_.insert(
|
| + std::make_pair(request_info->GetGlobalRequestID(), entry));
|
| +}
|
| +
|
| +void ChromeDataUseAscriber::OnUrlRequestDestroyed(net::URLRequest* request) {
|
| + const content::ResourceRequestInfo* request_info =
|
| + content::ResourceRequestInfo::ForRequest(request);
|
| + content::ResourceType resource_type = request_info
|
| + ? request_info->GetResourceType()
|
| + : content::RESOURCE_TYPE_LAST_TYPE;
|
| + if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME) {
|
| + // If request was not successful, then ReadyToCommitNavigation will not be
|
| + // called. So delete the pending navigation DataUseRecorderEntry here.
|
| + if (!request->status().is_success()) {
|
| + DeletePendingNavigationEntry(request_info->GetGlobalRequestID());
|
| + }
|
| + }
|
| +}
|
| +
|
| void ChromeDataUseAscriber::RenderFrameCreated(int render_process_id,
|
| int render_frame_id,
|
| int parent_render_process_id,
|
| int parent_render_frame_id) {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| +
|
| + // TODO(kundaji): Point child render frames to the same DataUseRecorder as
|
| + // parent render frame.
|
| + DataUseRecorderEntry entry = data_use_recorders_.insert(
|
| + data_use_recorders_.end(), base::MakeUnique<DataUseRecorder>());
|
| + render_frame_data_use_map_.insert(std::make_pair(
|
| + RenderFrameHostID(render_process_id, render_frame_id), entry));
|
| }
|
|
|
| void ChromeDataUseAscriber::RenderFrameDeleted(int render_process_id,
|
| @@ -36,6 +130,13 @@ void ChromeDataUseAscriber::RenderFrameDeleted(int render_process_id,
|
| int parent_render_process_id,
|
| int parent_render_frame_id) {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + RenderFrameHostID key(render_process_id, render_frame_id);
|
| + auto frame_iter = render_frame_data_use_map_.find(key);
|
| + DCHECK(frame_iter != render_frame_data_use_map_.end());
|
| + DataUseRecorderEntry entry = frame_iter->second;
|
| + render_frame_data_use_map_.erase(frame_iter);
|
| +
|
| + data_use_recorders_.erase(entry);
|
| }
|
|
|
| void ChromeDataUseAscriber::DidStartMainFrameNavigation(
|
| @@ -46,13 +147,19 @@ void ChromeDataUseAscriber::DidStartMainFrameNavigation(
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| }
|
|
|
| -void ChromeDataUseAscriber::DidFinishMainFrameNavigation(
|
| +void ChromeDataUseAscriber::ReadyToCommitMainFrameNavigation(
|
| GURL gurl,
|
| + content::GlobalRequestID global_request_id,
|
| int render_process_id,
|
| int render_frame_id,
|
| bool is_same_page_navigation,
|
| void* navigation_handle) {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| +
|
| + // TODO(kundaji): Move the DataUseRecorderEntry from pending navigation map
|
| + // to render frame map if |is_same_page_navigation| is true. Otherwise,
|
| + // merge it with the DataUseRecorderEntry in the render frame map.
|
| + DeletePendingNavigationEntry(global_request_id);
|
| }
|
|
|
| void ChromeDataUseAscriber::DidRedirectMainFrameNavigation(
|
| @@ -63,4 +170,17 @@ void ChromeDataUseAscriber::DidRedirectMainFrameNavigation(
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| }
|
|
|
| +void ChromeDataUseAscriber::DeletePendingNavigationEntry(
|
| + content::GlobalRequestID global_request_id) {
|
| + auto navigation_iter =
|
| + pending_navigation_data_use_map_.find(global_request_id);
|
| + // Pending navigation entry will not be found if finish navigation
|
| + // raced the URLRequest.
|
| + if (navigation_iter != pending_navigation_data_use_map_.end()) {
|
| + auto entry = navigation_iter->second;
|
| + pending_navigation_data_use_map_.erase(navigation_iter);
|
| + data_use_recorders_.erase(entry);
|
| + }
|
| +}
|
| +
|
| } // namespace data_use_measurement
|
|
|