File: pdf_printer_handler_posix_unittest.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (146 lines) | stat: -rw-r--r-- 4,905 bytes parent folder | download | duplicates (6)
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
141
142
143
144
145
146
// Copyright 2021 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/ui/webui/print_preview/pdf_printer_handler.h"

#include <sys/stat.h>
#include <sys/types.h>

#include <ios>

#include "base/check.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace printing {

namespace {

// Data content used as fake PDF doesn't matter, just can not be empty.
constexpr uint8_t kDummyData[] = {'d', 'u', 'm', 'm', 'y'};

// Returns the path to the newly created directory, or an empty path on failure.
base::FilePath CreateDirWithMode(const base::FilePath& base_path, int mode) {
  base::FilePath save_to_dir;
  if (!base::CreateTemporaryDirInDir(base_path, /*prefix=*/"save",
                                     &save_to_dir)) {
    return base::FilePath();
  }
  DCHECK(!save_to_dir.empty());
  if (!base::SetPosixFilePermissions(save_to_dir, mode)) {
    return base::FilePath();
  }
  return save_to_dir;
}

int GetFilePermissions(const base::FilePath& file_path) {
  int file_mode;
  if (!base::GetPosixFilePermissions(file_path, &file_mode)) {
    return 0;  // Don't know what they are, signal with no permissions.
  }

  // Only interested in the file permissions bits.
  return file_mode & base::FILE_PERMISSION_MASK;
}

// Set a umask and restore the old mask on destruction.  Cribbed from
// sql/database_unittest.cc.
class ScopedUmaskSetter {
 public:
  explicit ScopedUmaskSetter(mode_t target_mask)
      : old_umask_(umask(target_mask)) {}
  ~ScopedUmaskSetter() { umask(old_umask_); }

  ScopedUmaskSetter(const ScopedUmaskSetter&) = delete;
  ScopedUmaskSetter& operator=(const ScopedUmaskSetter&) = delete;

 private:
  const mode_t old_umask_;
};

class FakePdfPrinterHandler : public PdfPrinterHandler {
 public:
  FakePdfPrinterHandler(Profile* profile,
                        content::WebContents* contents,
                        const base::FilePath& save_to_pdf_file)
      : PdfPrinterHandler(profile, contents, /*sticky_settings=*/nullptr) {
    DCHECK(!save_to_pdf_file.empty());
    SetPrintToPdfPathForTesting(save_to_pdf_file);
  }

  void StartPrintToPdf() {
    SetPdfSavedClosureForTesting(run_loop_.QuitClosure());

    scoped_refptr<base::RefCountedMemory> dummy_data =
        base::MakeRefCounted<base::RefCountedStaticMemory>(kDummyData);
    StartPrint(u"dummy-job-title", /*settings=*/base::Value::Dict(), dummy_data,
               base::DoNothing());
    run_loop_.Run();
  }

 private:
  base::RunLoop run_loop_;
};

}  // namespace

class PdfPrinterHandlerPosixTest : public BrowserWithTestWindowTest {
 public:
  PdfPrinterHandlerPosixTest() = default;
  PdfPrinterHandlerPosixTest(const PdfPrinterHandlerPosixTest&) = delete;
  PdfPrinterHandlerPosixTest& operator=(const PdfPrinterHandlerPosixTest&) =
      delete;
  ~PdfPrinterHandlerPosixTest() override = default;

  void SetUp() override {
    BrowserWithTestWindowTest::SetUp();

    // Create a temp dir to work in.
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  }

 protected:
  base::ScopedTempDir temp_dir_;
};

TEST_F(PdfPrinterHandlerPosixTest, SaveAsPdfFilePermissions) {
  ScopedUmaskSetter permissive_umask(0022);

  // Saved PDF files are not executable files, and should be readable/writeable
  // for the user.  It should also have group readable permissions to match the
  // behavior seen for downloaded files.  Note that this is the desired case
  // regardless of the directory permissions.
  // `base::WriteFile()` creates files permissions of read/write for user and
  // read for everyone.
  constexpr int kExpectedFileMode = 0644;

  // Test against directories with varying permissions, to illustrate that this
  // does not impact the saved PDF's permissions.
  constexpr int kDirectoryModes[] = {0700, 0750, 0770, 0775, 0777};

  DVLOG(1) << "Expect file mode is always " << std::oct << kExpectedFileMode;
  for (int dir_mode : kDirectoryModes) {
    DVLOG(1) << "Checking for directory mode " << std::oct << dir_mode;
    base::FilePath save_to_dir =
        CreateDirWithMode(/*base_path=*/temp_dir_.GetPath(), dir_mode);
    ASSERT_FALSE(save_to_dir.empty());
    base::FilePath save_to_pdf_file = save_to_dir.Append("output.pdf");

    auto pdf_printer = std::make_unique<FakePdfPrinterHandler>(
        profile(), browser()->tab_strip_model()->GetActiveWebContents(),
        save_to_pdf_file);
    pdf_printer->StartPrintToPdf();
    EXPECT_EQ(kExpectedFileMode, GetFilePermissions(save_to_pdf_file));
  }
}

}  // namespace printing