Bug 1615401 - Part 1: Partially implement FileVersionInfoWin to use from OSInfo::Kernel32BaseVersion(). r=bobowen
authorToshihito Kikuchi <tkikuchi@mozilla.com>
Fri, 06 Mar 2020 18:51:54 +0200
changeset 517412 032c00b0ab3967111f686a45ce1b1beec97c5ba1
parent 517411 fddaf6472c50b10ed9671f2effe2159964f8cfe5
child 517413 dc9d71fb3bac807a37dbfba35d609ac4ffff1980
push id37190
push useraciure@mozilla.com
push dateSat, 07 Mar 2020 21:33:39 +0000
treeherdermozilla-central@d2ac41047c10 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbobowen
bugs1615401
milestone75.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1615401 - Part 1: Partially implement FileVersionInfoWin to use from OSInfo::Kernel32BaseVersion(). r=bobowen This patch partially implements `FileVersionInfoWin` and `base::FilePath` class of Chromium sandbox so that a coming patch can use `base::win::OSInfo::Kernel32BaseVersion()`. Differential Revision: https://phabricator.services.mozilla.com/D65744
ipc/app/moz.build
js/xpconnect/shell/moz.build
security/sandbox/chromium-shim/base/file_version_info_win.cpp
security/sandbox/chromium-shim/base/file_version_info_win.h
security/sandbox/chromium-shim/base/files/file_path.cpp
security/sandbox/chromium-shim/base/threading/scoped_blocking_call.h
security/sandbox/moz.build
--- a/ipc/app/moz.build
+++ b/ipc/app/moz.build
@@ -30,16 +30,20 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     ]
 
     if CONFIG['MOZ_SANDBOX']:
         # For sandbox includes and the include dependencies those have
         LOCAL_INCLUDES += [
             '/security/sandbox/chromium',
             '/security/sandbox/chromium-shim',
         ]
+
+        OS_LIBS += [
+            'version',
+        ]
 
         USE_LIBS += [
             'sandbox_s',
         ]
 
         DELAYLOAD_DLLS += [
             'winmm.dll',
             'user32.dll',
--- a/js/xpconnect/shell/moz.build
+++ b/js/xpconnect/shell/moz.build
@@ -32,16 +32,20 @@ if CONFIG['OS_ARCH'] == 'WINNT':
 
     if CONFIG['MOZ_SANDBOX']:
         # For sandbox includes and the include dependencies those have
         LOCAL_INCLUDES += [
             '/security/sandbox/chromium',
             '/security/sandbox/chromium-shim',
         ]
 
+        OS_LIBS += [
+            'version',
+        ]
+
         USE_LIBS += [
             'sandbox_s',
         ]
 
         DELAYLOAD_DLLS += [
             'winmm.dll',
             'user32.dll',
         ]
new file mode 100644
--- /dev/null
+++ b/security/sandbox/chromium-shim/base/file_version_info_win.cpp
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This is a partial implementation of Chromium's source file
+// base/file_version_info_win.cc
+
+#include "base/file_version_info_win.h"
+
+#include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/scoped_blocking_call.h"
+
+#include "mozilla/Unused.h"
+
+namespace {
+
+struct LanguageAndCodePage {
+  WORD language;
+  WORD code_page;
+};
+
+// Returns the \VarFileInfo\Translation value extracted from the
+// VS_VERSION_INFO resource in |data|.
+LanguageAndCodePage* GetTranslate(const void* data) {
+  static constexpr wchar_t kTranslation[] = L"\\VarFileInfo\\Translation";
+  LPVOID translate = nullptr;
+  UINT dummy_size;
+  if (::VerQueryValue(data, kTranslation, &translate, &dummy_size))
+    return static_cast<LanguageAndCodePage*>(translate);
+  return nullptr;
+}
+
+VS_FIXEDFILEINFO* GetVsFixedFileInfo(const void* data) {
+  VS_FIXEDFILEINFO* fixed_file_info = nullptr;
+  UINT length;
+  if (::VerQueryValue(data, L"\\", reinterpret_cast<void**>(&fixed_file_info),
+                      &length)) {
+    return fixed_file_info;
+  }
+  return nullptr;
+}
+
+}  // namespace
+
+// static
+std::unique_ptr<FileVersionInfoWin>
+FileVersionInfoWin::CreateFileVersionInfoWin(const base::FilePath& file_path) {
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::MAY_BLOCK);
+
+  DWORD dummy;
+  const wchar_t* path = file_path.value().c_str();
+  const DWORD length = ::GetFileVersionInfoSize(path, &dummy);
+  if (length == 0)
+    return nullptr;
+
+  std::vector<uint8_t> data(length, 0);
+
+  if (!::GetFileVersionInfo(path, dummy, length, data.data()))
+    return nullptr;
+
+  const LanguageAndCodePage* translate = GetTranslate(data.data());
+  if (!translate)
+    return nullptr;
+
+  return base::WrapUnique(new FileVersionInfoWin(
+      std::move(data), translate->language, translate->code_page));
+}
+
+FileVersionInfoWin::FileVersionInfoWin(std::vector<uint8_t>&& data,
+                                       WORD language,
+                                       WORD code_page)
+    : owned_data_(std::move(data)),
+      data_(owned_data_.data()),
+      language_(language),
+      code_page_(code_page),
+      fixed_file_info_(GetVsFixedFileInfo(data_)) {
+  DCHECK(!owned_data_.empty());
+
+  mozilla::Unused << language_;
+  mozilla::Unused << code_page_;
+}
--- a/security/sandbox/chromium-shim/base/file_version_info_win.h
+++ b/security/sandbox/chromium-shim/base/file_version_info_win.h
@@ -1,31 +1,53 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-// This is a dummy version of Chromium source file base/file_version_info_win.h
-// Within our copy of Chromium files FileVersionInfoWin is only used in
-// base/win/windows_version.cc in GetVersionFromKernel32, which we don't use.
+// This is a partial implementation of Chromium's source file
+// base/file_version_info_win.h.
 
 #ifndef BASE_FILE_VERSION_INFO_WIN_H_
 #define BASE_FILE_VERSION_INFO_WIN_H_
 
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+
 #include "mozilla/Assertions.h"
 
 struct tagVS_FIXEDFILEINFO;
 typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO;
 
 namespace base {
 class FilePath;
 }
 
 class FileVersionInfoWin {
  public:
   static std::unique_ptr<FileVersionInfoWin> CreateFileVersionInfoWin(
-      const base::FilePath& file_path) { MOZ_CRASH(); }
+      const base::FilePath& file_path);
+
+  // Get the fixed file info if it exists. Otherwise NULL
+  const VS_FIXEDFILEINFO* fixed_file_info() const { return fixed_file_info_; }
 
-  VS_FIXEDFILEINFO* fixed_file_info() { MOZ_CRASH(); }
+ private:
+  // |data| is a VS_VERSION_INFO resource. |language| and |code_page| are
+  // extracted from the \VarFileInfo\Translation value of |data|.
+  FileVersionInfoWin(std::vector<uint8_t>&& data,
+                     WORD language,
+                     WORD code_page);
+
+  const std::vector<uint8_t> owned_data_;
+  const void* const data_;
+  const WORD language_;
+  const WORD code_page_;
+
+  // This is a pointer into |data_| if it exists. Otherwise nullptr.
+  const VS_FIXEDFILEINFO* const fixed_file_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileVersionInfoWin);
 };
 
 #endif  // BASE_FILE_VERSION_INFO_WIN_H_
--- a/security/sandbox/chromium-shim/base/files/file_path.cpp
+++ b/security/sandbox/chromium-shim/base/files/file_path.cpp
@@ -1,22 +1,40 @@
 // Copyright (c) 2012 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.
 
-// This is a dummy version of Chromium source file base/file/file_path.cc.
-// To provide the functions required in base/win/windows_version.cc
-// GetVersionFromKernel32, which we don't use.
+// This is a partial implementation of Chromium's source file
+// base/file/file_path.cc.
 
 #include "base/files/file_path.h"
 
 #include "mozilla/Assertions.h"
 
 namespace base {
 
-FilePath::FilePath(FilePath::StringPieceType path) {
-  MOZ_CRASH();
+using StringType = FilePath::StringType;
+using StringPieceType = FilePath::StringPieceType;
+
+namespace {
+
+const FilePath::CharType kStringTerminator = FILE_PATH_LITERAL('\0');
+
+}  // namespace
+
+FilePath::FilePath() = default;
+
+FilePath::FilePath(const FilePath& that) = default;
+FilePath::FilePath(FilePath&& that) noexcept = default;
+
+FilePath::FilePath(StringPieceType path) : path_(path) {
+  StringType::size_type nul_pos = path_.find(kStringTerminator);
+  if (nul_pos != StringType::npos)
+    path_.erase(nul_pos, StringType::npos);
 }
 
-FilePath::~FilePath() {
-}
+FilePath::~FilePath() = default;
+
+FilePath& FilePath::operator=(const FilePath& that) = default;
+
+FilePath& FilePath::operator=(FilePath&& that) = default;
 
 } // namespace base
--- a/security/sandbox/chromium-shim/base/threading/scoped_blocking_call.h
+++ b/security/sandbox/chromium-shim/base/threading/scoped_blocking_call.h
@@ -8,30 +8,31 @@
 // base/threading/scoped_blocking_call.h
 // To provide to a dummy ScopedBlockingCall class. This prevents dependency
 // creep and we don't use the rest of the blocking call checking.
 
 #ifndef BASE_THREADING_SCOPED_BLOCKING_CALL_H
 #define BASE_THREADING_SCOPED_BLOCKING_CALL_H
 
 #include "base/base_export.h"
+#include "base/location.h"
 
 namespace base {
 
 enum class BlockingType {
   // The call might block (e.g. file I/O that might hit in memory cache).
   MAY_BLOCK,
   // The call will definitely block (e.g. cache already checked and now pinging
   // server synchronously).
   WILL_BLOCK
 };
 
 class BASE_EXPORT ScopedBlockingCall {
  public:
-  ScopedBlockingCall(BlockingType blocking_type) {};
+  ScopedBlockingCall(const Location& from_here, BlockingType blocking_type) {};
   ~ScopedBlockingCall() {};
 };
 
 namespace internal {
 
 class BASE_EXPORT ScopedBlockingCallWithBaseSyncPrimitives {
  public:
   ScopedBlockingCallWithBaseSyncPrimitives(BlockingType blocking_type) {};
--- a/security/sandbox/moz.build
+++ b/security/sandbox/moz.build
@@ -30,16 +30,17 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
         'chromium-shim/sandbox/win/loggingCallbacks.h',
         'chromium-shim/sandbox/win/loggingTypes.h',
         'chromium-shim/sandbox/win/permissionsService.h',
         'chromium-shim/sandbox/win/sandboxLogging.h',
         'win/SandboxInitialization.h',
     ]
 
     SOURCES += [
+        'chromium-shim/base/file_version_info_win.cpp',
         'chromium-shim/base/files/file_path.cpp',
         'chromium-shim/base/logging.cpp',
         'chromium-shim/sandbox/win/permissionsService.cpp',
         'chromium-shim/sandbox/win/sandboxLogging.cpp',
         'chromium/base/at_exit.cc',
         'chromium/base/base_switches.cc',
         'chromium/base/callback_internal.cc',
         'chromium/base/cpu.cc',