| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/extensions/shell_window.h" | 5 #include "chrome/browser/ui/extensions/shell_window.h" |
| 6 | 6 |
| 7 #include "chrome/browser/ui/browser_list.h" | 7 #include "chrome/browser/ui/browser_list.h" |
| 8 #include "chrome/browser/extensions/extension_process_manager.h" | 8 #include "chrome/browser/extensions/extension_process_manager.h" |
| 9 #include "chrome/browser/extensions/extension_tabs_module_constants.h" | 9 #include "chrome/browser/extensions/extension_tabs_module_constants.h" |
| 10 #include "chrome/browser/extensions/extension_window_controller.h" | 10 #include "chrome/browser/extensions/extension_window_controller.h" |
| 11 #include "chrome/browser/extensions/shell_window_registry.h" |
| 11 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 12 #include "chrome/browser/sessions/session_id.h" | 13 #include "chrome/browser/sessions/session_id.h" |
| 13 #include "chrome/common/chrome_notification_types.h" | 14 #include "chrome/common/chrome_notification_types.h" |
| 15 #include "chrome/common/chrome_view_type.h" |
| 14 #include "chrome/common/extensions/extension.h" | 16 #include "chrome/common/extensions/extension.h" |
| 17 #include "chrome/common/extensions/extension_messages.h" |
| 15 #include "content/public/browser/notification_details.h" | 18 #include "content/public/browser/notification_details.h" |
| 16 #include "content/public/browser/notification_service.h" | 19 #include "content/public/browser/notification_service.h" |
| 17 #include "content/public/browser/notification_source.h" | 20 #include "content/public/browser/notification_source.h" |
| 18 #include "content/public/browser/notification_types.h" | 21 #include "content/public/browser/notification_types.h" |
| 22 #include "content/public/browser/render_view_host.h" |
| 23 #include "content/public/browser/site_instance.h" |
| 24 #include "content/public/browser/web_contents.h" |
| 25 #include "content/public/common/renderer_preferences.h" |
| 26 |
| 27 using content::SiteInstance; |
| 28 using content::WebContents; |
| 19 | 29 |
| 20 namespace internal { | 30 namespace internal { |
| 21 | 31 |
| 22 class ShellWindowController : public ExtensionWindowController { | 32 class ShellWindowController : public ExtensionWindowController { |
| 23 public: | 33 public: |
| 24 ShellWindowController(ShellWindow* shell_window, Profile* profile); | 34 ShellWindowController(ShellWindow* shell_window, Profile* profile); |
| 25 | 35 |
| 26 // Overriden from ExtensionWindowController | 36 // Overriden from ExtensionWindowController |
| 27 virtual int GetWindowId() const OVERRIDE; | 37 virtual int GetWindowId() const OVERRIDE; |
| 28 virtual std::string GetWindowTypeText() const OVERRIDE; | 38 virtual std::string GetWindowTypeText() const OVERRIDE; |
| 29 virtual base::DictionaryValue* CreateWindowValue() const OVERRIDE; | |
| 30 virtual base::DictionaryValue* CreateWindowValueWithTabs() const OVERRIDE; | 39 virtual base::DictionaryValue* CreateWindowValueWithTabs() const OVERRIDE; |
| 31 virtual bool CanClose(Reason* reason) const OVERRIDE; | 40 virtual bool CanClose(Reason* reason) const OVERRIDE; |
| 32 virtual void SetFullscreenMode(bool is_fullscreen, | 41 virtual void SetFullscreenMode(bool is_fullscreen, |
| 33 const GURL& extension_url) const OVERRIDE; | 42 const GURL& extension_url) const OVERRIDE; |
| 34 | 43 |
| 35 private: | 44 private: |
| 36 ShellWindow* shell_window_; | 45 ShellWindow* shell_window_; |
| 37 | 46 |
| 38 DISALLOW_COPY_AND_ASSIGN(ShellWindowController); | 47 DISALLOW_COPY_AND_ASSIGN(ShellWindowController); |
| 39 }; | 48 }; |
| 40 | 49 |
| 41 ShellWindowController::ShellWindowController( | 50 ShellWindowController::ShellWindowController( |
| 42 ShellWindow* shell_window, | 51 ShellWindow* shell_window, |
| 43 Profile* profile) | 52 Profile* profile) |
| 44 : ExtensionWindowController(shell_window, profile), | 53 : ExtensionWindowController(shell_window, profile), |
| 45 shell_window_(shell_window) { | 54 shell_window_(shell_window) { |
| 46 } | 55 } |
| 47 | 56 |
| 48 int ShellWindowController::GetWindowId() const { | 57 int ShellWindowController::GetWindowId() const { |
| 49 return static_cast<int>(shell_window_->session_id().id()); | 58 return static_cast<int>(shell_window_->session_id().id()); |
| 50 } | 59 } |
| 51 | 60 |
| 52 namespace keys = extension_tabs_module_constants; | |
| 53 | |
| 54 std::string ShellWindowController::GetWindowTypeText() const { | 61 std::string ShellWindowController::GetWindowTypeText() const { |
| 55 return keys::kWindowTypeValueShell; | 62 return extension_tabs_module_constants::kWindowTypeValueShell; |
| 56 } | |
| 57 | |
| 58 base::DictionaryValue* ShellWindowController::CreateWindowValue() const { | |
| 59 DictionaryValue* result = ExtensionWindowController::CreateWindowValue(); | |
| 60 return result; | |
| 61 } | 63 } |
| 62 | 64 |
| 63 base::DictionaryValue* ShellWindowController::CreateWindowValueWithTabs() | 65 base::DictionaryValue* ShellWindowController::CreateWindowValueWithTabs() |
| 64 const { | 66 const { |
| 65 return CreateWindowValue(); | 67 return CreateWindowValue(); |
| 66 } | 68 } |
| 67 | 69 |
| 68 bool ShellWindowController::CanClose(Reason* reason) const { | 70 bool ShellWindowController::CanClose(Reason* reason) const { |
| 69 return true; | 71 return true; |
| 70 } | 72 } |
| 71 | 73 |
| 72 void ShellWindowController::SetFullscreenMode(bool is_fullscreen, | 74 void ShellWindowController::SetFullscreenMode(bool is_fullscreen, |
| 73 const GURL& extension_url) const { | 75 const GURL& extension_url) const { |
| 74 // TODO(mihaip): implement | 76 // TODO(mihaip): implement |
| 75 } | 77 } |
| 76 | 78 |
| 77 } // namespace internal | 79 } // namespace internal |
| 78 | 80 |
| 79 ShellWindow* ShellWindow::Create(Profile* profile, | 81 ShellWindow* ShellWindow::Create(Profile* profile, |
| 80 const Extension* extension, | 82 const Extension* extension, |
| 81 const GURL& url) { | 83 const GURL& url) { |
| 82 ExtensionProcessManager* manager = profile->GetExtensionProcessManager(); | |
| 83 DCHECK(manager); | |
| 84 | |
| 85 // This object will delete itself when the window is closed. | 84 // This object will delete itself when the window is closed. |
| 86 return ShellWindow::CreateShellWindow( | 85 return ShellWindow::CreateImpl(profile, extension, url); |
| 87 manager->CreateShellHost(extension, url)); | |
| 88 } | 86 } |
| 89 | 87 |
| 90 void ShellWindow::Observe(int type, | 88 ShellWindow::ShellWindow(Profile* profile, |
| 91 const content::NotificationSource& source, | 89 const Extension* extension, |
| 92 const content::NotificationDetails& details) { | 90 const GURL& url) |
| 93 switch (type) { | 91 : profile_(profile), |
| 94 case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: | 92 extension_(extension), |
| 95 if (content::Details<ExtensionHost>(host_.get()) == details) | 93 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 96 Close(); | 94 extension_function_dispatcher_(profile, this)) { |
| 97 break; | 95 web_contents_.reset(WebContents::Create( |
| 98 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 96 profile, SiteInstance::CreateForURL(profile, url), MSG_ROUTING_NONE, NULL, |
| 99 const Extension* unloaded_extension = | 97 NULL)); |
| 100 content::Details<UnloadedExtensionInfo>(details)->extension; | 98 content::WebContentsObserver::Observe(web_contents_.get()); |
| 101 // We compare extension IDs and not Extension pointers since ExtensionHost | 99 web_contents_->SetDelegate(this); |
| 102 // nulls out its Extension pointer when it gets this notification. | 100 web_contents_->SetViewType(chrome::VIEW_TYPE_APP_SHELL); |
| 103 if (host_->extension_id() == unloaded_extension->id()) | 101 web_contents_->GetMutableRendererPrefs()->browser_handles_all_requests = |
| 104 Close(); | 102 true; |
| 105 break; | 103 web_contents_->GetRenderViewHost()->SyncRendererPrefs(); |
| 106 } | |
| 107 case content::NOTIFICATION_APP_TERMINATING: | |
| 108 Close(); | |
| 109 break; | |
| 110 default: | |
| 111 NOTREACHED() << "Received unexpected notification"; | |
| 112 } | |
| 113 } | |
| 114 | 104 |
| 115 ShellWindow::ShellWindow(ExtensionHost* host) | 105 web_contents_->GetController().LoadURL( |
| 116 : host_(host) { | 106 url, content::Referrer(), content::PAGE_TRANSITION_LINK, |
| 117 // Close the window in response to window.close() and the like. | 107 std::string()); |
| 118 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | |
| 119 content::Source<Profile>(host->profile())); | |
| 120 // Also close if the window if the extension has been unloaded (parallels | |
| 121 // NOTIFICATION_EXTENSION_UNLOADED closing the app's tabs in TabStripModel). | |
| 122 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 108 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 123 content::Source<Profile>(host->profile())); | 109 content::Source<Profile>(profile_)); |
| 124 // Close when the browser is exiting. | 110 // Close when the browser is exiting. |
| 125 // TODO(mihaip): we probably don't want this in the long run (when platform | 111 // TODO(mihaip): we probably don't want this in the long run (when platform |
| 126 // apps are no longer tied to the browser process). | 112 // apps are no longer tied to the browser process). |
| 127 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING, | 113 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING, |
| 128 content::NotificationService::AllSources()); | 114 content::NotificationService::AllSources()); |
| 129 | 115 |
| 130 // Prevent the browser process from shutting down while this window is open. | 116 // Prevent the browser process from shutting down while this window is open. |
| 131 BrowserList::StartKeepAlive(); | 117 BrowserList::StartKeepAlive(); |
| 132 | 118 |
| 133 // Make this window available to the extension API. | 119 // Make this window available to the extension API. |
| 134 extension_window_controller_.reset( | 120 extension_window_controller_.reset( |
| 135 new internal::ShellWindowController(this, host->profile())); | 121 new internal::ShellWindowController(this, profile_)); |
| 122 |
| 123 ShellWindowRegistry::Get(profile_)->AddShellWindow(this); |
| 136 } | 124 } |
| 137 | 125 |
| 138 ShellWindow::~ShellWindow() { | 126 ShellWindow::~ShellWindow() { |
| 139 // Unregister now to prevent getting NOTIFICATION_APP_TERMINATING if we're the | 127 // Unregister now to prevent getting NOTIFICATION_APP_TERMINATING if we're the |
| 140 // last window open. | 128 // last window open. |
| 141 registrar_.RemoveAll(); | 129 registrar_.RemoveAll(); |
| 142 | 130 |
| 131 ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this); |
| 132 |
| 143 // Remove shutdown prevention. | 133 // Remove shutdown prevention. |
| 144 BrowserList::EndKeepAlive(); | 134 BrowserList::EndKeepAlive(); |
| 145 } | 135 } |
| 136 |
| 137 bool ShellWindow::OnMessageReceived(const IPC::Message& message) { |
| 138 bool handled = true; |
| 139 IPC_BEGIN_MESSAGE_MAP(ShellWindow, message) |
| 140 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) |
| 141 IPC_MESSAGE_UNHANDLED(handled = false) |
| 142 IPC_END_MESSAGE_MAP() |
| 143 return handled; |
| 144 } |
| 145 |
| 146 void ShellWindow::CloseContents(WebContents* contents) { |
| 147 Close(); |
| 148 } |
| 149 |
| 150 // TODO(benwells): Rearrange so users of this can call |
| 151 // WebContents::set_should_suppress_dialogs(bool) instead of overriding |
| 152 // this delegate function. |
| 153 bool ShellWindow::ShouldSuppressDialogs() { |
| 154 return true; |
| 155 } |
| 156 |
| 157 void ShellWindow::Observe(int type, |
| 158 const content::NotificationSource& source, |
| 159 const content::NotificationDetails& details) { |
| 160 switch (type) { |
| 161 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| 162 const Extension* unloaded_extension = |
| 163 content::Details<UnloadedExtensionInfo>(details)->extension; |
| 164 if (extension_ == unloaded_extension) |
| 165 Close(); |
| 166 break; |
| 167 } |
| 168 case content::NOTIFICATION_APP_TERMINATING: |
| 169 Close(); |
| 170 break; |
| 171 default: |
| 172 NOTREACHED() << "Received unexpected notification"; |
| 173 } |
| 174 } |
| 175 |
| 176 ExtensionWindowController* ShellWindow::GetExtensionWindowController() const { |
| 177 return extension_window_controller_.get(); |
| 178 } |
| 179 |
| 180 void ShellWindow::OnRequest(const ExtensionHostMsg_Request_Params& params) { |
| 181 extension_function_dispatcher_.Dispatch(params, |
| 182 web_contents_->GetRenderViewHost()); |
| 183 } |
| OLD | NEW |