1 // Copyright 2020 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.
4 
5 #include "chrome/browser/ui/ash/clipboard_image_model_factory_impl.h"
6 
7 #include "chrome/browser/profiles/profile.h"
8 
ClipboardImageModelFactoryImpl(Profile * primary_profile)9 ClipboardImageModelFactoryImpl::ClipboardImageModelFactoryImpl(
10     Profile* primary_profile)
11     : primary_profile_(primary_profile),
12       idle_timer_(FROM_HERE,
13                   base::TimeDelta::FromMinutes(2),
14                   this,
15                   &ClipboardImageModelFactoryImpl::OnRequestIdle) {
16   DCHECK(primary_profile_);
17 }
18 
19 ClipboardImageModelFactoryImpl::~ClipboardImageModelFactoryImpl() = default;
20 
Render(const base::UnguessableToken & id,const std::string & html_markup,ImageModelCallback callback)21 void ClipboardImageModelFactoryImpl::Render(const base::UnguessableToken& id,
22                                             const std::string& html_markup,
23                                             ImageModelCallback callback) {
24   DCHECK(!html_markup.empty());
25   pending_list_.emplace_front(id, html_markup, std::move(callback));
26   StartNextRequest();
27 }
28 
CancelRequest(const base::UnguessableToken & id)29 void ClipboardImageModelFactoryImpl::CancelRequest(
30     const base::UnguessableToken& id) {
31   if (request_ && request_->IsRunningRequest(id)) {
32     request_->Stop();
33     return;
34   }
35 
36   auto iter =
37       std::find_if(pending_list_.begin(), pending_list_.end(),
38                    [&id](const ClipboardImageModelRequest::Params& params) {
39                      return id == params.id;
40                    });
41   if (iter == pending_list_.end())
42     return;
43 
44   pending_list_.erase(iter);
45 }
46 
Activate()47 void ClipboardImageModelFactoryImpl::Activate() {
48   active_ = true;
49   StartNextRequest();
50 }
51 
Deactivate()52 void ClipboardImageModelFactoryImpl::Deactivate() {
53   active_ = false;
54 
55   if (!request_ || !request_->IsModifyingClipboard())
56     return;
57 
58   // Stop the currently running request if it is modifying the clipboard.
59   // ClipboardImageModelFactory is `Deactivate()`-ed prior to the user pasting
60   // and a modified clipboard could interfere with pasting from
61   // ClipboardHistory.
62   pending_list_.emplace_front(request_->StopAndGetParams());
63 }
64 
OnShutdown()65 void ClipboardImageModelFactoryImpl::OnShutdown() {
66   // Reset |request_| to drop its reference to Profile, specifically the
67   // RenderProcessHost of its WebContents.
68   request_.reset();
69 }
70 
StartNextRequest()71 void ClipboardImageModelFactoryImpl::StartNextRequest() {
72   if (pending_list_.empty() || !active_ ||
73       (request_ && request_->IsRunningRequest())) {
74     return;
75   }
76 
77   if (!request_) {
78     request_ = std::make_unique<ClipboardImageModelRequest>(
79         primary_profile_,
80         base::BindRepeating(&ClipboardImageModelFactoryImpl::StartNextRequest,
81                             weak_ptr_factory_.GetWeakPtr()));
82   }
83 
84   // Reset the timer that cleans up |request_|. If StartNextRequest() is not
85   // called again in 2 minutes, |request_| will be reset.
86   idle_timer_.Reset();
87   request_->Start(std::move(pending_list_.front()));
88   pending_list_.pop_front();
89 }
90 
OnRequestIdle()91 void ClipboardImageModelFactoryImpl::OnRequestIdle() {
92   if (!request_)
93     return;
94 
95   DCHECK(!request_->IsRunningRequest())
96       << "Running requests should timeout or complete before being cleaned up.";
97   request_.reset();
98 }
99