103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_patcher.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string>
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <vector>
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/bind.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind_helpers.h"
12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/files/file_path.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/json/json_file_value_serializer.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/location.h"
16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/memory/weak_ptr.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/values.h"
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_patcher_operation.h"
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_updater_service.h"
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace component_updater {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Deserialize the commands file (present in delta update packages). The top
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// level must be a list.
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::ListValue* ReadCommands(const base::FilePath& unpack_path) {
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const base::FilePath commands =
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      unpack_path.Append(FILE_PATH_LITERAL("commands.json"));
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(commands))
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return NULL;
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  JSONFileValueSerializer serializer(commands);
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::Value> root(serializer.Deserialize(NULL, NULL));
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return (root.get() && root->IsType(base::Value::TYPE_LIST))
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)             ? static_cast<base::ListValue*>(root.release())
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)             : NULL;
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
43effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochComponentPatcher::ComponentPatcher(
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& input_dir,
45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& unpack_dir,
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ComponentInstaller* installer,
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_refptr<OutOfProcessPatcher> out_of_process_patcher,
48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    scoped_refptr<base::SequencedTaskRunner> task_runner)
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : input_dir_(input_dir),
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      unpack_dir_(unpack_dir),
51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      installer_(installer),
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      out_of_process_patcher_(out_of_process_patcher),
53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      task_runner_(task_runner) {
54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
56effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochComponentPatcher::~ComponentPatcher() {
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ComponentPatcher::Start(const ComponentUnpacker::Callback& callback) {
60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  callback_ = callback;
61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  task_runner_->PostTask(FROM_HERE,
62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         base::Bind(&ComponentPatcher::StartPatching,
63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                    scoped_refptr<ComponentPatcher>(this)));
64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ComponentPatcher::StartPatching() {
67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  commands_.reset(ReadCommands(input_dir_));
68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!commands_.get()) {
69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DonePatching(ComponentUnpacker::kDeltaBadCommands, 0);
70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else {
71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    next_command_ = commands_->begin();
72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    PatchNextFile();
73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ComponentPatcher::PatchNextFile() {
77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (next_command_ == commands_->end()) {
78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DonePatching(ComponentUnpacker::kNone, 0);
79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!(*next_command_)->IsType(base::Value::TYPE_DICTIONARY)) {
82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DonePatching(ComponentUnpacker::kDeltaBadCommands, 0);
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const base::DictionaryValue* command_args =
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      static_cast<base::DictionaryValue*>(*next_command_);
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string operation;
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (command_args->GetString(kOp, &operation)) {
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    current_operation_ =
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        CreateDeltaUpdateOp(operation, out_of_process_patcher_);
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!current_operation_.get()) {
95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DonePatching(ComponentUnpacker::kDeltaUnsupportedCommand, 0);
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  current_operation_->Run(command_args,
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                          input_dir_,
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                          unpack_dir_,
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                          installer_,
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                          base::Bind(&ComponentPatcher::DonePatchingFile,
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                     scoped_refptr<ComponentPatcher>(this)),
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                          task_runner_);
105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ComponentPatcher::DonePatchingFile(ComponentUnpacker::Error error,
108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                        int extended_error) {
109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (error != ComponentUnpacker::kNone) {
110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DonePatching(error, extended_error);
111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else {
112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ++next_command_;
113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    PatchNextFile();
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ComponentPatcher::DonePatching(ComponentUnpacker::Error error,
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                    int extended_error) {
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  current_operation_ = NULL;
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  task_runner_->PostTask(FROM_HERE,
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                         base::Bind(callback_, error, extended_error));
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  callback_.Reset();
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace component_updater
126