blob: 31c3ab8a2b68d19493188374e988a0bc5e2ce04a [file] [log] [blame]
// 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 "chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.h"
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/chromeos/android_sms/android_sms_urls.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/components/multidevice/logging/logging.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#include "net/cookies/canonical_cookie.h"
#include "url/gurl.h"
namespace {
const char kMessagesPairStateCookieName[] = "pair_state_cookie";
const char kPairedCookieValue[] = "true";
} // namespace
namespace chromeos {
namespace android_sms {
AndroidSmsPairingStateTrackerImpl::AndroidSmsPairingStateTrackerImpl(
Profile* profile,
AndroidSmsAppManager* android_sms_app_manager)
: profile_(profile), android_sms_app_manager_(android_sms_app_manager) {
android_sms_app_manager_->AddObserver(this);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(
&AndroidSmsPairingStateTrackerImpl::AddCookieChangeListener,
weak_ptr_factory_.GetWeakPtr()));
}
AndroidSmsPairingStateTrackerImpl::~AndroidSmsPairingStateTrackerImpl() {
android_sms_app_manager_->RemoveObserver(this);
}
bool AndroidSmsPairingStateTrackerImpl::IsAndroidSmsPairingComplete() {
return was_paired_on_last_update_;
}
void AndroidSmsPairingStateTrackerImpl::AttemptFetchMessagesPairingState() {
GetCookieManager()->GetCookieList(
GetPairingUrl(), net::CookieOptions(),
base::BindOnce(&AndroidSmsPairingStateTrackerImpl::OnCookiesRetrieved,
base::Unretained(this)));
}
void AndroidSmsPairingStateTrackerImpl::OnCookiesRetrieved(
const std::vector<net::CanonicalCookie>& cookies,
const net::CookieStatusList& excluded_cookies) {
bool was_previously_paired = was_paired_on_last_update_;
for (const auto& cookie : cookies) {
if (cookie.Name() == kMessagesPairStateCookieName) {
PA_LOG(VERBOSE) << "Cookie says Messages paired: " << cookie.Value();
was_paired_on_last_update_ = cookie.Value() == kPairedCookieValue;
if (was_previously_paired != was_paired_on_last_update_)
NotifyPairingStateChanged();
return;
}
}
was_paired_on_last_update_ = false;
if (was_previously_paired != was_paired_on_last_update_)
NotifyPairingStateChanged();
}
void AndroidSmsPairingStateTrackerImpl::OnCookieChange(
const net::CanonicalCookie& cookie,
network::mojom::CookieChangeCause cause) {
DCHECK_EQ(kMessagesPairStateCookieName, cookie.Name());
DCHECK(cookie.IsDomainMatch(GetPairingUrl().host()));
// NOTE: cookie.Value() cannot be trusted in this callback. The cookie may
// have expired or been removed and the Value() does not get updated. It's
// cleanest to just re-fetch it.
AttemptFetchMessagesPairingState();
}
void AndroidSmsPairingStateTrackerImpl::OnInstalledAppUrlChanged() {
// If the app URL changed, stop any ongoing cookie monitoring and attempt to
// add a new change listener.
cookie_listener_receiver_.reset();
AddCookieChangeListener();
}
GURL AndroidSmsPairingStateTrackerImpl::GetPairingUrl() {
base::Optional<GURL> app_url = android_sms_app_manager_->GetCurrentAppUrl();
if (app_url)
return *app_url;
// If no app is installed, default to the normal messages URL.
return GetAndroidMessagesURL();
}
network::mojom::CookieManager*
AndroidSmsPairingStateTrackerImpl::GetCookieManager() {
return content::BrowserContext::GetStoragePartitionForSite(profile_,
GetPairingUrl())
->GetCookieManagerForBrowserProcess();
}
void AndroidSmsPairingStateTrackerImpl::AddCookieChangeListener() {
// Trigger the first fetch of the sms cookie and start listening for changes.
AttemptFetchMessagesPairingState();
GetCookieManager()->AddCookieChangeListener(
GetPairingUrl(), kMessagesPairStateCookieName,
cookie_listener_receiver_.BindNewPipeAndPassRemote());
}
} // namespace android_sms
} // namespace chromeos