text:
\chapter{INTRODUCTION TO CHIRAL SYMMETRY}
\label{Intro}
\thispagestyle{empty}

\newpage

Chiral perturbation theory (CHPT)
is a systematic approach to formulate the standard model as a
quantum field theory at the hadronic level. In its general form, it
uses only the symmetries of the standard model, in particular its
spontaneously broken chiral symmetry.
It is characterized by an effective chiral
Lagrangian in terms of pseudoscalar meson fields (and possibly other
low-lying hadronic states) giving rise to a systematic low-energy
expansion of amplitudes \cite{Wein79,GL1}.

In the formulation of Ref.\cite{GL1}, one considers the generating
functional $Z[v,a,s,p]$ of
connected Green functions of quark currents associated
with the fundamental Lagrangian
\begin{equation}
{\cal L} = {\cal L}^0_{QCD} + \bar q \gamma^\mu (v_\mu + \gamma_5 a_\mu)q
- \bar q (s - i \gamma_5 p)q . \label{eq:QCD}
\end{equation}
${\cal L}^0_{QCD}$ is the QCD Lagrangian with the masses of the
three light quarks set to zero. The external fields $v_\mu$, $a_\mu$,
$s$ and $p$ are hermitian $3 \times 3$ matrices in flavour space.
To describe electromagnetic and semileptonic interactions, the
relevant external gauge fields of the standard model are
\footnote{We adopt the present conventions of the Particle Data
Group \cite{PDGR}.}
\begin{eqnarray}
r_\mu  =  v_\mu + a_\mu & = & - eQ  A_\mu
\label{eq:gf} \\*
l_\mu  =  v_\mu - a_\mu & = &  - eQ  A_\mu
        - \displaystyle \frac{e}{\sqrt{2}\sin{\theta_W}} (W^+_\mu T_+ + h.c.) \nonumber
\end{eqnarray} $$
Q = \displaystyle \frac{1}{3} \rm{diag}(2,-1,-1), \qquad
T_+ = \left( \begin{array}{ccc}
0 & V_{ud} & V_{us} \\
0 & 0 & 0 \\
0 & 0 & 0 \end{array} \right)  $$
where the $V_{ij}$ are Kobayashi--Maskawa matrix elements.
The quark mass matrix
\begin{equation}
{\cal M} = \mbox{diag}(m_u,m_d,m_s)
\end{equation}
is contained in the scalar field $s(x)$.
The Lagrangian (\ref{eq:QCD}) exhibits a local $SU(3)_L \times SU(3)_R$
symmetry
\begin{eqnarray}
q & \rightarrow & g_R \, \displaystyle \frac{1}{2} (1 + \gamma_5)q +
                  g_L \, \displaystyle \frac{1}{2} (1 - \gamma_5)q \nonumber \\*
r_\mu  & \rightarrow & g_R r_\mu g^\dagger_R +
                             i g_R \partial_\mu g^\dagger_R \nonumber \\*
l_\mu  & \rightarrow & g_L l_\mu g^\dagger_L +
                             i g_L \partial_\mu g^\dagger_L \\*
s + i p & \rightarrow & g_R (s + i p) g^\dagger_L \nonumber \\*
g_{R,L} & \in & SU(3)_{R,L}. \nonumber \end{eqnarray}

The generating functional $Z$ admits an expansion in powers of
external momenta and quark masses (CHPT).
In the meson sector at leading
order in CHPT, it is given by the classical action
\begin{equation}
Z = \int d^4 x {\cal L}_2 (U,v,a,s,p). \end{equation}
${\cal L}_2$ is the non-linear $\sigma$ model Lagrangian coupled to the
external fields $v,a,s,p$
\begin{equation}
{\cal L}_2 = \frac{F^2}{4} \langle D_\mu U D^\mu U^\dagger +
             \chi U^\dagger + \chi^\dagger U \rangle \label{eq:L2} \end{equation}
where
\begin{equation}
D_\mu U = \partial_\mu U - ir_\mu U + iU l_\mu, \qquad
\chi = 2 B_0(s + ip), \end{equation}
and $\langle A \rangle$ stands for the trace of the matrix $A$. $U$ is a
unitary $3 \times 3$ matrix
$$
U^\dagger U = {\bf 1}, \qquad \det U = 1,
$$
which transforms as
\begin{equation}
U \rightarrow g_R U g^\dagger_L \end{equation}
under $SU(3)_L \times SU(3)_R$.
$U$ incorporates the fields of the eight pseudoscalar Goldstone
bosons. A convenient parametrization is \footnote{We follow the
Condon-Shortley-de Swart phase conventions.}
\begin{equation}
U = \exp{(i\sqrt{2}\Phi/F)},\qquad
\Phi = \left( \begin{array}{ccc}
\displaystyle \frac{\pi^0}{\sqrt{2}} + \displaystyle \frac{\eta_8}{\sqrt{6}} & -\pi^+ & - K^+ \\*
\pi^- & -\displaystyle \frac{\pi^0}{\sqrt{2}} + \displaystyle \frac{\eta_8}{\sqrt{6}} & - K^0 \\*
K^- & -\overline{K^0} & - \displaystyle \frac{2 \eta_8}{\sqrt{6}} \end{array} \right). \end{equation}

The parameters $F$ and $B_0$ are the only free
constants at $O(p^2)$: $F$ is the pion decay constant
in the chiral limit,
\begin{equation}
F_\pi =  F(1 + O(m_{quark})) = 93.2 MeV , \end{equation}
whereas $B_0$ is related to the quark condensate,
\begin{equation}
\langle 0|\bar u u |0\rangle = - F^2 B_0(1 + O(m_{quark})). \end{equation}
$B_0$ always appears multiplied by quark masses. At $O(p^2)$, the
product $B_0 m_q$ can be expressed in terms of meson masses, e.g.
\begin{equation}
M^2_{\pi^+} = B_0 (m_u + m_d). \end{equation}

The Lagrangian (\ref{eq:L2}) is referred to as the effective chiral
Lagrangian of $O(p^2)$. The chiral counting rules are the following:
the field $U$ is of $O(p^0)$, the derivative $\partial_\mu$ and the
external gauge fields $v_\mu, a_\mu$ are terms of $O(p)$, and the
fields $s, p$ count as $O(p^2)$.

At order $p^4$ the generating functional consists of three terms
\cite{GL1} :
\begin{enumerate}
\item[i)] The  one-loop graphs generated by the lowest order Lagrangian
(\ref{eq:L2}).
\item[ii)] An explicit local action of order $p^4$.
\item[iii)] A contribution to account for the chiral anomaly.
\end{enumerate}

We briefly discuss the contributions ii) and iii)
and start with the local action of $O(p^4)$.
It is generated by the Lagrangian ${\cal L}_4$ \cite{GL1}:
\begin{eqnarray}
{\cal L}_4 & = & L_1 \langle D_\mu U^\dagger D^\mu U\rangle^2 +
                 L_2 \langle D_\mu U^\dagger D_\nu U\rangle
                     \langle D^\mu U^\dagger D^\nu U\rangle \nonumber \\*
& & + L_3 \langle D_\mu U^\dagger D^\mu U D_\nu U^\dagger D^\nu U\rangle +
    L_4 \langle D_\mu U^\dagger D^\mu U\rangle \langle \chi^\dagger U +
    \chi U^\dagger\rangle  \nonumber \\*
& & +L_5 \langle D_\mu U^\dagger D^\mu U(\chi^\dagger U + U^\dagger
\chi)\rangle
    +
    L_6 \langle \chi^\dagger U + \chi U^\dagger \rangle^2 +
    L_7 \langle \chi^\dagger U - \chi U^\dagger \rangle^2  \nonumber \\*
& & + L_8 \langle \chi^\dagger U \chi^\dagger U +
 \chi U^\dagger \chi U^\dagger\rangle
    -i L_9 \langle F_R^{\mu\nu} D_\mu U D_\nu U^\dagger +
      F_L^{\mu\nu} D_\mu U^\dagger D_\nu U \rangle \nonumber \\*
& & + L_{10} \langle U^\dagger F_R^{\mu\nu} U F_{L\mu\nu}\rangle +
    L_{11} \langle F_{R\mu\nu} F_R^{\mu\nu} + F_{L\mu\nu} F_L^{\mu\nu}\rangle +
    L_{12} \langle \chi^\dagger \chi \rangle,
\end{eqnarray}
where
\begin{eqnarray}
  F_R^{\mu\nu} & = & \partial^\mu r^\nu -
                     \partial^\nu r^\mu -
                     i [r^\mu,r^\nu]   \\*
  F_L^{\mu\nu} & = & \partial^\mu l^\nu -
                     \partial^\nu l^\mu -
                     i [l^\mu,l^\nu] . \nonumber
\end{eqnarray}
The twelve new low-energy couplings $L_1, \ldots, L_{12}$ arising
here are in general
divergent (except $L_3,L_7$). They absorb the divergences of the one-loop
graphs via the renormalization
\begin{eqnarray}
L_i&=&L_i^r +\Gamma_i \lambda
\nonumber \\
\lambda &=&(4\pi)^{-2}\mu^{d-4} \left\{ \frac{1}{d-4} - \frac{1}{2} \left(
{\mbox{ln}}(4\pi) +\Gamma'(1) +1 \right) \right\}
\end{eqnarray}
in the dimensional regularization scheme. The coefficients $\Gamma_i$ are
displayed in table \ref{tab:Li}. They govern the scale dependence of the
renormalized, finite couplings $L_i^r(\mu)$,
\begin{equation}
L_i^r(\mu_2) =L_i^r(\mu_1) + \frac{\Gamma_i}{16\pi^2} \ln\frac{\mu_1}{\mu_2} \;
\; . \label{eq:scale}
\end{equation}
Observable quantities are independent of the scale $\mu$, once the loop
contributions are included.

The constants $F,B_0$, together with $L_1^r,\ldots,L_{10}^r$,
completely determine the low-energy behaviour of pseudoscalar meson
interactions to $O(p^4)$. $L_{11}^r$ and $L_{12}^r$ are contact terms which
are not directly accessible to experiment.
Similarly to $F$ and $B_0$ discussed above, the constants $L_i^r$ are not
determined
by chiral symmetry $-$ they are fixed by the dynamics of the underlying theory
through the renormalization group invariant scale $\Lambda$ and by the heavy
quark masses $m_c,m_b,\ldots \; .$ With present techniques, it is, however, not
possible to evaluate them directly from the
QCD Lagrangian. In the absence of such
a calculational scheme, they have been determined by comparison with
experimental low-energy information and by using large$-N_C$ arguments.
The result is shown in column 2 of table \ref{tab:Li}, where
$L_1^r,\ldots,L_{10}^r$ are
displayed at the scale $\mu=M_{\rho}$. The experimental information
underlying these values is shown in column 3.
[$L_1,L_2$ and $L_3$ are taken from a recent overall
fit to $K_{e4}$ and $\pi \pi$ data \cite{Kl4Rig}, see also the section
on $K_{l4}$ decays in chapter \ref{semi} and Ref. \cite{Kl4Bij}.
$L_4,\ldots,L_{10}$ are from \cite{GL1}.
For $L_9$ see also \cite{BC88}.
In Refs. \cite{GL1,Res} it was shown that the values for the
$L^r_i(M_\rho)$ can be understood in terms of meson resonance exchange.
For recent attempts to evaluate $L_i$ directly from the QCD
Lagrangian see \cite{rafael}.]

\begin{table}[t]
\begin{center}
\caption{Phenomenological values and source for the renormalized coupling
constants $L^r_i(M_\rho)$.
The quantities $\Gamma_i$
in the fourth column determine the scale dependence of the $L^r_i(\mu)$
according to Eq. (\protect\ref{eq:scale}). $L_{11}^r$ and $L_{12}^r$ are not
directly accessible to experiment.} \label{tab:Li}
\vspace{.5cm}
\begin{tabular}{|c||r|l|r|}  \hline
i & $L^r_i(M_\rho) \times 10^3$ & source & $\Gamma_i$ \\ \hline
  1  & 0.7 $\pm$ 0.5 & $K_{e4},\pi\pi\rightarrow\pi\pi$ & 3/32  \\
  2  & 1.2 $\pm$ 0.4 &  $K_{e4},\pi\pi\rightarrow\pi\pi$&  3/16  \\
  3  & $-$3.6 $\pm$ 1.3 &$K_{e4},\pi\pi\rightarrow\pi\pi$&  0     \\
  4  & $-$0.3 $\pm$ 0.5 & Zweig rule &  1/8  \\
  5  & 1.4 $\pm$ 0.5  & $F_K:F_\pi$ & 3/8  \\
  6  & $-$0.2 $\pm$ 0.3 & Zweig rule &  11/144  \\
  7  & $-$0.4 $\pm$ 0.2 &Gell-Mann-Okubo,$L_5,L_8$ & 0             \\
  8  & 0.9 $\pm$ 0.3 & \small{$M_{K^0}-M_{K^+},L_5,$}&
5/48 \\
     &               &   \small{ $(2m_s-m_u-m_d):(m_d-m_u)$}       & \\
 9  & 6.9 $\pm$ 0.7 & $<r^2>_{em}^\pi$ & 1/4  \\
 10  & $-$5.5 $\pm$ 0.7& $\pi \rightarrow e \nu\gamma$  &  $-$ 1/4  \\
\hline
11   &               &                                & $-$1/8 \\
12   &               &                                & 5/24 \\
\hline
\end{tabular}
\end{center}
\end{table}

Here, it is of interest to know which of the low-energy couplings occur in the
matrix elements for the
semileptonic kaon decays discussed in chapter \ref{semi}.
This information is given in table \ref{tab:semili}.
(There is an ambiguity concerning the bookkeeping of $L_4$ and $L_5$: some of
these contributions may be absorbed into the physical decay constants
$F_\pi,F_K$. Here we have chosen the convention which corresponds to the
amplitudes displayed in chapter \ref{semi}.
 Furthermore, in $K_{\mu4}$ decays, additional constants  may occur via
the form factor $R$ which has not yet been worked out at one-loop level
\cite{colgass}. This channel is therefore omitted in the table.)

\begin{table}[t]
\protect
\begin{center}
\caption{Occurrence
of the low-energy coupling constants $L_1,\ldots,L_{10}$ and of
the anomaly  in the semileptonic decays discussed
in chapter \protect\ref{semi}.\label{tab:semili}
  }
\vspace{1em}
\begin{tabular}{|c||c|c|c|c|c|c|c|}  \hline
 & & & & & $K^+\rightarrow$ & $K^+\rightarrow$ & $K^0\rightarrow$
\\
     &
$K_{l2\gamma}$ &
$K_{l2ll}$    &
$K_{l3}$    &
$K_{l3\gamma}$&
$\pi^+\pi^-e^+\nu_e$&
$\pi^0\pi^0e^+\nu_e$&
$\pi^0\pi^-e^+\nu_e$ \\ \hline
 $L_1$ &      &      &      &      & $\times$ &$\times$ &
\\
 $L_2$&      &      &      &      & $\times$ &$\times$ &
\\
 $L_3$ &      &      &      &      & $\times$ &$\times$ & $\times$
\\
 $L_4$ &      &      &      &      & $\times$ &$\times$ &
\\
 $L_5$&       &      &      &      & $\times$ &$\times$ &$\times$
\\
 $L_9$&      &$\times$&$\times$&$\times$& $\times$ &$\times$ &$\times$
\\
 $L_9+L_{10}$ &$\times$&$\times$&      &$\times$&       & &
\\
\hline
Anomaly&$\times$&$\times$& &$\times$&$\times$&&$\times$
\\
\hline
\end{tabular}
\end{center}
\end{table}
We now turn to point iii) above.
A functional $Z[U,l,r]$ which reproduces the chiral anomaly
was first constructed by Wess and Zumino \cite{WZ}. For practical
purposes, it is useful to write it in the explicit form given by Witten
 \cite{Witten}:
\begin{eqnarray}
Z [U,l,r]_{WZW} &=&-\displaystyle \frac{i N_C}{240 \pi^2}
\int_{M^5} d^5x \epsilon^{ijklm} \langle \Sigma^L_i
\Sigma^L_j \Sigma^L_k \Sigma^L_l \Sigma^L_m \rangle \label{eq:WZW} \\*
 & & - \displaystyle \frac{i N_C}{48 \pi^2} \int d^4 x
\varepsilon_{\mu \nu \alpha \beta}\left( W (U,l,r)^{\mu \nu
\alpha \beta} - W ({\bf 1},l,r)^{\mu \nu \alpha \beta} \right)
\nonumber \\
W (U,l,r)_{\mu \nu \alpha \beta} & = &
\langle U l_{\mu} l_{\nu} l_{\alpha}U^{\dagger} r_{\beta}
+ \frac{1}{4} U l_{\mu} U^{\dagger} r_{\nu} U l_\alpha U^{\dagger} r_{\beta}
+ i U \partial_{\mu} l_{\nu} l_{\alpha} U^{\dagger} r_{\beta}
\nonumber  \\
& & + i \partial_{\mu} r_{\nu} U l_{\alpha} U^{\dagger} r_{\beta}
- i \Sigma^L_{\mu} l_{\nu} U^{\dagger} r_{\alpha} U l_{\beta}
+ \Sigma^L_{\mu} U^{\dagger} \partial_{\nu} r_{\alpha} U l_\beta
\nonumber \\
& & -\Sigma^L_{\mu} \Sigma^L_{\nu} U^{\dagger} r_{\alpha} U l_{\beta}
+ \Sigma^L_{\mu} l_{\nu} \partial_{\alpha} l_{\beta}
+ \Sigma^L_{\mu} \partial_{\nu} l_{\alpha} l_{\beta}  \\
& & - i \Sigma^L_{\mu} l_{\nu} l_{\alpha} l_{\beta}
+ \frac{1}{2} \Sigma^L_{\mu} l_{\nu} \Sigma^L_{\alpha} l_{\beta}
- i \Sigma^L_{\mu} \Sigma^L_{\nu} \Sigma^L_{\alpha} l_{\beta}\rangle
\nonumber \\
& & - \left( L \leftrightarrow R \right) \nonumber \end{eqnarray}
$$
\Sigma^L_\mu = U^{\dagger} \partial_\mu U \qquad
\Sigma^R_\mu = U \partial_\mu U^{\dagger} $$
$$ N_C = 3 \qquad \varepsilon_{0123} = 1  $$
where $\left( L \leftrightarrow R \right)$ stands for the interchange
$$
U \leftrightarrow U^\dagger, \qquad l_\mu \leftrightarrow r_\mu,
\qquad \Sigma^L_\mu \leftrightarrow \Sigma^R_\mu . $$
The integration in the first term in Eq. (\ref{eq:WZW}) is over a
five-dimensional
  manifold whose boundary is four-dimensional Minkowski space, such
that
\begin{equation}
\int_{M^5} d^5x \epsilon^{ijklm}\partial_m T_{ijkl}=\int d^4x \epsilon^{\mu \nu
\rho\sigma} T_{\mu \nu\rho\sigma}
\end{equation}
according to Stoke's theorem. [This term involves at least five pseudoscalar
fields and will not be needed in the following chapter.]   The convention used
in
Eq. (\ref{eq:WZW}) ensures that $Z[U,l,r]_{WZW}$ conserves parity and
reproduces the anomaly under $SU(3)_L\times SU(3)_R$ transformations in
Bardeen's form \cite{bardeen} (in particular, it  is invariant under
 transformations generated by the vector currents).

The Wess-Zumino-Witten functional contains all the
 anomalies which contribute to the semileptonic meson decays considered in the
following chapter. The relevant piece for e.g. $K_{l4}$ decays is
\begin{equation}
Z[U,l,r]_{WZW}=\frac{i\sqrt{2}}{ 4 \pi^2 F^3}
\int d^4 x \epsilon_{\mu \nu \rho \sigma}<\partial^\mu \Phi \partial^\nu \Phi
\partial^\rho \Phi v^\sigma> + \cdots \; \; .
\end{equation}

This short introduction to CHPT (see Refs.\cite{Georgi,Gasser} for more
extensive treatments with references to the original literature)
contains all the ingredients necessary
for the calculation of semileptonic $K$ decay amplitudes to $O(p^4)$
presented in the next chapter. For the low energies involved in these
decays, the momentum dependence of the $W$ propagator connecting to the
lepton-neutrino pair in the final state can be neglected.
The chiral realization of the
non-leptonic weak interactions is discussed in the corresponding
chapters on non-leptonic $K$ decays.

\newpage
\addcontentsline{toc}{section}{\hspace{1cm}Bibliography}

redpajama_set_name: RedPajamaArXiv


The Comfortaire mattress brand is something of a 'high-end' line of mattresses, which have been marketed over the years as symbols of luxury. Is that reputation really justified? Let's take a look at what make Comfortaire stand out, how their mattresses are made and most importantly how their customers really feel about their products.
Comfortaire is a relatively young company as far as bed manufacturers go, being founded specifically as an airbed company as opposed to the innerspring mattress companies that have long dominated the mattress market. Comfortaire's mission from the beginning was to create high quality springless mattresses that would provide superior comfort and support.
'Comfortaire' is more than just a luxurious sounding name – it actually relates directly to what makes Comfortaire unique amongst their competitors. A Comfortaire mattress includes an air layer in their design which helps achieve a better spinal alignment when you sleep, meaning Comfortaire beds can be good for your posture. Many mattresses actually misalign the sleeper's posture because their firmness doesn't allow the mattress to conform to the right shape for the body – so instead the body has to conform to the bed, thus going out of alignment.
But one of the other major benefits of having an air layer is that it makes the firmness of the bed highly adjustable. Each mattress comes with a control which allows you to actually change the firmness of the bed to match your own preference.
This is not to say that Comfortaire beds are simply airbeds – they're a little more advanced than that. The air layer is on top of a layer of foam, and beneath a layer of quilting which gives the surface of the mattress its soft and luxurious feel.
There are only a handful of beds in the Comfortaire mattress range, but one of the more popular of these is the Comfortaire Cerenity mattress. Most buyers of this model report being satisfied with the level of comfort and healthier sleep they've experienced, as well as being satisfied that they got what they paid for.
The Comfortaire Cerulean is another popular choice. Once again the adjustability of the mattress firmness ranks as one of the positive things many owners of this mattress report. Most customers also say they're happy with the pricing and feel they've got a good deal in terms of how much they spent.


A BuzzFeed News roundup of fake photos circulating in the wake of the shootings at a Munich shopping mall.
1. People are sharing this photo and saying it shows some of the victims of the shootings in Munich. But it's actually from South Africa.
The photo was first published in 2015 after an attack in South Africa.
2. Some are sharing this man's photo and identifying him as someone named Samuel Hydberg who is the shooter. That is not his name, and he is not a suspect in Munich.
And during the Oregon shooting.
People are now trying to fool news organizations into using photos of Hyde.
3. This photo allegedly shows showing people lying on the ground in Munich.
It's actually is from a police training in Manchester, England.
4. This photo is allegedly an aerial view of the Munich shooter.
But a closer inspection shows once again it's a photo of comedian Sam Hyde.
5. People are sharing this photo and claiming that it shows a shooter.
6. This photo of crime scene technicians was one in a series of images shared by a Twitter user in a tweet about Munich.
The photo is from Munich — but it was taken in May, after a man armed with a knife killed one person and injured three others.
This post is constantly being updated. Please check back for updates.


Right now, our repository makes to-do items available… and that's it. We need to be able to create, update, and delete to-do items as well. That's the focus on this tutorial: extending the repository for the full set of CRUD operations (Create, Read, Update, and Delete). And, along the way, we will extend our tests of the repository to match.
Right now, we do not need to do anything more elaborate than just appending the new model to the list.
That is fine for read-only operations, but once we start adding, editing, and deleting models, we are changing what is in the repository, and that may affect future tests using that repository. Ideally, we would use a fresh repository for each test method.
Our instrumentation tests happen to be in the same Java package as the production code. This means that we are doing white-box testing: we can access package-private members, such as constructors.
The hasItem() method will show up in red, as that is a static method that we can import. If you use Alt-Enter (Option-Return on macOS) for the import quick-fix, you will get a few candidate implementations, all from the hamcrest test library. Choose the org.hamcrest.Matchers.hasItem edition of the method to import.
If you run RepoTests again from the Android Studio toolbar — or by clicking on the double-play icon in the gutter next to the class declaration — you should see that this test succeeds.


text:
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/printing/cups_printers_manager.h"

#include <algorithm>
#include <map>
#include <memory>
#include <string>
#include <unordered_set>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "chrome/browser/ash/printing/enterprise_printers_provider.h"
#include "chrome/browser/ash/printing/printer_configurer.h"
#include "chrome/browser/ash/printing/printer_event_tracker.h"
#include "chrome/browser/ash/printing/printers_map.h"
#include "chrome/browser/ash/printing/server_printers_provider.h"
#include "chrome/browser/ash/printing/synced_printers_manager.h"
#include "chrome/browser/ash/printing/test_printer_configurer.h"
#include "chrome/browser/ash/printing/usb_printer_detector.h"
#include "chrome/browser/ash/printing/usb_printer_notification_controller.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/printing/ppd_provider.h"
#include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
#include "components/prefs/pref_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"

namespace ash {
namespace {

using ::chromeos::kPrinterId;
using ::chromeos::PpdProvider;
using ::chromeos::Printer;
using ::chromeos::PrinterClass;
using ::chromeos::PrinterSearchData;

// Fake backend for EnterprisePrintersProvider.  This allows us to poke
// arbitrary changes in the enterprise printer lists.
class FakeEnterprisePrintersProvider : public EnterprisePrintersProvider {
 public:
  FakeEnterprisePrintersProvider() = default;
  ~FakeEnterprisePrintersProvider() override = default;

  // Attach |observer| for notification of events.  |observer| is expected to
  // live on the same thread (UI) as this object.  OnPrinter* methods are
  // invoked inline so calling RegisterPrinter in response to OnPrinterAdded is
  // forbidden.
  void AddObserver(EnterprisePrintersProvider::Observer* observer) override {
    observers_.AddObserver(observer);
  }

  // Remove |observer| so that it no longer receives notifications.  After the
  // completion of this method, the |observer| can be safely destroyed.
  void RemoveObserver(EnterprisePrintersProvider::Observer* observer) override {
    observers_.RemoveObserver(observer);
  }

  // Fake manipulation functions.

  // Add the given printers to the list of enterprise printers and
  // notify observers.
  void AddEnterprisePrinters(const std::vector<Printer>& printers) {
    enterprise_printers_.insert(enterprise_printers_.end(), printers.begin(),
                                printers.end());
    for (Observer& observer : observers_) {
      observer.OnPrintersChanged(true, enterprise_printers_);
    }
  }

 private:
  base::ObserverList<EnterprisePrintersProvider::Observer>::Unchecked
      observers_;
  std::vector<Printer> enterprise_printers_;
};

// Fake backend for SyncedPrintersManager.  This allows us to poke arbitrary
// changes in the saved printer lists.
class FakeSyncedPrintersManager : public SyncedPrintersManager {
 public:
  FakeSyncedPrintersManager() = default;
  ~FakeSyncedPrintersManager() override = default;

  // Returns the printers that are saved in preferences.
  std::vector<Printer> GetSavedPrinters() const override {
    return saved_printers_;
  }

  // Attach |observer| for notification of events.  |observer| is expected to
  // live on the same thread (UI) as this object.  OnPrinter* methods are
  // invoked inline so calling RegisterPrinter in response to OnPrinterAdded is
  // forbidden.
  void AddObserver(SyncedPrintersManager::Observer* observer) override {
    observers_.AddObserver(observer);
  }

  // Remove |observer| so that it no longer receives notifications.  After the
  // completion of this method, the |observer| can be safely destroyed.
  void RemoveObserver(SyncedPrintersManager::Observer* observer) override {
    observers_.RemoveObserver(observer);
  }

  void UpdateSavedPrinter(const Printer& printer) override {
    if (!IsPrinterAlreadySaved(printer)) {
      SavePrinter(printer);
      return;
    }

    for (size_t i = 0; i < saved_printers_.size(); ++i) {
      if (saved_printers_[i].id() == printer.id()) {
        saved_printers_[i] = printer;
        break;
      }
    }

    NotifyOnSavedPrintersObservers();
  }

  bool RemoveSavedPrinter(const std::string& printer_id) override {
    for (auto it = saved_printers_.begin(); it != saved_printers_.end(); ++it) {
      if (it->id() == printer_id) {
        saved_printers_.erase(it);
        NotifyOnSavedPrintersObservers();
        return true;
      }
    }
    return false;
  }

  // Everything else in the interface we either don't use in
  // CupsPrintersManager, or just use in a simple pass-through manner that's not
  // worth additional layers of testing on top of the testing in
  // SyncedPrintersManager.
  PrintersSyncBridge* GetSyncBridge() override { return nullptr; }
  // Returns the printer with id |printer_id|, or nullptr if no such printer
  // exists.
  std::unique_ptr<Printer> GetPrinter(
      const std::string& printer_id) const override {
    return nullptr;
  }

  // Fake manipulation functions.

  // Add the given printers to the list of saved printers and
  // notify observers.
  void AddSavedPrinters(const std::vector<Printer>& printers) {
    saved_printers_.insert(saved_printers_.end(), printers.begin(),
                           printers.end());
    NotifyOnSavedPrintersObservers();
  }

  // Remove the printers with the given ids from the set of saved printers,
  // notify observers.
  void RemoveSavedPrinters(const std::unordered_set<std::string>& ids) {
    RemovePrinters(ids, &saved_printers_);
    NotifyOnSavedPrintersObservers();
  }

 private:
  void RemovePrinters(const std::unordered_set<std::string>& ids,
                      std::vector<Printer>* target) {
    auto new_end = std::remove_if(target->begin(), target->end(),
                                  [&ids](const Printer& printer) -> bool {
                                    return base::Contains(ids, printer.id());
                                  });

    target->resize(new_end - target->begin());
  }

  bool IsPrinterAlreadySaved(const Printer& printer) const {
    for (const Printer& saved_printer : saved_printers_) {
      if (printer.id() == saved_printer.id()) {
        return true;
      }
    }
    return false;
  }

  void SavePrinter(const Printer& printer) {
    DCHECK(!IsPrinterAlreadySaved(printer));

    saved_printers_.push_back(printer);

    NotifyOnSavedPrintersObservers();
  }

  void NotifyOnSavedPrintersObservers() const {
    for (Observer& observer : observers_) {
      observer.OnSavedPrintersChanged();
    }
  }

  base::ObserverList<SyncedPrintersManager::Observer>::Unchecked observers_;
  std::vector<Printer> saved_printers_;
};

class FakePrinterDetector : public PrinterDetector {
 public:
  FakePrinterDetector() {}
  ~FakePrinterDetector() override = default;

  void RegisterPrintersFoundCallback(OnPrintersFoundCallback cb) override {
    on_printers_found_callback_ = std::move(cb);
  }

  std::vector<DetectedPrinter> GetPrinters() override { return detections_; }

  void AddDetections(
      const std::vector<PrinterDetector::DetectedPrinter>& new_detections) {
    detections_.insert(detections_.end(), new_detections.begin(),
                       new_detections.end());
    on_printers_found_callback_.Run(detections_);
  }

  // Remove printers that have ids in ids.
  void RemoveDetections(const std::unordered_set<std::string>& ids) {
    auto new_end =
        std::remove_if(detections_.begin(), detections_.end(),
                       [&ids](const DetectedPrinter& detection) -> bool {
                         return base::Contains(ids, detection.printer.id());
                       });

    detections_.resize(new_end - detections_.begin());
    on_printers_found_callback_.Run(detections_);
  }

 private:
  std::vector<DetectedPrinter> detections_;
  OnPrintersFoundCallback on_printers_found_callback_;
};

// Fake PpdProvider backend.  This fake generates PpdReferences based on
// the passed make_and_model strings using these rules:
//
// If make_and_model is empty, then we say NOT_FOUND
// Otherwise, generate a ppd reference with make_and_model[0] as
// the effective make and model in the PpdReference.
class FakePpdProvider : public PpdProvider {
 public:
  FakePpdProvider() {}

  void ResolvePpdReference(const PrinterSearchData& search_data,
                           ResolvePpdReferenceCallback cb) override {
    if (search_data.make_and_model.empty()) {
      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE,
          base::BindOnce(std::move(cb), PpdProvider::NOT_FOUND,
                         Printer::PpdReference(), usb_manufacturer_));
    } else {
      Printer::PpdReference ret;
      ret.effective_make_and_model = search_data.make_and_model[0];
      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE, base::BindOnce(std::move(cb), PpdProvider::SUCCESS, ret,
                                    "" /* usb_manufacturer */));
    }
  }

  void SetUsbManufacturer(const std::string& manufacturer) {
    usb_manufacturer_ = manufacturer;
  }

  // These methods are not used by CupsPrintersManager.
  void ResolvePpd(const Printer::PpdReference& reference,
                  ResolvePpdCallback cb) override {}
  void ResolveManufacturers(ResolveManufacturersCallback cb) override {}
  void ResolvePrinters(const std::string& manufacturer,
                       ResolvePrintersCallback cb) override {}
  void ResolvePpdLicense(base::StringPiece effective_make_and_model,
                         ResolvePpdLicenseCallback cb) override {}
  void ReverseLookup(const std::string& effective_make_and_model,
                     ReverseLookupCallback cb) override {}

 private:
  ~FakePpdProvider() override {}
  std::string usb_manufacturer_;
};

// Expect that the printers in printers have the given ids, without
// considering order.
void ExpectPrinterIdsAre(const std::vector<Printer>& printers,
                         const std::vector<std::string>& ids) {
  std::vector<std::string> found_ids;
  for (const Printer& printer : printers) {
    found_ids.push_back(printer.id());
  }
  std::sort(found_ids.begin(), found_ids.end());
  std::vector<std::string> sorted_ids(ids);
  std::sort(sorted_ids.begin(), sorted_ids.end());
  EXPECT_EQ(sorted_ids, found_ids);
}

class FakeUsbPrinterNotificationController
    : public UsbPrinterNotificationController {
 public:
  FakeUsbPrinterNotificationController() = default;
  ~FakeUsbPrinterNotificationController() override = default;

  void ShowEphemeralNotification(const Printer& printer) override {
    NOTIMPLEMENTED();
  }
  void ShowConfigurationNotification(const Printer& printer) override {
    configuration_notifications_.insert(printer.id());
  }
  void ShowSavedNotification(const Printer& printer) override {
    saved_notifications_.insert(printer.id());
  }
  void RemoveNotification(const std::string& printer_id) override {
    saved_notifications_.erase(printer_id);
    configuration_notifications_.erase(printer_id);
  }
  bool IsNotificationDisplayed(const std::string& printer_id) const override {
    return configuration_notifications_.contains(printer_id) ||
           saved_notifications_.contains(printer_id);
  }

  bool IsSavedNotification(const std::string& printer_id) const {
    return saved_notifications_.contains(printer_id);
  }

  bool IsConfigurationNotification(const std::string& printer_id) const {
    return configuration_notifications_.contains(printer_id);
  }

 private:
  base::flat_set<std::string> saved_notifications_;
  base::flat_set<std::string> configuration_notifications_;
};

class FakePrintServersManager : public PrintServersManager {
 public:
  FakePrintServersManager() = default;
  ~FakePrintServersManager() override = default;

  void AddObserver(Observer* observer) override { observer_ = observer; }
  void RemoveObserver(Observer* observer) override { observer_ = nullptr; }
  void ChoosePrintServer(
      const std::vector<std::string>& selected_print_server_ids) override {}
  PrintServersConfig GetPrintServersConfig() const override {
    return PrintServersConfig();
  }

  void ServerPrintersChanged(
      const std::vector<PrinterDetector::DetectedPrinter>& printers) {
    observer_->OnServerPrintersChanged(printers);
  }

 private:
  Observer* observer_;
};

class CupsPrintersManagerTest : public testing::Test,
                                public CupsPrintersManager::Observer {
 public:
  CupsPrintersManagerTest() : ppd_provider_(new FakePpdProvider) {
    // Zeroconf and usb detector ownerships are taken by the manager, so we
    // have to keep raw pointers to them.
    auto zeroconf_detector = std::make_unique<FakePrinterDetector>();
    zeroconf_detector_ = zeroconf_detector.get();
    auto usb_detector = std::make_unique<FakePrinterDetector>();
    usb_detector_ = usb_detector.get();
    auto printer_configurer = std::make_unique<TestPrinterConfigurer>();
    printer_configurer_ = printer_configurer.get();
    auto usb_notif_controller =
        std::make_unique<FakeUsbPrinterNotificationController>();
    usb_notif_controller_ = usb_notif_controller.get();
    auto enterprise_printers_provider =
        std::make_unique<FakeEnterprisePrintersProvider>();
    enterprise_printers_provider_ = enterprise_printers_provider.get();
    auto print_servers_manager = std::make_unique<FakePrintServersManager>();
    print_servers_manager_ = print_servers_manager.get();

    // Register the pref |UserPrintersAllowed|
    CupsPrintersManager::RegisterProfilePrefs(pref_service_.registry());

    manager_ = CupsPrintersManager::CreateForTesting(
        &synced_printers_manager_, std::move(usb_detector),
        std::move(zeroconf_detector), ppd_provider_,
        std::move(printer_configurer), std::move(usb_notif_controller),
        std::move(print_servers_manager),
        std::move(enterprise_printers_provider), &event_tracker_,
        &pref_service_);
    manager_->AddObserver(this);
  }

  ~CupsPrintersManagerTest() override {
    // Fast forwarding so that delayed tasks like |SendScannerCountToUMA| will
    // run and not leak memory in unused callbacks.
    task_environment_.FastForwardUntilNoTasksRemain();
  }

  // CupsPrintersManager::Observer implementation
  void OnPrintersChanged(PrinterClass printer_class,
                         const std::vector<Printer>& printers) override {
    observed_printers_[printer_class] = printers;
  }

  // Check that, for the given printer class, the printers we have from the
  // observation callback and the printers we have when we query the manager
  // are both the same and have the passed ids.
  void ExpectPrintersInClassAre(PrinterClass printer_class,
                                const std::vector<std::string>& ids) {
    ExpectPrinterIdsAre(manager_->GetPrinters(printer_class), ids);
    ExpectPrinterIdsAre(observed_printers_[printer_class], ids);
  }

  void UpdatePolicyValue(const char* name, bool value) {
    auto value_ptr = std::make_unique<base::Value>(value);
    // TestingPrefSyncableService assumes ownership of |value_ptr|.
    pref_service_.SetManagedPref(name, std::move(value_ptr));
  }

  static PrintServer CreatePrintServer(std::string id,
                                       std::string server_url,
                                       std::string name) {
    GURL url(server_url);
    PrintServer print_server(id, url, name);
    return print_server;
  }

 protected:
  // Everything from PrintServersProvider must be called on Chrome_UIThread
  // Note: MainThreadType::IO is strictly about requesting a specific
  // MessagePumpType for the main thread. It has nothing to do with
  // BrowserThread::UI or BrowserThread::IO which are named threads in the
  // //content/browser code.
  // See
  // //docs/threading_and_tasks_testing.md#mainthreadtype-trait
  content::BrowserTaskEnvironment task_environment_{
      base::test::TaskEnvironment::MainThreadType::IO,
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};

  // Captured printer lists from observer callbacks.
  base::flat_map<PrinterClass, std::vector<Printer>> observed_printers_;

  // Backend fakes driving the CupsPrintersManager.
  FakeSyncedPrintersManager synced_printers_manager_;
  FakeEnterprisePrintersProvider* enterprise_printers_provider_;  // Not owned.
  FakePrinterDetector* usb_detector_;                             // Not owned.
  FakePrinterDetector* zeroconf_detector_;                        // Not owned.
  TestPrinterConfigurer* printer_configurer_;                     // Not owned.
  FakeUsbPrinterNotificationController* usb_notif_controller_;    // Not owned.
  FakePrintServersManager* print_servers_manager_;                // Not owned.
  scoped_refptr<FakePpdProvider> ppd_provider_;

  // This is unused, it's just here for memory ownership.
  PrinterEventTracker event_tracker_;

  // PrefService used to register the |UserPrintersAllowed| pref and
  // change its value for testing.
  sync_preferences::TestingPrefServiceSyncable pref_service_;

  // The manager being tested.  This must be declared after the fakes, as its
  // initialization must come after that of the fakes.
  std::unique_ptr<CupsPrintersManager> manager_;

  // Manages active networks.
  network_config::CrosNetworkConfigTestHelper cros_network_config_helper_;
};

// Pseudo-constructor for inline creation of a DetectedPrinter that should (in
// this test) be handled as a Discovered printer (because it has no make and
// model information, and that's now the FakePpdProvider is set up to
// determine whether or not something has a Ppd available).
PrinterDetector::DetectedPrinter MakeDiscoveredPrinter(const std::string& id,
                                                       const std::string& uri) {
  PrinterDetector::DetectedPrinter ret;
  ret.printer.set_id(id);
  ret.printer.SetUri(uri);
  return ret;
}

// Calls MakeDiscoveredPrinter with empty uri.
PrinterDetector::DetectedPrinter MakeDiscoveredPrinter(const std::string& id) {
  return MakeDiscoveredPrinter(id, "" /* uri */);
}

// Calls MakeDiscoveredPrinter with the USB protocol as the uri.
PrinterDetector::DetectedPrinter MakeUsbDiscoveredPrinter(
    const std::string& id) {
  return MakeDiscoveredPrinter(id, "usb://host/path");
}

// Pseudo-constructor for inline creation of a DetectedPrinter that should (in
// this test) be handled as an Automatic printer (because it has a make and
// model string).
PrinterDetector::DetectedPrinter MakeAutomaticPrinter(const std::string& id) {
  PrinterDetector::DetectedPrinter ret;
  ret.printer.set_id(id);
  ret.ppd_search_data.make_and_model.push_back("make and model string");
  return ret;
}

// Test that Enterprise printers from SyncedPrinterManager are
// surfaced appropriately.
TEST_F(CupsPrintersManagerTest, GetEnterprisePrinters) {
  enterprise_printers_provider_->AddEnterprisePrinters(
      {Printer("Foo"), Printer("Bar")});
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kEnterprise, {"Foo", "Bar"});
}

// Test that Saved printers from SyncedPrinterManager are
// surfaced appropriately.
TEST_F(CupsPrintersManagerTest, GetSavedPrinters) {
  synced_printers_manager_.AddSavedPrinters({Printer("Foo"), Printer("Bar")});
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Foo", "Bar"});
}

// Test that USB printers from the usb detector are converted to 'Printer's
// and surfaced appropriately.  One printer should be "automatic" because it
// has a findable Ppd, the other should be "discovered".
TEST_F(CupsPrintersManagerTest, GetUsbPrinters) {
  usb_detector_->AddDetections({MakeDiscoveredPrinter("DiscoveredPrinter"),
                                MakeAutomaticPrinter("AutomaticPrinter")});
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter"});
}

// Same as GetUsbPrinters, only for Zeroconf printers.
TEST_F(CupsPrintersManagerTest, GetZeroconfPrinters) {
  zeroconf_detector_->AddDetections({MakeDiscoveredPrinter("DiscoveredPrinter"),
                                     MakeAutomaticPrinter("AutomaticPrinter")});
  synced_printers_manager_.AddSavedPrinters({Printer("Foo"), Printer("Bar")});

  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter"});
}

// Test that printers that appear in either a Saved or Enterprise set do
// *not* appear in Discovered or Automatic, even if they are detected as such.
TEST_F(CupsPrintersManagerTest, SyncedPrintersTrumpDetections) {
  zeroconf_detector_->AddDetections(
      {MakeDiscoveredPrinter("DiscoveredPrinter0"),
       MakeDiscoveredPrinter("DiscoveredPrinter1"),
       MakeAutomaticPrinter("AutomaticPrinter0"),
       MakeAutomaticPrinter("AutomaticPrinter1")});
  task_environment_.RunUntilIdle();
  // Before we muck with anything else, check that automatic and discovered
  // classes are what we intended to set up.
  ExpectPrintersInClassAre(PrinterClass::kDiscovered,
                           {"DiscoveredPrinter0", "DiscoveredPrinter1"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic,
                           {"AutomaticPrinter0", "AutomaticPrinter1"});

  // Save both the Discovered and Automatic printers.  This should put them
  // into the Saved class and thus *remove* them from their previous
  // classes.
  manager_->PrinterInstalled(Printer("DiscoveredPrinter0"),
                             /*is_automatic=*/true);
  manager_->SavePrinter(Printer("DiscoveredPrinter0"));
  manager_->PrinterInstalled(Printer("AutomaticPrinter0"),
                             /*is_automatic=*/true);
  manager_->SavePrinter(Printer("AutomaticPrinter0"));
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter1"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter1"});
  ExpectPrintersInClassAre(PrinterClass::kSaved,
                           {"DiscoveredPrinter0", "AutomaticPrinter0"});
}

// Test updates of saved printers.  Updates of existing saved printers
// should propagate.  Updates of printers in other classes should result in
// those printers becoming saved.  Updates of unknown printers should
// result in a new saved printer.
TEST_F(CupsPrintersManagerTest, SavePrinter) {
  // Start with a printer in each class named after the class it's in, except
  // Enterprise which is not relevant to this test.
  Printer existing_saved("Saved");
  synced_printers_manager_.AddSavedPrinters({existing_saved});
  usb_detector_->AddDetections({MakeDiscoveredPrinter("Discovered")});
  zeroconf_detector_->AddDetections({MakeAutomaticPrinter("Automatic")});
  task_environment_.RunUntilIdle();

  // Sanity check that we do, indeed, have one printer in each class.
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Saved"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"Automatic"});
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"Discovered"});

  // Update the existing saved printer.  Check that the new display name
  // propagated.
  existing_saved.set_display_name("New Display Name");
  manager_->SavePrinter(existing_saved);
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Saved"});
  EXPECT_EQ(manager_->GetPrinters(PrinterClass::kSaved)[0].display_name(),
            "New Display Name");

  // Do the same thing for the Automatic and Discovered printers.
  // Create a configuration for the zeroconf printer, which should shift it
  // into the saved category.
  manager_->SavePrinter(Printer("Automatic"));
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {});
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Automatic", "Saved"});

  manager_->SavePrinter(Printer("Discovered"));
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {});
  ExpectPrintersInClassAre(PrinterClass::kSaved,
                           {"Automatic", "Saved", "Discovered"});

  // Save a printer we haven't seen before, which should just add it to
  // kSaved.
  manager_->SavePrinter(Printer("NewFangled"));
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kSaved,
                           {"Automatic", "Saved", "Discovered", "NewFangled"});

  // Remove the automatic printer, make sure it ends up back in the automatic
  // class after removal.
  manager_->RemoveSavedPrinter("Automatic");
  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kSaved,
                           {"Saved", "Discovered", "NewFangled"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"Automatic"});
}

// Test that GetPrinter() finds printers in any class, and returns null if
// a printer is not found.
TEST_F(CupsPrintersManagerTest, GetPrinter) {
  synced_printers_manager_.AddSavedPrinters({Printer("Saved")});
  enterprise_printers_provider_->AddEnterprisePrinters({Printer("Enterprise")});
  usb_detector_->AddDetections({MakeDiscoveredPrinter("Discovered")});
  zeroconf_detector_->AddDetections({MakeAutomaticPrinter("Automatic")});
  task_environment_.RunUntilIdle();

  for (const std::string& id :
       {"Saved", "Enterprise", "Discovered", "Automatic"}) {
    absl::optional<Printer> printer = manager_->GetPrinter(id);
    ASSERT_TRUE(printer);
    EXPECT_EQ(printer->id(), id);
  }

  absl::optional<Printer> printer = manager_->GetPrinter("Nope");
  EXPECT_FALSE(printer);
}

// Test that if |UserPrintersAllowed| pref is set to false, then
// GetPrinters() will only return printers from
// |PrinterClass::kEnterprise|.
TEST_F(CupsPrintersManagerTest, GetPrintersUserNativePrintersDisabled) {
  synced_printers_manager_.AddSavedPrinters({Printer("Saved")});
  enterprise_printers_provider_->AddEnterprisePrinters({Printer("Enterprise")});
  task_environment_.RunUntilIdle();

  // Disable the use of non-enterprise printers.
  UpdatePolicyValue(prefs::kUserPrintersAllowed, false);

  // Verify that non-enterprise printers are not returned by GetPrinters()
  std::vector<Printer> saved_printers =
      manager_->GetPrinters(PrinterClass::kSaved);
  ExpectPrinterIdsAre(saved_printers, {});

  // Verify that enterprise printers are returned by GetPrinters()
  std::vector<Printer> enterprise_printers =
      manager_->GetPrinters(PrinterClass::kEnterprise);
  ExpectPrinterIdsAre(enterprise_printers, {"Enterprise"});
}

// Test that if |UserPrintersAllowed| pref is set to false, then
// SavePrinter() will simply do nothing.
TEST_F(CupsPrintersManagerTest, SavePrinterUserNativePrintersDisabled) {
  // Start by installing a saved printer to be used to test than any
  // changes made to the printer will not be propagated.
  Printer existing_saved("Saved");
  synced_printers_manager_.AddSavedPrinters({existing_saved});
  usb_detector_->AddDetections({MakeDiscoveredPrinter("Discovered")});
  zeroconf_detector_->AddDetections({MakeAutomaticPrinter("Automatic")});
  task_environment_.RunUntilIdle();

  // Sanity check that we do, indeed, have one printer in each class.
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Saved"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"Automatic"});
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"Discovered"});

  // Disable the use of non-enterprise printers.
  UpdatePolicyValue(prefs::kUserPrintersAllowed, false);

  // Update the existing saved printer. Verify that the changes did not
  // progogate.
  existing_saved.set_display_name("New Display Name");
  manager_->SavePrinter(existing_saved);
  task_environment_.RunUntilIdle();

  // Reenable user printers in order to do checking.
  UpdatePolicyValue(prefs::kUserPrintersAllowed, true);
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Saved"});
  EXPECT_EQ(manager_->GetPrinters(PrinterClass::kSaved)[0].display_name(), "");
  UpdatePolicyValue(prefs::kUserPrintersAllowed, false);

  // Attempt to update the Automatic and Discovered printers. In both cases
  // check that the printers do not move into the saved category.
  manager_->SavePrinter(Printer("Automatic"));
  task_environment_.RunUntilIdle();
  UpdatePolicyValue(prefs::kUserPrintersAllowed, true);
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"Automatic"});
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Saved"});
  UpdatePolicyValue(prefs::kUserPrintersAllowed, false);

  manager_->SavePrinter(Printer("Discovered"));
  task_environment_.RunUntilIdle();
  UpdatePolicyValue(prefs::kUserPrintersAllowed, true);
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"Discovered"});
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Saved"});
  UpdatePolicyValue(prefs::kUserPrintersAllowed, false);

  // Attempt to update a printer that we haven't seen before, check that
  // nothing changed.
  manager_->SavePrinter(Printer("NewFangled"));
  task_environment_.RunUntilIdle();
  UpdatePolicyValue(prefs::kUserPrintersAllowed, true);
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Saved"});
}

// Test that if |UserPrintersAllowed| pref is set to false GetPrinter only
// returns a printer when the given printer id corresponds to an enterprise
// printer. Otherwise, it returns nothing.
TEST_F(CupsPrintersManagerTest, GetPrinterUserNativePrintersDisabled) {
  synced_printers_manager_.AddSavedPrinters({Printer("Saved")});
  enterprise_printers_provider_->AddEnterprisePrinters({Printer("Enterprise")});
  task_environment_.RunUntilIdle();

  // Sanity check that the printers were added.
  ExpectPrintersInClassAre(PrinterClass::kSaved, {"Saved"});
  ExpectPrintersInClassAre(PrinterClass::kEnterprise, {"Enterprise"});

  // Disable the use of non-enterprise printers.
  UpdatePolicyValue(prefs::kUserPrintersAllowed, false);

  absl::optional<Printer> saved_printer = manager_->GetPrinter("Saved");
  EXPECT_FALSE(saved_printer);

  absl::optional<Printer> enterprise_printer =
      manager_->GetPrinter("Enterprise");
  ASSERT_TRUE(enterprise_printer);
  EXPECT_EQ(enterprise_printer->id(), "Enterprise");
}

TEST_F(CupsPrintersManagerTest, SetUsbManufacturer) {
  const std::string& expected_manufacturer = "HP";
  ppd_provider_->SetUsbManufacturer(expected_manufacturer);
  usb_detector_->AddDetections({MakeUsbDiscoveredPrinter("DiscoveredPrinter")});
  task_environment_.RunUntilIdle();

  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});

  EXPECT_EQ(
      expected_manufacturer,
      manager_->GetPrinter("DiscoveredPrinter")->usb_printer_manufacturer());
}

TEST_F(CupsPrintersManagerTest, EmptyUsbManufacturer) {
  usb_detector_->AddDetections({MakeUsbDiscoveredPrinter("DiscoveredPrinter")});
  task_environment_.RunUntilIdle();

  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});

  EXPECT_TRUE(manager_->GetPrinter("DiscoveredPrinter")
                  ->usb_printer_manufacturer()
                  .empty());
}

TEST_F(CupsPrintersManagerTest, PrinterNotInstalled) {
  Printer printer(kPrinterId);
  EXPECT_FALSE(manager_->IsPrinterInstalled(printer));
}

TEST_F(CupsPrintersManagerTest, PrinterIsInstalled) {
  Printer printer(kPrinterId);
  manager_->PrinterInstalled(printer, /*is_automatic=*/false);
  EXPECT_TRUE(manager_->IsPrinterInstalled(printer));
}

// Test that we detect that the configuration is stale when any of the
// relevant fields change.
TEST_F(CupsPrintersManagerTest, UpdatedPrinterConfiguration) {
  Printer printer(kPrinterId);
  manager_->PrinterInstalled(printer, /*is_automatic=*/false);

  Printer updated(printer);
  updated.SetUri("ipp://different.value");
  EXPECT_FALSE(manager_->IsPrinterInstalled(updated));

  updated = printer;
  updated.mutable_ppd_reference()->autoconf = true;
  EXPECT_FALSE(manager_->IsPrinterInstalled(updated));

  updated = printer;
  updated.mutable_ppd_reference()->user_supplied_ppd_url = "different value";
  EXPECT_FALSE(manager_->IsPrinterInstalled(updated));

  updated = printer;
  updated.mutable_ppd_reference()->effective_make_and_model = "different value";
  EXPECT_FALSE(manager_->IsPrinterInstalled(updated));

  updated = printer;
  updated.mutable_ppd_reference()->autoconf = true;
  EXPECT_FALSE(manager_->IsPrinterInstalled(updated));

  // Sanity check, configuration for the original printers should still be
  // current.
  EXPECT_TRUE(manager_->IsPrinterInstalled(printer));
}

// Test that we can save non-discovered printers.
TEST_F(CupsPrintersManagerTest, SavePrinterSucceedsOnManualPrinter) {
  Printer printer(kPrinterId);
  printer.SetUri("ipp://manual.uri");
  manager_->SavePrinter(printer);

  auto saved_printers = manager_->GetPrinters(PrinterClass::kSaved);
  ASSERT_EQ(1u, saved_printers.size());
  EXPECT_EQ(printer.uri(), saved_printers[0].uri());
}

// Test that installing a printer does not put it in the saved class.
TEST_F(CupsPrintersManagerTest, PrinterInstalledDoesNotSavePrinter) {
  Printer printer(kPrinterId);
  manager_->PrinterInstalled(printer, /*is_automatic=*/false);

  auto saved_printers = manager_->GetPrinters(PrinterClass::kSaved);
  EXPECT_EQ(0u, saved_printers.size());
}

// Test that calling SavePrinter() when printer configuration change updates
// the saved printer but does not install the updated printer.
TEST_F(CupsPrintersManagerTest, SavePrinterUpdatesPreviouslyInstalledPrinter) {
  Printer printer(kPrinterId);
  manager_->PrinterInstalled(printer, /*is_automatic=*/false);
  manager_->SavePrinter(printer);
  EXPECT_TRUE(manager_->IsPrinterInstalled(printer));

  Printer updated(printer);
  updated.SetUri("ipps://different/value");
  EXPECT_FALSE(manager_->IsPrinterInstalled(updated));

  manager_->SavePrinter(updated);
  auto saved_printers = manager_->GetPrinters(PrinterClass::kSaved);
  ASSERT_EQ(1u, saved_printers.size());
  EXPECT_EQ(updated.uri(), saved_printers[0].uri());

  // Even though the updated printer was saved, it still needs to be marked as
  // installed again.
  EXPECT_FALSE(manager_->IsPrinterInstalled(updated));
}

// Automatic USB Printer is configured automatically.
TEST_F(CupsPrintersManagerTest, AutomaticUsbPrinterIsInstalledAutomatically) {
  auto automatic_printer = MakeAutomaticPrinter(kPrinterId);
  automatic_printer.printer.SetUri("usb://host/path");

  usb_detector_->AddDetections({automatic_printer});

  task_environment_.RunUntilIdle();

  EXPECT_TRUE(printer_configurer_->IsConfigured(kPrinterId));
}

// Automatic USB Printer is *not* configured if |UserPrintersAllowed|
// pref is set to false.
TEST_F(CupsPrintersManagerTest, AutomaticUsbPrinterNotInstalledAutomatically) {
  // Disable the use of non-enterprise printers.
  UpdatePolicyValue(prefs::kUserPrintersAllowed, false);

  auto automatic_printer = MakeAutomaticPrinter(kPrinterId);
  automatic_printer.printer.SetUri("usb://host/path");

  zeroconf_detector_->AddDetections({automatic_printer});

  task_environment_.RunUntilIdle();

  EXPECT_FALSE(manager_->IsPrinterInstalled(automatic_printer.printer));
}

// Nearby printers that are not automatic & USB are not automatically
// installed.
TEST_F(CupsPrintersManagerTest, OtherNearbyPrintersNotInstalledAutomatically) {
  auto discovered_printer = MakeDiscoveredPrinter("Discovered");
  discovered_printer.printer.SetUri("usb://host/path");
  auto automatic_printer = MakeAutomaticPrinter("Automatic");

  usb_detector_->AddDetections({discovered_printer});
  zeroconf_detector_->AddDetections({automatic_printer});

  task_environment_.RunUntilIdle();

  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"Discovered"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"Automatic"});
  EXPECT_FALSE(printer_configurer_->IsConfigured("Discovered"));
  EXPECT_FALSE(printer_configurer_->IsConfigured("Automatic"));
}

TEST_F(CupsPrintersManagerTest, DetectedUsbPrinterConfigurationNotification) {
  auto discovered_printer = MakeDiscoveredPrinter("Discovered");
  discovered_printer.printer.SetUri("usb://host/path");

  usb_detector_->AddDetections({discovered_printer});
  task_environment_.RunUntilIdle();

  EXPECT_TRUE(usb_notif_controller_->IsConfigurationNotification("Discovered"));

  usb_detector_->RemoveDetections({"Discovered"});

  EXPECT_FALSE(
      usb_notif_controller_->IsConfigurationNotification("Discovered"));
}

TEST_F(CupsPrintersManagerTest,
       DetectedZeroconfDiscoveredPrinterNoNotification) {
  auto discovered_printer = MakeDiscoveredPrinter("Discovered");
  discovered_printer.printer.SetUri("ipp://host");

  zeroconf_detector_->AddDetections({discovered_printer});
  task_environment_.RunUntilIdle();

  EXPECT_FALSE(
      usb_notif_controller_->IsConfigurationNotification("Discovered"));
}

// Test that RecordNearbyNetworkPrinterCounts logs the total number of
// detected network printers.
TEST_F(CupsPrintersManagerTest, RecordTotalNetworkPrinterCounts) {
  base::HistogramTester histogram_tester;
  manager_->SavePrinter(Printer("DiscoveredNetworkPrinter0"));
  usb_detector_->AddDetections({MakeDiscoveredPrinter("DiscoveredUSBPrinter"),
                                MakeAutomaticPrinter("AutomaticUSBPrinter")});
  manager_->RecordNearbyNetworkPrinterCounts();
  task_environment_.RunUntilIdle();
  histogram_tester.ExpectBucketCount("Printing.CUPS.TotalNetworkPrintersCount",
                                     0, 1);
  zeroconf_detector_->AddDetections(
      {MakeDiscoveredPrinter("DiscoveredNetworkPrinter0"),
       MakeDiscoveredPrinter("DiscoveredNetworkPrinter1"),
       MakeAutomaticPrinter("AutomaticNetworkPrinter0"),
       MakeAutomaticPrinter("AutomaticNetworkPrinter1")});
  manager_->RecordNearbyNetworkPrinterCounts();
  task_environment_.RunUntilIdle();
  histogram_tester.ExpectBucketCount("Printing.CUPS.TotalNetworkPrintersCount",
                                     4, 1);
}

// Test that RecordNearbyNetworkPrinterCounts logs the number of
// all nearby (not already saved) detected network printers.
TEST_F(CupsPrintersManagerTest, RecordNearbyNetworkPrinterCounts) {
  base::HistogramTester histogram_tester;
  usb_detector_->AddDetections({MakeDiscoveredPrinter("DiscoveredUSBPrinter"),
                                MakeAutomaticPrinter("AutomaticUSBPrinter")});
  manager_->RecordNearbyNetworkPrinterCounts();
  task_environment_.RunUntilIdle();
  histogram_tester.ExpectBucketCount("Printing.CUPS.NearbyNetworkPrintersCount",
                                     0, 1);
  manager_->SavePrinter(Printer("DiscoveredNetworkPrinter0"));
  zeroconf_detector_->AddDetections(
      {MakeDiscoveredPrinter("DiscoveredNetworkPrinter0"),
       MakeDiscoveredPrinter("DiscoveredNetworkPrinter1"),
       MakeAutomaticPrinter("AutomaticNetworkPrinter0"),
       MakeAutomaticPrinter("AutomaticNetworkPrinter1")});
  manager_->RecordNearbyNetworkPrinterCounts();
  task_environment_.RunUntilIdle();
  histogram_tester.ExpectBucketCount("Printing.CUPS.NearbyNetworkPrintersCount",
                                     3, 1);

  // Save one more network printer.
  manager_->SavePrinter(Printer("AutomaticNetworkPrinter1"));
  manager_->RecordNearbyNetworkPrinterCounts();
  task_environment_.RunUntilIdle();
  histogram_tester.ExpectBucketCount("Printing.CUPS.NearbyNetworkPrintersCount",
                                     2, 1);
}

TEST_F(CupsPrintersManagerTest, OnServerPrintersChanged) {
  auto server_printer = MakeAutomaticPrinter("ServerPrinter");
  server_printer.printer.mutable_ppd_reference()->autoconf = true;

  print_servers_manager_->ServerPrintersChanged({server_printer});

  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"ServerPrinter"});
}

// Tests that when the active network is switched to a different network the
// list of nearby printers is cleared.
TEST_F(CupsPrintersManagerTest, ActiveNetworkSwitched) {
  cros_network_config_helper_.network_state_helper().ConfigureService(
      R"({"GUID": "Wifi1", "Type": "wifi", "State": "online"})");

  zeroconf_detector_->AddDetections({MakeDiscoveredPrinter("DiscoveredPrinter"),
                                     MakeAutomaticPrinter("AutomaticPrinter")});

  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter"});

  cros_network_config_helper_.network_state_helper().ClearServices();
  cros_network_config_helper_.network_state_helper().ConfigureService(
      R"({"GUID": "Wifi2", "Type": "wifi", "State": "online"})");

  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {});
}

// Tests that when the active network is disconnected the list of nearby
// printers is cleared.
TEST_F(CupsPrintersManagerTest, ActiveNetworkDisconnected) {
  cros_network_config_helper_.network_state_helper().ConfigureService(
      R"({"GUID": "Wifi1", "Type": "wifi", "State": "online"})");

  zeroconf_detector_->AddDetections({MakeDiscoveredPrinter("DiscoveredPrinter"),
                                     MakeAutomaticPrinter("AutomaticPrinter")});

  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter"});

  cros_network_config_helper_.network_state_helper().ClearServices();

  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {});
}

// Tests that when the a new wifi network is detected, but the active network
// remains the same, the list of nearby printers stays the same.
TEST_F(CupsPrintersManagerTest, NewNetworkDetected) {
  cros_network_config_helper_.network_state_helper().ConfigureService(
      R"({"GUID": "Wifi1", "Type": "wifi", "State": "online"})");
  zeroconf_detector_->AddDetections({MakeDiscoveredPrinter("DiscoveredPrinter"),
                                     MakeAutomaticPrinter("AutomaticPrinter")});

  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter"});

  cros_network_config_helper_.network_state_helper().ConfigureService(
      R"({"GUID": "Wifi2", "Type": "wifi", "State": "online"})");

  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter"});
}

// Tests that when the signal strength of the active network changes, the list
// of nearby printers stays the same.
TEST_F(CupsPrintersManagerTest, ActiveNetworkStrengthChanged) {
  const std::string service_path =
      cros_network_config_helper_.network_state_helper().ConfigureService(
          R"({"GUID": "Wifi1", "Type": "wifi", "State": "online"})");
  zeroconf_detector_->AddDetections({MakeDiscoveredPrinter("DiscoveredPrinter"),
                                     MakeAutomaticPrinter("AutomaticPrinter")});

  task_environment_.RunUntilIdle();
  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter"});

  cros_network_config_helper_.network_state_helper().SetServiceProperty(
      service_path, shill::kSignalStrengthProperty, base::Value(50));

  ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"DiscoveredPrinter"});
  ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"AutomaticPrinter"});
}

}  // namespace
}  // namespace ash

redpajama_set_name: RedPajamaGithub


Each Tuesday a dedicated group meets to pray for the needs of our church family and our community. Using Acts 1:4 as his basis, Armin Gesswein often called the central all-church prayer meeting "Christ's last command; our first responsibility." If you have never joined our group…why don't you drop in and see what it's all about!!! We meet at a NEW TIME of 7 PM.


text:
Last update date: 24/02/2022
Pursuant to EU Regulation 2016/679 ("General European Regulation on the protection of personal data") and Legislative Decree 196/2003 ("Code regarding the protection of personal data"), as well as on the basis of provided for by the Provisions of the Privacy Guarantor n. 229 of 8 May 2014 and no. 231 of 10 June 2021, Cancellato S.r.l., Innovative Benefit & StartUp Company , with registered office in Milan, via Premuda n. 46, C.F. and VAT number 11746840963, in the person of the legal representative pro tempore , owner of the processing of personal data, provides Users of the website www.cancellatouniform.com (from now on , " Site "), some information relating to the cookies it uses.
"Cookies" are small text files, created automatically when accessing a specific site, with the purpose of performing computer authentication, monitoring sessions and storing specific information regarding the User and his visit.
More specifically, cookies are sent from the server (physical place where the site resides) of the website visited to the User's browser (Microsoft Edge, Mozilla Firefox, Google Chrome, Safari, etc.), they are stored locally on the computer of the latter, to then be retransmitted, at the next visit, to the same site.
During navigation, the User may also receive cookies from external sites (third-party cookies) on their terminal, set and used directly by the managers of the latter, in the manner and according to the purposes defined by them.
Finally, cookies can remain on the user's computer for long or short periods, depending on their characteristics.
Types of cookies.
Their duration corresponds to the browser session and are automatically deleted when the browser is closed.
They are constant and remain stored on the terminal even beyond the browser session, until the expected expiry date.
They belong to the visited website, which transmits them directly to the visitor.
They come from third party sites than the one visited. The owner of the visited site has no control over them and related information. Their eventual disabling does not prejudice in any way the navigability.
The use of these cookies is governed by the rules set by third parties and, therefore, to manage or disable these cookies, users must read the privacy policies and information published on the websites of these third parties.
Categories of cookies.
Technical cookies:
Technical cookies are those used for the sole purpose of carrying out the transmission of a communication over an electronic communications network, or to the extent strictly necessary for the provider of an information society service explicitly requested by the subscriber or user to provide this service (Article 122, paragraph 1 of the Code regarding the protection of personal data).
Technical cookies are not used for other purposes and are normally installed directly by the owner or manager of the website. No consent from the interested party is required for their use.
They can be divided into:
navigation or session cookies (or strictly necessary), which guarantee normal navigation and use of the website (allowing, for example, to make a purchase or authenticate to access restricted areas);
analytical (or measurement) cookies, similar to technical cookies when used directly by the site operator to collect information, in aggregate form, on the number of users and how they visit the site, as well as for statistical analysis on the display of pages and to monitor their correct functioning;
functionality cookies (for simple interactions or functionalities), which allow the user to navigate according to a series of selected criteria (for example, the language, the products selected for purchase) in order to improve the service made to the same.
Technical cookies used on the Site:
Name of the cookie
Used in connection with access to the control panel.
third (Shopify.com)
_secure_session_id
Used in connection with browsing a shop.
_shopify_country
Used in connection with checkout.
_shopify_m
Used to manage customer privacy settings.
_shopify_tm
_shopify_tw
_storefront_u
Used to facilitate the updating of customer account information.
_tracking_consent
Tracking preferences.
_clsk
Used to store and combine a user's page views in a single session.
_biz_uid
User ID on current domain.
_biz_sid
User session ID.
_biz_flagsA
Stores more information, for example whether the user has sent a form or not, performed a crossdomain migration, sent a pixel, renounced tracking, etc.
_biz_nA
Sequence number that Bizible includes for all requests for internal diagnostic purposes.
_biz_pendingA
Temporarily stores analytical data that has not yet been successfully sent to the Bizible server.
Used in connection with the cart.
cart_currency
cart_sig
cart_ts
cart_ver
checkout_token
dynamic_checkout_shown_on_cart
hide_shopify_pay_for_checkout
keep_alive
Used in connection with the location of the buyer.
master_device_id
Used in connection with the merchant's access.
previous_step
secure_customer_sig
Used in connection with customer access.
shopify_pay
shopify_pay_redirect
30 minutes, 3 weeks or 1 year depending on the
storefront_digest
tracked_start_checkout
checkout_one_experiment
sc_f
Used to make payments via Paypal.
third (paypal.com)
x-pp-s
l7_az
nsid
Analytical cookies used on the Site
Tracking of landing pages.
_orig_referrer
_s
Shopify analysis.
_shopify_d
_shopify_fs
_shopify_s
_shopify_sa_p
Shopify marketing and referral analysis.
_shopify_sa_t
_shopify_y
_y
_shopify_evids
_shopify_ga
Shopify and Google Analytics.
Profiling or advertising cookies:
Profiling or advertising cookies monitor and profile users during navigation, studying and storing their browsing options and habits on the site and on the web in general, as well as consumption habits, also for the purpose of sending advertising targeted and personalized services and goods.
Advertising cookies used on the Site
_clck
Used to store a single user ID.
_uetsid
Used to store and track visits.
It allows us to show our advertising to people who have already visited our website when they are on Facebook or on a digital platform supported by Facebook Advertising.
Used as a conversion linker tag in web containers that can be configured to link across domains for cases where there are landing pages and cross-domain conversion pages for Google Adsense.
Information on the processing of personal data.
The treatment is carried out with electronic and automated tools, without disclosure or communication to third parties. To read the complete information on the processing of personal data, pursuant to EU Regulation 2016/679 and Legislative Decree 196/2003, see the Privacy Policy of the Site.
Management of cookie preferences.
With the exception of technical cookies, the provision of data is left to the will of the interested party who decides to browse the site after having read, upon access, the brief information contained in the appropriate banner, and having provided the consent by clicking on the "ACCEPT" button. Alternatively, the interested user may not consent to the installation of non-technical cookies by clicking on the "REJECT" button.
You can still specify your cookie preferences by clicking on "SET PREFERENCES" in the appropriate banner. You will then be redirected to a screen where you can indicate your preferences in relation to each category of cookies. It will always be possible to change your preferences by clicking on "COOKIE SETTING" in the menu in the footer of the Site.
In any case, to proceed with the deactivation of cookies or to choose the desired blocking level, the user can use their browser, changing its settings. Below are the links to the main browsers currently on the market for changing session settings.
Italian: https://support.google.com/chrome/answer/95647?hl=it
English: https://support.google.com/chrome/bin/answer.py?hl=eng&answer=95647
Italian: https://support.mozilla.org/it/kb/Gestione%20dei%20cookie
English: https://support.mozilla.org/en-US/kb/enable-and-disable-cookie-website-preferences
Italian: https://support.microsoft.com/it-it/help/4027947/windows-delete-cookies
English: https://support.microsoft.com/en-us/help/4027947/windows-delete-cookies
Italian: https://support.apple.com / it-it / HT201265
English: https://support.apple.com/kb/PH17191?viewlocale=it_IT&locale=en_US
Further information and requests regarding privacy can be sent to Cancellato Srl, Società Benefit & Innovativa StartUp through the contact form contained in the page " Contact us ".

redpajama_set_name: RedPajamaCommonCrawl


Very nice toy truck designed by Ko Verzuu for Ado Holland in 1948. Ado is an abbreviation for Arbeid door onvolwaardigen, translated; labor by incapacitated, which makes this an even more special piece. Toys by Ado are being highly collected at the moment, even more than ever cause this is very decorative combined with 1950s furniture from all countries! This is an early long truck from ca 1948, type prefabrication (MONTAGEBOUW) which is an exceptional find for its age cause this is from the early ADO productions when these toys were made in very limited production cause of the expenses. Ado toys have a great charm because of their played look and original age wear. Ko Verzuu inspired his designs on 'De Stijl' period and the designs of Gerrit Thomas Rietveld especially. In this car you can see a lot of comparisons with 'De Stijl' and Gerrit Rietveld. This car is in a very nice used condition, completely and original. Marked with the metal emblem. Would be an amazing decorative addition to any interior.


text:
WWE	Home	Film	TV	Gaming	Comics	Music	Offbeat	Quizzes	Write For Us	Careers	Comps	Sport	UFC
WWE	Film	TV	Gaming	Comics	Music	Offbeat	Quizzes	Write For Us	Careers
10 Rip Off Wrestling Gimmicks (That Messed Up What They Copied)
Pro wrestling does a fine line in crappy versions of successful gimmicks.
by John Bills
Sep 15, 2021 Updated: September 15th, 2021
In a world of constant development and creativity, how important is originality? Often cited as vital to the success or failure of a character, it is difficult to shake the feeling that it is somewhat overrated. All stories have been told, of course, and all we're doing is interpreting them in different ways. Originality is overrated because it doesn't really exist.
That doesn't make it okay for Prince Iaukea to become The Artist Formerly Known as Prince Iaukea.
Pro wrestling history is littered with characters and gimmicks that took inspiration from those that came before, of performers who cherry-picked things that worked and ramped them up to 11. Furthermore, the more inventive wrestlers have never been afraid to dip their toes into the wider world of art in search of stimulus. If it works in literature or cinema, there's a good chance that it might work in the squared circle.
This being professional wrestling, there have been as many missteps as there have been success stories, as many head-scratchers as there were triumphs. More often than not the blunders have come from missing what made the original so invigorating and exciting, by taking only the bells and whistles and failing to understand anything about the characters at all. Many lessons have gone unlearnt.
The main one being 'don't have a charisma vacuum portray the most charismatic musician of a generation'.
10. 'Woken' Matt Hardy
Impact Wrestling/WWE
Did anyone really expect this to work? Sure, immediately feuding with Bray Wyatt at his least relevant wasn't exactly the hottest start, but you'd have to be a major supporter of WWE to say that there was hope for 'Woken' Matt Hardy. The tentative noise surrounding the character's arrival alone was an indictment of WWE creativity. If ever there was an example of the lack of faith that fans have in the world's largest wrestling promotion, this was it.
Still, there was the faint hope that WWE might get this right. All the company needed to do was allow Matt Hardy to go whole hog on the gimmick, utilising that massive budget in the process, right? Come to think of it, just what was Matt Hardy capable of with a blank cheque?
We never got to find out, because WWE was and is incapable of fathoming the subtlety required to make such gimmicks work. 'Broken' Matt Hardy was fantastic for a number of reasons, not least Hardy's commitment to the wackiness of it all, but it was the unspoken words that spoke the loudest. 'Broken' Matt Hardy didn't need to explain every reference to you, the viewer. 'Woken' Matt Hardy fell into the same trap that all WWE characters tend to; an obsession with WINK WINK NUDGE NUDGE, and a total inability to leave some things left unsaid.
First	Posted On: 6th Jan 2021
John Bills
Born in the middle of Wales in the middle of the 1980's, John can't quite remember when he started watching wrestling but he has a terrible feeling that Dino Bravo was involved. Now living in Prague, John spends most of his time trying to work out how Tomohiro Ishii still stands upright. His favourite wrestler of all time is Dean Malenko, but really it is Repo Man. He is the author of 'An Illustrated History of Slavic Misery', the best book about the Slavic people that you haven't yet read. You can get that and others from www.poshlostbooks.com.
See more from John
10 Best Wrestling Matches Of 2021
WWE Royal Rumble 2022: 10 Surprise Entrants We Could See	New
WWE Gives Up On "Gunther Stark" Trademark
10 WWE Stars Who Have Gone AWOL
7 Ups & 2 Downs From AEW Dynamite (19 Jan)
Another AEW Original's Contract Expiring Soon?
Real Reason AEW Scrapped This Dynamite Match Last Night
Scotty 2 Hotty Reveals Vince McMahon's BIZARRE Demand To NXT Coaches
10 Best Times Wrestlers Responded To Fans During Matches
Jon Moxley Cuts Epic Promo, DESTROYS Heckler In AEW Dynamite Return