blob: 92f8decf9b376f6f4af8358afd67758addc3359b [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/data_usage/tab_id_annotator.h"
#include <stdint.h>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "chrome/browser/data_usage/tab_id_provider.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "components/data_usage/core/data_use.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/web_contents.h"
#include "net/url_request/url_request.h"
using content::BrowserThread;
using data_usage::DataUse;
namespace chrome_browser_data_usage {
namespace {
// Attempts to get the associated tab info for render frame identified by
// |render_process_id| and |render_frame_id|. |global_request_id| is also
// populated in the tab info.
int32_t GetTabInfoForRequest(int render_process_id,
int render_frame_id,
content::GlobalRequestID global_request_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// TODO(sclittle): For prerendering tabs, investigate if it's possible to find
// the original tab that initiated the prerender.
return SessionTabHelper::IdForTab(content::WebContents::FromRenderFrameHost(
content::RenderFrameHost::FromID(render_process_id, render_frame_id)));
}
// Annotates |data_use| with the given |tab_id|, then passes it to |callback|.
// This is done in a separate function instead of as a method on TabIdAnnotator
// so that an in-progress annotation can complete even if the TabIdAnnotator is
// destroyed. This doesn't make much of a difference for production code, but
// makes it easier to test the TabIdAnnotator.
void AnnotateDataUse(
std::unique_ptr<DataUse> data_use,
const data_usage::DataUseAnnotator::DataUseConsumerCallback& callback,
int32_t tab_info) {
DCHECK(data_use);
data_use->tab_id = tab_info;
data_use->main_frame_global_request_id =
data_usage::DataUse::kInvalidMainFrameGlobalRequestID;
callback.Run(std::move(data_use));
}
} // namespace
TabIdAnnotator::TabIdAnnotator() {}
TabIdAnnotator::~TabIdAnnotator() {}
void TabIdAnnotator::Annotate(net::URLRequest* request,
std::unique_ptr<DataUse> data_use,
const DataUseConsumerCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(data_use);
TabIdProvider* existing_tab_id_provider = static_cast<TabIdProvider*>(
request->GetUserData(TabIdProvider::kTabIdProviderUserDataKey));
if (existing_tab_id_provider) {
existing_tab_id_provider->ProvideTabId(
base::BindOnce(&AnnotateDataUse, base::Passed(&data_use), callback));
return;
}
const content::ResourceRequestInfo* request_info =
content::ResourceRequestInfo::ForRequest(request);
int render_process_id = -1, render_frame_id = -1;
if (!content::ResourceRequestInfo::GetRenderFrameForRequest(
request, &render_process_id, &render_frame_id)) {
// Run the callback immediately with a tab ID of -1 if the request has no
// render frame.
AnnotateDataUse(std::move(data_use), callback, -1 /* tab_id */);
return;
}
// Populate global request ID only for main frame request.
content::GlobalRequestID global_request_id;
if (request_info &&
request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
global_request_id = request_info->GetGlobalRequestID();
}
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
std::unique_ptr<TabIdProvider> tab_id_provider(
new TabIdProvider(ui_thread_task_runner.get(), FROM_HERE,
base::BindOnce(&GetTabInfoForRequest, render_process_id,
render_frame_id, global_request_id)));
tab_id_provider->ProvideTabId(
base::BindOnce(&AnnotateDataUse, base::Passed(&data_use), callback));
request->SetUserData(TabIdProvider::kTabIdProviderUserDataKey,
std::move(tab_id_provider));
}
} // namespace chrome_browser_data_usage