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

Unified Diff: chrome/browser/android/data_usage/data_use_ui_tab_model.cc

Issue 1443683002: Notify DataUseTabModel of navigations and tab closures (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed sclittle comments Created 5 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/android/data_usage/data_use_ui_tab_model.cc
diff --git a/chrome/browser/android/data_usage/data_use_ui_tab_model.cc b/chrome/browser/android/data_usage/data_use_ui_tab_model.cc
index 95e86286088001fabe436cda92c6f9375ccb4a8d..40cd19ccf499399a14af6c37340f2cf8c80d53ba 100644
--- a/chrome/browser/android/data_usage/data_use_ui_tab_model.cc
+++ b/chrome/browser/android/data_usage/data_use_ui_tab_model.cc
@@ -8,21 +8,127 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
#include "content/public/browser/browser_thread.h"
#include "url/gurl.h"
+namespace {
+
+// Notifies |data_use_tab_model| of navigation event on IO thread.
+void OnNavigationEventOnIOThread(
+ base::WeakPtr<chrome::android::DataUseTabModel> data_use_tab_model,
sclittle 2015/11/17 22:50:11 For readability, you could move this anonymous nam
tbansal1 2015/11/18 01:32:23 Done.
+ int32_t tab_id,
+ chrome::android::DataUseTabModel::TransitionType transition,
+ const GURL gurl) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+
+ if (!data_use_tab_model)
+ return;
+ data_use_tab_model->OnNavigationEvent(tab_id, transition, gurl);
+}
+
+// Notifies |data_use_tab_model| of tab closure on IO thread.
+void OnTabCloseEventOnIOThread(
+ base::WeakPtr<chrome::android::DataUseTabModel> data_use_tab_model,
+ int32_t tab_id) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+
+ if (!data_use_tab_model)
+ return;
+ data_use_tab_model->OnTabCloseEvent(tab_id);
+}
+
+// Notifies |data_use_ui_tab_model| on UI thread that tracking has started on
+// tab with id |tab_id|.
+void NotifyTrackingStartingOnUIThread(
+ base::WeakPtr<chrome::android::DataUseUITabModel> | data_use_ui_tab_model |
mmenke 2015/11/17 22:48:40 |?
tbansal1 2015/11/18 01:32:23 Done.
+ ,
sclittle 2015/11/17 22:50:11 I don't think this compiles, please fix this.
tbansal1 2015/11/18 01:32:23 Done.
+ int32_t tab_id) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (!data_use_ui_tab_model)
+ return;
+ data_use_ui_tab_model->NotifyTrackingStarting(tab_id);
+}
+
+// Notifies |data_use_ui_tab_model| on UI thread that tracking has ended on tab
+// with id |tab_id|.
+void NotifyTrackingEndingOnUIThread(
+ base::WeakPtr<chrome::android::DataUseUITabModel> data_use_ui_tab_model,
+ int32_t tab_id) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (!data_use_ui_tab_model)
+ return;
+ data_use_ui_tab_model->NotifyTrackingEnding(tab_id);
+}
+
+// Sets TabObserverOnIOThread by calling DataUseUITabModel's method on UI
+// thread.
+void SetTabDataUseObserverOnUIThread(
+ base::WeakPtr<chrome::android::DataUseUITabModel> data_use_ui_tab_model,
+ scoped_refptr<chrome::android::DataUseUITabModel::TabObserverOnIOThread>
+ tab_data_use_observer) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ if (!data_use_ui_tab_model)
+ return;
+ data_use_ui_tab_model->SetTabDataUseObserver(tab_data_use_observer);
+}
+
+// Creates a TabObserverOnIOThread object on IO thread.
+void CreateTabObserverOnIOThread(
+ base::WeakPtr<chrome::android::DataUseUITabModel> data_use_ui_tab_model,
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ scoped_refptr<chrome::android::DataUseUITabModel::TabObserverOnIOThread>
+ tab_observer(
+ new chrome::android::DataUseUITabModel::TabObserverOnIOThread(
+ data_use_ui_tab_model, ui_task_runner));
+ ui_task_runner->PostTask(FROM_HERE,
+ base::Bind(&SetTabDataUseObserverOnUIThread,
+ data_use_ui_tab_model, tab_observer));
+}
+
+// Passes |data_use_tab_model| to |tab_data_use_observer| on IO thread.
+void SetDataUseTabModelForTabDataUseObserver(
+ scoped_refptr<chrome::android::DataUseUITabModel::TabObserverOnIOThread>
+ tab_data_use_observer,
+ base::WeakPtr<chrome::android::DataUseTabModel> data_use_tab_model) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+
+ if (tab_data_use_observer)
+ tab_data_use_observer->SetIODataUseTabModel(data_use_tab_model);
+}
+
+} // namespace
+
namespace chrome {
namespace android {
DataUseUITabModel::DataUseUITabModel(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : io_task_runner_(io_task_runner) {
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
sclittle 2015/11/17 22:50:11 Instead of taking in a ui_task_runner, you could j
tbansal1 2015/11/18 01:32:23 Done.
+ : io_task_runner_(io_task_runner), weak_factory_(this) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(io_task_runner_);
+ DCHECK(ui_task_runner);
+ DCHECK(ui_task_runner->BelongsToCurrentThread());
+
+ io_task_runner_->PostTask(
sclittle 2015/11/17 22:50:11 It might just be simpler to have CreateTabObserver
tbansal1 2015/11/18 01:32:23 Done.
+ FROM_HERE, base::Bind(&CreateTabObserverOnIOThread,
+ weak_factory_.GetWeakPtr(), ui_task_runner));
}
-DataUseUITabModel::~DataUseUITabModel() {}
+DataUseUITabModel::~DataUseUITabModel() {
+ if (tab_data_use_observer_) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ tab_data_use_observer_->AddRef();
+
+ // Removes the last refptr to |tab_observer|, so that it is destroyed on IO
sclittle 2015/11/17 22:50:11 nit: Say "Removes the last reference" instead of "
tbansal1 2015/11/18 01:32:23 Done.
+ // thread.
+ io_task_runner_->ReleaseSoon(FROM_HERE, tab_data_use_observer_.get());
+ tab_data_use_observer_ = nullptr;
+ }
+}
void DataUseUITabModel::ReportBrowserNavigation(
const GURL& gurl,
@@ -31,14 +137,29 @@ void DataUseUITabModel::ReportBrowserNavigation(
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(thread_checker_.CalledOnValidThread());
- // TODO(tbansal): Post to DataUseTabModel on IO thread.
+ if (tab_id < 0)
sclittle 2015/11/17 22:50:11 For clarity, test for the -1 tab ID at the point w
tbansal1 2015/11/18 01:32:23 Done.
+ return;
+
+ DataUseTabModel::TransitionType transition_type;
+
+ if (ConvertTransitionType(page_transition, &transition_type)) {
+ io_task_runner_->PostTask(
sclittle 2015/11/17 22:50:11 PostTask already has built-in support for cancelli
tbansal1 2015/11/18 01:32:22 Done.
+ FROM_HERE,
+ base::Bind(&OnNavigationEventOnIOThread, io_data_use_tab_model_, tab_id,
+ transition_type, gurl));
+ }
}
void DataUseUITabModel::ReportTabClosure(int32_t tab_id) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(thread_checker_.CalledOnValidThread());
- // TODO(tbansal): Post to DataUseTabModel on IO thread.
+ if (tab_id < 0)
+ return;
+
+ io_task_runner_->PostTask(
sclittle 2015/11/17 22:50:11 Same here, just PostTask directly on the DataUseTa
tbansal1 2015/11/18 01:32:23 Done.
+ FROM_HERE,
+ base::Bind(&OnTabCloseEventOnIOThread, io_data_use_tab_model_, tab_id));
// Clear out local state.
TabEvents::iterator it = tab_events_.find(tab_id);
@@ -54,7 +175,20 @@ void DataUseUITabModel::ReportCustomTabInitialNavigation(
// TODO(tbansal): Post to DataUseTabModel on IO thread.
}
-void DataUseUITabModel::OnTrackingStarted(int32_t tab_id) {
+void DataUseUITabModel::SetIODataUseTabModel(
+ base::WeakPtr<DataUseTabModel> io_data_use_tab_model) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // It is okay to use base::Unretained because this is only called at the time
+ // of profile creation.
+ io_data_use_tab_model_ = io_data_use_tab_model;
+ io_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&SetDataUseTabModelForTabDataUseObserver,
sclittle 2015/11/17 22:50:11 Just post a task to create the observer here with
tbansal1 2015/11/18 01:32:23 Done.
+ tab_data_use_observer_, io_data_use_tab_model_));
+}
+
+void DataUseUITabModel::NotifyTrackingStarting(int32_t tab_id) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(thread_checker_.CalledOnValidThread());
@@ -65,7 +199,7 @@ void DataUseUITabModel::OnTrackingStarted(int32_t tab_id) {
RemoveTabEvent(tab_id, DATA_USE_TRACKING_ENDED);
}
-void DataUseUITabModel::OnTrackingEnded(int32_t tab_id) {
+void DataUseUITabModel::NotifyTrackingEnding(int32_t tab_id) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(thread_checker_.CalledOnValidThread());
@@ -98,8 +232,17 @@ bool DataUseUITabModel::HasDataUseTrackingEnded(int32_t tab_id) {
return RemoveTabEvent(tab_id, DATA_USE_TRACKING_ENDED);
}
+
+void DataUseUITabModel::SetTabDataUseObserver(
+ scoped_refptr<TabObserverOnIOThread> tab_data_use_observer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
sclittle 2015/11/17 22:50:11 Should you also DCHECK that this method is only ev
tbansal1 2015/11/18 01:32:23 Added DCHECK
+ tab_data_use_observer_.swap(tab_data_use_observer);
sclittle 2015/11/17 22:50:11 Why swap? Why not just assign it? The previous val
tbansal1 2015/11/18 01:32:23 Done.
+ DCHECK(tab_data_use_observer_);
+}
+
bool DataUseUITabModel::MaybeCreateTabEvent(int32_t tab_id,
DataUseTrackingEvent event) {
+ DCHECK(thread_checker_.CalledOnValidThread());
TabEvents::iterator it = tab_events_.find(tab_id);
if (it == tab_events_.end()) {
tab_events_.insert(std::make_pair(tab_id, event));
@@ -110,6 +253,7 @@ bool DataUseUITabModel::MaybeCreateTabEvent(int32_t tab_id,
bool DataUseUITabModel::RemoveTabEvent(int32_t tab_id,
DataUseTrackingEvent event) {
+ DCHECK(thread_checker_.CalledOnValidThread());
TabEvents::iterator it = tab_events_.find(tab_id);
DCHECK(it != tab_events_.end());
if (it->second == event) {
@@ -119,6 +263,96 @@ bool DataUseUITabModel::RemoveTabEvent(int32_t tab_id,
return false;
}
+bool DataUseUITabModel::ConvertTransitionType(
+ ui::PageTransition page_transition,
+ DataUseTabModel::TransitionType* transition_type) const {
+ if (!ui::PageTransitionIsValidType(page_transition) ||
+ !ui::PageTransitionIsMainFrame(page_transition) ||
+ !ui::PageTransitionIsNewNavigation(page_transition)) {
+ return false;
+ }
+
+ const int32_t mask = 0xFFFFFFFF ^ ui::PAGE_TRANSITION_QUALIFIER_MASK;
+
+ switch (page_transition & mask) {
+ case ui::PAGE_TRANSITION_LINK:
+ if ((page_transition & ui::PAGE_TRANSITION_FROM_API) != 0) {
+ // Clicking on bookmarks.
+ *transition_type = DataUseTabModel::TRANSITION_BOOKMARK;
+ return true;
+ }
+ return false; // Newtab, clicking on a link.
+ case ui::PAGE_TRANSITION_TYPED:
+ *transition_type = DataUseTabModel::TRANSITION_OMNIBOX_NAVIGATION;
+ return true;
+ case ui::PAGE_TRANSITION_AUTO_BOOKMARK:
+ // Auto bookmark from newtab page.
+ *transition_type = DataUseTabModel::TRANSITION_BOOKMARK;
+ return true;
+ case ui::PAGE_TRANSITION_AUTO_TOPLEVEL:
+ // History menu.
+ *transition_type = DataUseTabModel::TRANSITION_HISTORY_ITEM;
+ return true;
+ case ui::PAGE_TRANSITION_GENERATED:
+ // Omnibox search (e.g., searching for "tacos").
+ *transition_type = DataUseTabModel::TRANSITION_OMNIBOX_SEARCH;
+ return true;
+ case ui::PAGE_TRANSITION_RELOAD:
+ // Restored tabs.
+ return false;
+ default:
+ return false;
+ }
+}
+
+DataUseUITabModel::TabObserverOnIOThread::TabObserverOnIOThread(
+ base::WeakPtr<DataUseUITabModel> data_use_ui_tab_model,
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
+ : data_use_ui_tab_model_(data_use_ui_tab_model),
+ ui_task_runner_(ui_task_runner),
+ registered_as_observer_(false) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ DCHECK(ui_task_runner_);
+}
+
+DataUseUITabModel::TabObserverOnIOThread::~TabObserverOnIOThread() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (data_use_tab_model_ && registered_as_observer_)
+ data_use_tab_model_->RemoveObserver(this);
+}
+
+void DataUseUITabModel::TabObserverOnIOThread::SetIODataUseTabModel(
+ base::WeakPtr<DataUseTabModel> data_use_tab_model) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ data_use_tab_model_ = data_use_tab_model;
+
+ if (registered_as_observer_)
+ return;
sclittle 2015/11/17 22:50:11 This is weird. It looks like this Observer support
tbansal1 2015/11/18 01:32:23 Done.
+ registered_as_observer_ = true;
+
+ if (data_use_tab_model_)
+ data_use_tab_model_->AddObserver(this);
sclittle 2015/11/17 22:50:11 You should just DCHECK(data_use_tab_model_) when y
tbansal1 2015/11/18 01:32:23 Done.
+}
+
+void DataUseUITabModel::TabObserverOnIOThread::NotifyTrackingStarting(
+ int32_t tab_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ ui_task_runner_->PostTask(FROM_HERE,
sclittle 2015/11/17 22:50:11 PostTask already has built-in support for cancelli
tbansal1 2015/11/18 01:32:23 Done.
+ base::Bind(&NotifyTrackingStartingOnUIThread,
+ data_use_ui_tab_model_, tab_id));
+}
+
+void DataUseUITabModel::TabObserverOnIOThread::NotifyTrackingEnding(
+ int32_t tab_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ ui_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&NotifyTrackingEndingOnUIThread,
+ data_use_ui_tab_model_, tab_id));
+}
+
} // namespace android
} // namespace chrome

Powered by Google App Engine
This is Rietveld 408576698