1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/sync_driver/revisit/sessions_page_revisit_observer.h"
7 #include "base/metrics/histogram_macros.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "components/sessions/session_types.h"
10 #include "components/sync_driver/glue/synced_session.h"
11 #include "components/sync_driver/revisit/current_tab_matcher.h"
12 #include "components/sync_driver/revisit/offset_tab_matcher.h"
13 #include "components/sync_driver/revisit/page_equality.h"
15 namespace sync_driver
{
17 SessionsPageRevisitObserver::SessionsPageRevisitObserver(
18 scoped_ptr
<ForeignSessionsProvider
> provider
)
19 : provider_(provider
.Pass()) {}
21 SessionsPageRevisitObserver::~SessionsPageRevisitObserver() {}
23 void SessionsPageRevisitObserver::OnPageVisit(const GURL
& url
,
24 const TransitionType transition
) {
25 // We need to be invoked and eventually execute on the thread which owns the
26 // session objects the provider will give us. However, this work is not
27 // especially time sensitive, and so we post a task to perform this to get out
28 // of the way of any currently executing logic.
30 // Bind this task to this->AsWeakPtr() so that if we're destructed this task
31 // just vanish instead of breaking things.
32 base::ThreadTaskRunnerHandle::Get()->PostTask(
33 FROM_HERE
, base::Bind(&SessionsPageRevisitObserver::CheckForRevisit
,
34 this->AsWeakPtr(), url
, transition
));
37 void SessionsPageRevisitObserver::CheckForRevisit(
39 const TransitionType transition
) {
40 base::TimeTicks
start(base::TimeTicks::Now());
42 // We want to match tabs/navigation entries in two slightly different ways. We
43 // value the current url/navigation entry of a tab more highly, and want to
44 // actually seperate metrics from the backwards/forwards entries. And then
45 // to make things a little bit messier, we only have an accurate modified time
46 // for the tabs/current entries. So use index offset for forward/back entries.
47 PageEquality
page_equality(url
);
48 CurrentTabMatcher
current_matcher(page_equality
);
49 OffsetTabMatcher
offset_matcher(page_equality
);
51 std::vector
<const sync_driver::SyncedSession
*> foreign_sessions
;
52 if (provider_
->GetAllForeignSessions(&foreign_sessions
)) {
53 for (const sync_driver::SyncedSession
* session
: foreign_sessions
) {
54 for (const std::pair
<const SessionID::id_type
, sessions::SessionWindow
*>&
55 key_value
: session
->windows
) {
56 for (const sessions::SessionTab
* tab
: key_value
.second
->tabs
) {
57 // These matchers look identical and could easily implement an
58 // interface and we could iterate through a vector of matchers here.
59 // However this would cause quite a bit of overhead at the inner most
60 // loop of something that takes linear time in relation to the number
61 // of open foreign tabs. A small fraction of users have thousands of
63 current_matcher
.Check(tab
);
64 offset_matcher
.Check(tab
);
70 // emit even if there are no foreign sessions so that that counts all match.
71 current_matcher
.Emit(transition
);
72 offset_matcher
.Emit(transition
);
74 base::TimeDelta
duration(base::TimeTicks::Now() - start
);
75 UMA_HISTOGRAM_TIMES("Sync.PageRevisitSessionDuration", duration
);
78 } // namespace sync_driver