summaryrefslogtreecommitdiff
path: root/chromium/content/browser/manifest/manifest_manager_host.cc
blob: 68ea016c62eb1947f1d4dae8bd23fea038f1721b (plain)
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
// Copyright 2014 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.

#include "content/browser/manifest/manifest_manager_host.h"

#include <stdint.h>

#include "base/bind.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_frame_host.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/manifest/manifest.h"

namespace content {

ManifestManagerHost::ManifestManagerHost(RenderFrameHost* render_frame_host)
    : manifest_manager_frame_(render_frame_host) {
  // Check that |manifest_manager_frame_| is a main frame.
  DCHECK(!manifest_manager_frame_->GetParent());
}

ManifestManagerHost::~ManifestManagerHost() {
  OnConnectionError();
}

void ManifestManagerHost::BindObserver(
    mojo::PendingAssociatedReceiver<blink::mojom::ManifestUrlChangeObserver>
        receiver) {
  manifest_url_change_observer_receiver_.Bind(std::move(receiver));
}

ManifestManagerHost* ManifestManagerHost::GetOrCreateForCurrentDocument(
    RenderFrameHostImpl* rfh) {
  DCHECK(rfh->is_main_frame());
  if (!GetForCurrentDocument(rfh))
    CreateForCurrentDocument(rfh);
  return GetForCurrentDocument(rfh);
}

void ManifestManagerHost::GetManifest(GetManifestCallback callback) {
  auto& manifest_manager = GetManifestManager();
  int request_id = callbacks_.Add(
      std::make_unique<GetManifestCallback>(std::move(callback)));
  manifest_manager.RequestManifest(
      base::BindOnce(&ManifestManagerHost::OnRequestManifestResponse,
                     base::Unretained(this), request_id));
}

void ManifestManagerHost::RequestManifestDebugInfo(
    blink::mojom::ManifestManager::RequestManifestDebugInfoCallback callback) {
  GetManifestManager().RequestManifestDebugInfo(std::move(callback));
}

blink::mojom::ManifestManager& ManifestManagerHost::GetManifestManager() {
  if (!manifest_manager_) {
    manifest_manager_frame_->GetRemoteInterfaces()->GetInterface(
        manifest_manager_.BindNewPipeAndPassReceiver());
    manifest_manager_.set_disconnect_handler(base::BindOnce(
        &ManifestManagerHost::OnConnectionError, base::Unretained(this)));
  }
  return *manifest_manager_;
}

void ManifestManagerHost::OnConnectionError() {
  std::vector<GetManifestCallback> callbacks;
  for (CallbackMap::iterator it(&callbacks_); !it.IsAtEnd(); it.Advance()) {
    callbacks.push_back(std::move(*it.GetCurrentValue()));
  }
  callbacks_.Clear();
  for (auto& callback : callbacks)
    std::move(callback).Run(GURL(), blink::Manifest());

  if (GetForCurrentDocument(manifest_manager_frame_)) {
    DeleteForCurrentDocument(manifest_manager_frame_);
  }
}

void ManifestManagerHost::OnRequestManifestResponse(
    int request_id,
    const GURL& url,
    const blink::Manifest& manifest) {
  auto callback = std::move(*callbacks_.Lookup(request_id));
  callbacks_.Remove(request_id);
  std::move(callback).Run(url, manifest);
}

void ManifestManagerHost::ManifestUrlChanged(
    const base::Optional<GURL>& manifest_url) {
  if (!manifest_manager_frame_->IsCurrent())
    return;

  // TODO(yuzus): |NotifyManifestUrlChanged| should start taking a
  // |RenderFrameHost| parameter.
  WebContents* web_contents =
      WebContents::FromRenderFrameHost(manifest_manager_frame_);
  static_cast<WebContentsImpl*>(web_contents)
      ->NotifyManifestUrlChanged(manifest_url);
}

RENDER_DOCUMENT_HOST_USER_DATA_KEY_IMPL(ManifestManagerHost)
}  // namespace content