Index: components/framelet/browser/framelet_guest.cc |
diff --git a/components/framelet/browser/framelet_guest.cc b/components/framelet/browser/framelet_guest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9473f84cd0a2e31800389c6a0ddec1a0734087b4 |
--- /dev/null |
+++ b/components/framelet/browser/framelet_guest.cc |
@@ -0,0 +1,222 @@ |
+// Copyright 2015 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 "components/framelet/browser/framelet_guest.h" |
+ |
+#include "base/strings/stringprintf.h" |
+#include "cc/surfaces/surface.h" |
+#include "components/framelet/browser/framelet_memory_tracker.h" |
+#include "components/framelet/browser/resource_usage_reporter.h" |
+#include "components/framelet/common/framelet_constants.h" |
+#include "components/framelet/common/framelet_messages.h" |
+#include "components/guest_view/browser/guest_view_manager.h" |
+#include "components/strings/grit/components_chromium_strings.h" |
+#include "content/public/browser/render_process_host.h" |
+#include "content/public/browser/site_instance.h" |
+#include "content/public/common/url_constants.h" |
+#include "ipc/ipc_message.h" |
+ |
+namespace framelet { |
+ |
+// static. |
+const char FrameletGuest::Type[] = "framelet"; |
+ |
+// static. |
+guest_view::GuestViewBase* FrameletGuest::Create( |
+ content::WebContents* owner_web_contents) { |
+ return new FrameletGuest(owner_web_contents); |
+} |
+ |
+void FrameletGuest::AttachToEmbedderFrame(int element_instance_id, |
+ int embedder_local_render_frame_id, |
+ const base::DictionaryValue& params) { |
+ element_instance_id_ = element_instance_id; |
+ // We should only update params if there's a change between creation and |
+ // attachment. |
+ content::GuestAttachParams attach_params; |
+ params.GetBoolean(framelet::kVisible, &attach_params.visible); |
+ params.GetBoolean(framelet::kFocused, &attach_params.focused); |
+ int element_width = 300; |
+ int element_height = 300; |
+ params.GetInteger(guest_view::kElementWidth, &element_width); |
+ params.GetInteger(guest_view::kElementHeight, &element_height); |
+ // TODO(fsamuel): This should probably be a size rather than a rect. |
+ attach_params.view_rect = gfx::Rect(element_width, element_height); |
+ host()->Attach(element_instance_id, owner_web_contents(), attach_params); |
+} |
+ |
+void FrameletGuest::ReportHeapSize(int heap_size) { |
+ resource_usage_reporter_->ReportUsage(heap_size); |
+} |
+ |
+void FrameletGuest::OnResourceUsageLevelChanged( |
+ const ResourceUsageLevel& usage_level) { |
+ // The state machine reports usage level here. |
+ // TODO(fsamuel): Feed this value through a ResourceUsageManager, that |
+ // collects all values, and only updates the embedder if the max changes. |
+ owner_web_contents()->Send(new ChromeGuestViewMsg_ReportMemoryUsage( |
+ element_instance_id(), usage_level)); |
+} |
+ |
+scoped_ptr<ResourceUsageRange<int>> FrameletGuest::GetRangeForUsageLevel( |
+ const ResourceUsageLevel& usage_level) const { |
+ switch (usage_level) { |
+ case ResourceUsageLevel::LOW: |
+ return make_scoped_ptr(new ResourceUsageRange<int>( |
+ ResourceUsageRangeType::LEFT_UNBOUNDED, kMemoryUsageLimitLow)); |
+ case ResourceUsageLevel::MEDIUM: |
+ return make_scoped_ptr(new ResourceUsageRange<int>( |
+ kMemoryUsageLimitLow - kMemoryUsageRangeOverlap, |
+ kMemoryUsageLimitMedium)); |
+ case ResourceUsageLevel::HIGH: |
+ return make_scoped_ptr(new ResourceUsageRange<int>( |
+ kMemoryUsageLimitMedium - kMemoryUsageRangeOverlap, |
+ kMemoryUsageLimitHigh)); |
+ case ResourceUsageLevel::CRITICAL: |
+ return make_scoped_ptr(new ResourceUsageRange<int>( |
+ ResourceUsageRangeType::RIGHT_UNBOUNDED, kMemoryUsageLimitHigh)); |
+ default: |
+ CHECK(false); |
+ return nullptr; |
+ } |
+} |
+ |
+bool FrameletGuest::SetChildFrameSurface(const cc::SurfaceId& surface_id, |
+ const gfx::Size& frame_size, |
+ float scale_factor, |
+ const cc::SurfaceSequence& sequence) { |
+ owner_web_contents()->Send(new ChromeGuestViewMsg_SetChildFrameSurface( |
+ element_instance_id(), surface_id, frame_size, scale_factor, sequence)); |
+ return true; |
+} |
+ |
+FrameletGuest::FrameletGuest(content::WebContents* owner_web_contents) |
+ : GuestView<FrameletGuest>(owner_web_contents), monitor_resources_(true) {} |
+ |
+FrameletGuest::~FrameletGuest() {} |
+ |
+// content::WebContentsDelegate implementation. |
+bool FrameletGuest::HandleContextMenu( |
+ const content::ContextMenuParams& params) { |
+ return false; |
+} |
+ |
+const char* FrameletGuest::GetAPINamespace() const { |
+ return framelet::kEmbedderAPINamespace; |
+} |
+ |
+bool FrameletGuest::CanRunInDetachedState() const { |
+ return true; |
+} |
+ |
+int FrameletGuest::GetTaskPrefix() const { |
+ return IDS_TASK_MANAGER_FRAMELET_TAG_PREFIX; |
+} |
+ |
+void FrameletGuest::CreateWebContents( |
+ const base::DictionaryValue& create_params, |
+ const guest_view::GuestViewBase::WebContentsCreatedCallback& callback) { |
+ // For each embedder process, there should exist a framelet process. |
+ GURL guest_site(base::StringPrintf( |
+ "%s://framelet-%d", content::kGuestScheme, |
+ owner_web_contents()->GetRenderProcessHost()->GetID())); |
+ |
+ guest_view::GuestViewManager* guest_view_manager = |
+ guest_view::GuestViewManager::FromBrowserContext( |
+ owner_web_contents()->GetBrowserContext()); |
+ content::SiteInstance* guest_site_instance = |
+ guest_view_manager->GetGuestSiteInstance(guest_site); |
+ if (!guest_site_instance) { |
+ guest_site_instance = content::SiteInstance::CreateForURL( |
+ owner_web_contents()->GetBrowserContext(), guest_site); |
+ } |
+ content::WebContents::CreateParams params( |
+ owner_web_contents()->GetBrowserContext(), guest_site_instance); |
+ params.guest_delegate = this; |
+ callback.Run(content::WebContents::Create(params)); |
+} |
+ |
+void FrameletGuest::DidAttachToEmbedder() {} |
+ |
+void FrameletGuest::DidInitialize(const base::DictionaryValue& create_params) { |
+ resource_usage_reporter_.reset(new ResourceUsageReporter<int>(this)); |
+ std::string url; |
+ create_params.GetString(guest_view::kUrl, &url); |
+ web_contents()->GetController().LoadURL(GURL(url), content::Referrer(), |
+ ui::PAGE_TRANSITION_AUTO_TOPLEVEL, |
+ std::string()); |
+ |
+ create_params.GetBoolean(framelet::kMonitorResources, &monitor_resources_); |
+ |
+ if (monitor_resources_) { |
+ FrameletMemoryTracker::ClientID client_id( |
+ web_contents()->GetRenderProcessHost()->GetID(), |
+ web_contents()->GetRoutingID()); |
+ FrameletMemoryTracker::FromBrowserContext(browser_context()) |
+ ->AddClient(client_id, this); |
+ } |
+} |
+ |
+bool FrameletGuest::OnMessageReceivedFromEmbedder(const IPC::Message& message) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(FrameletGuest, message) |
+ IPC_MESSAGE_HANDLER(ChromeGuestViewHostMsg_DestroyFramelet, |
+ OnDestroyFramelet) |
+ IPC_MESSAGE_HANDLER(ChromeGuestViewHostMsg_ForwardInputEvent, |
+ OnForwardInputEvent) |
+ IPC_MESSAGE_HANDLER(ChromeGuestViewHostMsg_ResizeFramelet, OnResizeFramelet) |
+ IPC_MESSAGE_HANDLER(ChromeGuestViewHostMsg_SetContainerVisible, |
+ OnSetContainerVisible) |
+ IPC_MESSAGE_HANDLER(ChromeGuestViewHostMsg_SetFocus, OnSetFocus) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP(); |
+ return handled; |
+} |
+ |
+void FrameletGuest::WillDestroy() { |
+ if (monitor_resources_) { |
+ // TODO(fsamuel): Verify whether this is actually safe. The WebContents |
+ // should still exist so we might be fine. |
+ FrameletMemoryTracker::ClientID client_id( |
+ web_contents()->GetRenderProcessHost()->GetID(), |
+ web_contents()->GetRoutingID()); |
+ FrameletMemoryTracker::FromBrowserContext(browser_context()) |
+ ->RemoveClient(client_id); |
+ } |
+} |
+ |
+void FrameletGuest::OnDestroyFramelet(int element_instance_id) { |
+ // Since FrameletGuest is only managed on one thread, any subsequent IPC sent |
+ // to the browser will arrive after the guest has been destroyed. |
+ owner_web_contents()->Send( |
+ new ChromeGuestViewMsg_DestroyFramelet_ACK(element_instance_id)); |
+ Destroy(); |
+ // WARNING: We cannot access member variables beyond this point because |this| |
+ // has been destroyed. |
+} |
+ |
+void FrameletGuest::OnForwardInputEvent(int element_instance_id, |
+ const blink::WebInputEvent* event) { |
+ host()->ForwardInputEvent(event); |
+} |
+ |
+void FrameletGuest::OnResizeFramelet(int element_instance_id, |
+ const gfx::Size& new_size) { |
+ guest_view::SetSizeParams size_params; |
+ size_params.normal_size.reset(new gfx::Size(new_size)); |
+ SetSize(size_params); |
+} |
+ |
+void FrameletGuest::OnSetContainerVisible(int element_instance_id, |
+ bool visible) { |
+ host()->SetContainerVisible(visible); |
+} |
+ |
+void FrameletGuest::OnSetFocus(int element_instance_id, |
+ bool focused, |
+ blink::WebFocusType focus_type) { |
+ host()->SetFocus(focused, focus_type); |
+} |
+ |
+} // namespace framelet |