Index: chrome/browser/extensions/platform_app_host.cc |
diff --git a/chrome/browser/extensions/platform_app_host.cc b/chrome/browser/extensions/platform_app_host.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0e21399f81e33fee15602992fde904cdb9797f82 |
--- /dev/null |
+++ b/chrome/browser/extensions/platform_app_host.cc |
@@ -0,0 +1,225 @@ |
+// 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. |
+ |
+#include "chrome/browser/extensions/platform_app_host.h" |
+ |
+#include <list> |
+ |
+// TODO(benwells): review include list and forward decls |
+#include "base/bind.h" |
+#include "base/memory/singleton.h" |
+#include "base/memory/weak_ptr.h" |
+#include "base/message_loop.h" |
+#include "base/metrics/histogram.h" |
+#include "base/string_util.h" |
+#include "base/utf_string_conversions.h" |
+#include "chrome/browser/browser_shutdown.h" |
+#include "chrome/browser/extensions/extension_process_manager.h" |
+#include "chrome/browser/extensions/extension_service.h" |
+#include "chrome/browser/extensions/extension_system.h" |
+#include "chrome/browser/extensions/extension_tab_util.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h" |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/browser/ui/browser_list.h" |
+#include "chrome/browser/ui/browser_window.h" |
+#include "chrome/browser/ui/prefs/prefs_tab_helper.h" |
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
+#include "chrome/common/chrome_constants.h" |
+#include "chrome/common/chrome_notification_types.h" |
+#include "chrome/common/chrome_view_type.h" |
+#include "chrome/common/extensions/extension.h" |
+#include "chrome/common/extensions/extension_constants.h" |
+#include "chrome/common/extensions/extension_messages.h" |
+#include "chrome/common/render_messages.h" |
+#include "chrome/common/url_constants.h" |
+#include "content/public/browser/content_browser_client.h" |
+#include "content/public/browser/native_web_keyboard_event.h" |
+#include "content/public/browser/notification_service.h" |
+#include "content/public/browser/render_process_host.h" |
+#include "content/public/browser/render_view_host.h" |
+#include "content/public/browser/site_instance.h" |
+#include "content/public/browser/web_contents.h" |
+#include "content/public/browser/web_contents_view.h" |
+#include "content/public/common/renderer_preferences.h" |
+#include "grit/browser_resources.h" |
+#include "grit/chromium_strings.h" |
+#include "grit/generated_resources.h" |
+#include "ui/base/keycodes/keyboard_codes.h" |
+#include "ui/base/l10n/l10n_util.h" |
+#include "ui/base/resource/resource_bundle.h" |
+ |
+#if defined(TOOLKIT_VIEWS) |
+#include "ui/views/widget/widget.h" |
+#endif |
+ |
+using WebKit::WebDragOperation; |
+using WebKit::WebDragOperationsMask; |
+using content::OpenURLParams; |
+using content::RenderViewHost; |
+using content::WebContents; |
+ |
+////////////////// |
+// PlatformAppHost |
+ |
+// TODO(benwells): SiteInstance should be created per platform app, not per |
+// platform app host (which means per shell window). This probably means we |
+// need some sort of PlatformAppSiteManager or something :( |
+PlatformAppHost::PlatformAppHost(Profile* profile, |
+ const Extension* extension, |
+ const GURL& url) |
+ : extension_(extension), |
+ extension_id_(extension->id()), |
+ profile_(profile), |
+ render_view_host_(NULL), |
+ did_stop_loading_(false), |
+ initial_url_(url), |
+ ALLOW_THIS_IN_INITIALIZER_LIST( |
+ extension_function_dispatcher_(profile_, this)), |
+ associated_web_contents_(NULL), |
+ site_instance_(content::SiteInstance::Create(profile)) { |
+ host_contents_.reset(WebContents::Create( |
+ profile_, site_instance_.get(), MSG_ROUTING_NONE, NULL, NULL)); |
+ content::WebContentsObserver::Observe(host_contents_.get()); |
+ host_contents_->SetDelegate(this); |
+ host_contents_->SetViewType(chrome::VIEW_TYPE_APP_SHELL); |
+ host_contents_->GetMutableRendererPrefs()->browser_handles_all_requests = |
+ true; |
+ host_contents_->GetRenderViewHost()->SyncRendererPrefs(); |
+ |
+ prefs_tab_helper_.reset(new PrefsTabHelper(host_contents())); |
+ |
+ render_view_host_ = host_contents_->GetRenderViewHost(); |
+ |
+ CreateView(NULL); |
+ |
+ // Listen for when an extension is unloaded from the same profile, as it may |
+ // be the same extension that this points to. |
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
+ content::Source<Profile>(profile_)); |
+} |
+ |
+PlatformAppHost::~PlatformAppHost() {} |
+ |
+WebContents* PlatformAppHost::GetAssociatedWebContents() const { |
+ return associated_web_contents_; |
+} |
+ |
+void PlatformAppHost::SetAssociatedWebContents( |
+ content::WebContents* web_contents) { |
+ associated_web_contents_ = web_contents; |
+ if (web_contents) { |
+ registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
+ content::Source<WebContents>(associated_web_contents_)); |
+ } |
+} |
+ |
+content::WebContents* PlatformAppHost::host_contents() const { |
+ return host_contents_.get(); |
+} |
+ |
+content::RenderProcessHost* PlatformAppHost::render_process_host() const { |
+ return render_view_host()->GetProcess(); |
+} |
+ |
+RenderViewHost* PlatformAppHost::render_view_host() const { |
+ return render_view_host_; |
+} |
+ |
+void PlatformAppHost::CreateRenderViewSoon() { |
+ host_contents_->GetController().LoadURL( |
+ initial_url_, content::Referrer(), content::PAGE_TRANSITION_LINK, |
+ std::string()); |
+} |
+ |
+Browser* PlatformAppHost::GetBrowser() { |
+ return NULL; |
+} |
+ |
+content::ViewType PlatformAppHost::extension_host_type() const { |
+ return chrome::VIEW_TYPE_APP_SHELL; |
+} |
+ |
+void PlatformAppHost::Close() { |
+ // TODO(benwells):create NOTIFICATION_PLATFORM_APP_VIEW_SHOULD_CLOSE. |
+ // content::NotificationService::current()->Notify( |
+ // chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
+ // content::Source<Profile>(profile_), |
+ // content::Details<PlatformAppHost>(this)); |
+} |
+ |
+void PlatformAppHost::Observe(int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ switch (type) { |
+ case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
+ // TODO(benwells): work out what to do here. Probably should shut all |
+ // the windows. |
+ // The extension object will be deleted after this notification has been |
+ // sent. NULL it out so that dirty pointer issues don't arise in cases |
+ // when multiple PlatformAppHost objects pointing to the same Extension |
+ // are present. |
+ if (extension_ == |
Aaron Boodman
2012/04/18 21:33:22
Instead of comparing the extension that is unloade
|
+ content::Details<UnloadedExtensionInfo>(details)->extension) { |
+ extension_ = NULL; |
+ } |
+ break; |
+ case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: |
+ if (content::Source<WebContents>(source).ptr() == |
+ associated_web_contents_) { |
+ associated_web_contents_ = NULL; |
+ } |
+ break; |
+ default: |
+ NOTREACHED() << "Unexpected notification sent."; |
+ break; |
+ } |
+} |
+ |
+void PlatformAppHost::DidStopLoading() { |
+ bool notify = !did_stop_loading_; |
+ did_stop_loading_ = true; |
+#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) |
+ if (view_.get()) |
+ view_->DidStopLoading(); |
+#endif |
+ if (notify) |
+ UMA_HISTOGRAM_TIMES("Extensions.ShellLoadTime", since_created_.Elapsed()); |
+} |
+ |
+void PlatformAppHost::CloseContents(WebContents* contents) { |
+ Close(); |
+} |
+ |
+bool PlatformAppHost::ShouldSuppressDialogs() { |
+ return true; |
+} |
+ |
+bool PlatformAppHost::OnMessageReceived(const IPC::Message& message) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(PlatformAppHost, message) |
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+} |
+ |
+void PlatformAppHost::OnRequest(const ExtensionHostMsg_Request_Params& params) { |
+ extension_function_dispatcher_.Dispatch(params, render_view_host()); |
+} |
+ |
+void PlatformAppHost::RenderViewCreated(RenderViewHost* render_view_host) { |
+ render_view_host_ = render_view_host; |
+ |
+ if (view()) |
+ view()->RenderViewCreated(); |
+} |
+ |
+void PlatformAppHost::RenderViewDeleted(RenderViewHost* render_view_host) { |
+ // If our RenderViewHost is deleted, fall back to the host_contents' current |
+ // RVH. There is sometimes a small gap between the pending RVH being deleted |
+ // and RenderViewCreated being called, so we update it here. |
+ if (render_view_host == render_view_host_) |
+ render_view_host_ = host_contents_->GetRenderViewHost(); |
+} |