summaryrefslogtreecommitdiff
path: root/chromium/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc
blob: 9f3a2e3fb6625fb87cae10f300810e7004624a8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2018 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 "components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h"

#include <utility>

#include "base/bind.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h"

namespace contextual_suggestions {

namespace {
// TODO(pnoland): check if this is the correct base URL for all images.
static constexpr char kImageURLFormat[] =
    "http://www.google.com/images?q=tbn:%s";

GURL ImageUrlFromId(const std::string& image_id) {
  return GURL(base::StringPrintf(kImageURLFormat, image_id.c_str()));
}
}  // namespace

ContextualContentSuggestionsServiceProxy::
    ContextualContentSuggestionsServiceProxy(
        ntp_snippets::ContextualContentSuggestionsService* service,
        std::unique_ptr<ContextualSuggestionsMetricsReporter> metrics_reporter)
    : service_(service),
      metrics_reporter_(std::move(metrics_reporter)),
      last_ukm_source_id_(ukm::kInvalidSourceId),
      weak_ptr_factory_(this) {}

ContextualContentSuggestionsServiceProxy::
    ~ContextualContentSuggestionsServiceProxy() {}

void ContextualContentSuggestionsServiceProxy::FetchContextualSuggestions(
    const GURL& url,
    ClustersCallback callback) {
  service_->FetchContextualSuggestionClusters(
      url,
      base::BindOnce(
          &ContextualContentSuggestionsServiceProxy::CacheSuggestions,
          weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
      base::BindRepeating(
          &ContextualContentSuggestionsServiceProxy::ReportEvent,
          weak_ptr_factory_.GetWeakPtr(), last_ukm_source_id_));
}

void ContextualContentSuggestionsServiceProxy::FetchContextualSuggestionImage(
    const std::string& suggestion_id,
    ntp_snippets::ImageFetchedCallback callback) {
  auto suggestion_iter = suggestions_.find(suggestion_id);
  if (suggestion_iter == suggestions_.end()) {
    DVLOG(1) << "Unkown suggestion ID: " << suggestion_id;
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), gfx::Image()));
    return;
  }

  FetchImageImpl(suggestion_iter->second.image_id, std::move(callback));
}

void ContextualContentSuggestionsServiceProxy::FetchContextualSuggestionFavicon(
    const std::string& suggestion_id,
    ntp_snippets::ImageFetchedCallback callback) {
  auto suggestion_iter = suggestions_.find(suggestion_id);
  if (suggestion_iter == suggestions_.end()) {
    DVLOG(1) << "Unkown suggestion ID: " << suggestion_id;
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), gfx::Image()));
    return;
  }

  FetchImageImpl(suggestion_iter->second.favicon_image_id, std::move(callback));
}

void ContextualContentSuggestionsServiceProxy::ClearState() {
  suggestions_.clear();
  weak_ptr_factory_.InvalidateWeakPtrs();
}

void ContextualContentSuggestionsServiceProxy::ReportEvent(
    ukm::SourceId ukm_source_id,
    ContextualSuggestionsEvent event) {
  // TODO(pnoland): investigate how we can get into this state(one known
  // example is if we switch tabs and there's no committed navigation in the new
  // tab) and prevent it from happening. Replace the early return with a DCHECK
  // once this is done.
  if (ukm_source_id == ukm::kInvalidSourceId) {
    return;
  }

  // Flush the previous page (if any) and setup the new page.
  if (ukm_source_id != last_ukm_source_id_) {
    if (last_ukm_source_id_ != ukm::kInvalidSourceId)
      metrics_reporter_->Flush();
    last_ukm_source_id_ = ukm_source_id;
    metrics_reporter_->SetupForPage(ukm_source_id);
  }

  metrics_reporter_->RecordEvent(event);
}

void ContextualContentSuggestionsServiceProxy::FlushMetrics() {
  if (last_ukm_source_id_ != ukm::kInvalidSourceId)
    metrics_reporter_->Flush();
  last_ukm_source_id_ = ukm::kInvalidSourceId;
}

void ContextualContentSuggestionsServiceProxy::FetchImageImpl(
    const std::string& image_id,
    ntp_snippets::ImageFetchedCallback callback) {
  GURL image_url = ImageUrlFromId(image_id);

  ntp_snippets::ContentSuggestion::ID synthetic_cache_id(
      ntp_snippets::Category::FromKnownCategory(
          ntp_snippets::KnownCategories::CONTEXTUAL),
      image_id);

  service_->FetchContextualSuggestionImage(synthetic_cache_id, image_url,
                                           std::move(callback));
}

void ContextualContentSuggestionsServiceProxy::CacheSuggestions(
    ClustersCallback callback,
    std::string peek_text,
    std::vector<Cluster> clusters) {
  suggestions_.clear();
  for (auto& cluster : clusters) {
    for (auto& suggestion : cluster.suggestions) {
      suggestions_.emplace(std::make_pair(suggestion.id, suggestion));
    }
  }
  std::move(callback).Run(peek_text, std::move(clusters));
}

}  // namespace contextual_suggestions