Commit e3df3398 authored by rdsmith@chromium.org's avatar rdsmith@chromium.org

Revert 182194

> Fix issue 174250, crash when reloading packaged app.
> 
> When a shell window was closed, it wasn't removed from the registry immediately
> (it was removed in a callback from OnNativeClose, which happens a bit later.)
> This meant that when the app was loaded again, the window was still in the
> registry with a stale pointer to the old extension. ExtensionSettingsHandler
> was tickling this by iterating shell windows on extension load.
> 
> BUG=174250
> 
> 
> Review URL: https://chromiumcodereview.appspot.com/12210107

TBR=jeremya@chromium.org
Review URL: https://codereview.chromium.org/12207155

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182230 0039d316-1c4b-4281-b951-d872f2087c98
parent 1d3865f8
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/web_contents_modal_dialog_manager.h" #include "chrome/browser/ui/web_contents_modal_dialog_manager.h"
#include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_notification_types.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
...@@ -687,7 +686,7 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReloadRelaunches) { ...@@ -687,7 +686,7 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReloadRelaunches) {
ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
ASSERT_TRUE(GetFirstShellWindow()); ASSERT_TRUE(GetFirstShellWindow());
// Now tell the app to reload itself. // Now tell the app to reload itself
ExtensionTestMessageListener launched_listener2("Launched", false); ExtensionTestMessageListener launched_listener2("Launched", false);
launched_listener.Reply("reload"); launched_listener.Reply("reload");
ASSERT_TRUE(launched_listener2.WaitUntilSatisfied()); ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
...@@ -852,22 +851,4 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_WebContentsHasFocus) { ...@@ -852,22 +851,4 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_WebContentsHasFocus) {
CloseShellWindow(window); CloseShellWindow(window);
} }
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DontCrashWhenReloading) {
// Regression test for http://crbug.com/174250
browser()->profile()->GetPrefs()->SetBoolean(
prefs::kExtensionsUIDeveloperMode, true);
ui_test_utils::NavigateToURL(browser(), GURL("chrome://extensions"));
ExtensionTestMessageListener launched_listener("Launched", true);
const Extension* extension = LoadAndLaunchPlatformApp("reload");
ASSERT_TRUE(extension);
ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
ASSERT_TRUE(GetFirstShellWindow());
// Now tell the app to reload itself.
ExtensionTestMessageListener launched_listener2("Launched", false);
launched_listener.Reply("reload");
ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
ASSERT_TRUE(GetFirstShellWindow());
}
} // namespace extensions } // namespace extensions
...@@ -67,9 +67,8 @@ void ShellWindowRegistry::ShellWindowIconChanged(ShellWindow* shell_window) { ...@@ -67,9 +67,8 @@ void ShellWindowRegistry::ShellWindowIconChanged(ShellWindow* shell_window) {
} }
void ShellWindowRegistry::RemoveShellWindow(ShellWindow* shell_window) { void ShellWindowRegistry::RemoveShellWindow(ShellWindow* shell_window) {
size_t num_erased = shell_windows_.erase(shell_window); shell_windows_.erase(shell_window);
if (num_erased > 0) FOR_EACH_OBSERVER(Observer, observers_, OnShellWindowRemoved(shell_window));
FOR_EACH_OBSERVER(Observer, observers_, OnShellWindowRemoved(shell_window));
} }
void ShellWindowRegistry::AddObserver(Observer* observer) { void ShellWindowRegistry::AddObserver(Observer* observer) {
......
...@@ -4,9 +4,7 @@ ...@@ -4,9 +4,7 @@
#include "chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h" #include "chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h"
#include "base/bind.h"
#include "base/mac/mac_util.h" #include "base/mac/mac_util.h"
#include "base/message_loop.h"
#include "base/sys_string_conversions.h" #include "base/sys_string_conversions.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/cocoa/browser_window_utils.h" #include "chrome/browser/ui/cocoa/browser_window_utils.h"
...@@ -681,13 +679,7 @@ gfx::Insets NativeAppWindowCocoa::GetFrameInsets() const { ...@@ -681,13 +679,7 @@ gfx::Insets NativeAppWindowCocoa::GetFrameInsets() const {
void NativeAppWindowCocoa::WindowWillClose() { void NativeAppWindowCocoa::WindowWillClose() {
[window_controller_ setAppWindow:NULL]; [window_controller_ setAppWindow:NULL];
shell_window_->OnNativeWindowChanged(); shell_window_->OnNativeWindowChanged();
// On other platforms, the native window doesn't get destroyed synchronously. shell_window_->OnNativeClose();
// We simulate that here so that ShellWindow can assume that it doesn't get
// deleted immediately upon calling Close().
MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&ShellWindow::OnNativeClose,
base::Unretained(shell_window_)));
} }
void NativeAppWindowCocoa::WindowDidBecomeKey() { void NativeAppWindowCocoa::WindowDidBecomeKey() {
......
...@@ -244,11 +244,6 @@ ShellWindow::~ShellWindow() { ...@@ -244,11 +244,6 @@ ShellWindow::~ShellWindow() {
chrome::EndKeepAlive(); chrome::EndKeepAlive();
} }
void ShellWindow::Close() {
extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
native_app_window_->Close();
}
void ShellWindow::RequestMediaAccessPermission( void ShellWindow::RequestMediaAccessPermission(
content::WebContents* web_contents, content::WebContents* web_contents,
const content::MediaStreamRequest& request, const content::MediaStreamRequest& request,
...@@ -348,16 +343,9 @@ void ShellWindow::RequestToLockMouse(WebContents* web_contents, ...@@ -348,16 +343,9 @@ void ShellWindow::RequestToLockMouse(WebContents* web_contents,
} }
void ShellWindow::OnNativeClose() { void ShellWindow::OnNativeClose() {
// This method is shared between the path for the user clicking the close
// button and the path where a close is triggered by code (e.g. by the
// extension being unloaded). In the latter case, this RemoveShellWindow is
// superfluous, since it will already have been removed, but the call is
// idempotent so it's harmless the second time.
extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this); extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
if (extension_) { content::RenderViewHost* rvh = web_contents_->GetRenderViewHost();
content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); rvh->Send(new ExtensionMsg_AppWindowClosed(rvh->GetRoutingID()));
rvh->Send(new ExtensionMsg_AppWindowClosed(rvh->GetRoutingID()));
}
delete this; delete this;
} }
...@@ -499,7 +487,7 @@ void ShellWindow::UpdateExtensionAppIcon() { ...@@ -499,7 +487,7 @@ void ShellWindow::UpdateExtensionAppIcon() {
void ShellWindow::CloseContents(WebContents* contents) { void ShellWindow::CloseContents(WebContents* contents) {
DCHECK(contents == web_contents_); DCHECK(contents == web_contents_);
Close(); native_app_window_->Close();
} }
bool ShellWindow::ShouldSuppressDialogs() { bool ShellWindow::ShouldSuppressDialogs() {
...@@ -573,16 +561,12 @@ void ShellWindow::Observe(int type, ...@@ -573,16 +561,12 @@ void ShellWindow::Observe(int type,
const extensions::Extension* unloaded_extension = const extensions::Extension* unloaded_extension =
content::Details<extensions::UnloadedExtensionInfo>( content::Details<extensions::UnloadedExtensionInfo>(
details)->extension; details)->extension;
if (extension_ == unloaded_extension) { if (extension_ == unloaded_extension)
Close(); native_app_window_->Close();
// After this notification finishes processing, the Extension will be
// deleted, so we null out our reference to avoid bad access.
extension_ = NULL;
}
break; break;
} }
case chrome::NOTIFICATION_APP_TERMINATING: case chrome::NOTIFICATION_APP_TERMINATING:
Close(); native_app_window_->Close();
break; break;
default: default:
NOTREACHED() << "Received unexpected notification"; NOTREACHED() << "Received unexpected notification";
......
...@@ -133,11 +133,6 @@ class ShellWindow : public content::NotificationObserver, ...@@ -133,11 +133,6 @@ class ShellWindow : public content::NotificationObserver,
// per platform). Public users of ShellWindow should use ShellWindow::Create. // per platform). Public users of ShellWindow should use ShellWindow::Create.
void Init(const GURL& url, const CreateParams& params); void Init(const GURL& url, const CreateParams& params);
// Remove the window from the ShellWindowRegistry and tell the native
// window to close. The native window won't be actually closed until
// OnNativeClose().
void Close();
// content::WebContentsObserver implementation. // content::WebContentsObserver implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include "chrome/browser/ui/gtk/extensions/native_app_window_gtk.h" #include "chrome/browser/ui/gtk/extensions/native_app_window_gtk.h"
#include "base/message_loop.h"
#include "base/utf_string_conversions.h" #include "base/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h" #include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h"
...@@ -185,15 +184,12 @@ void NativeAppWindowGtk::Close() { ...@@ -185,15 +184,12 @@ void NativeAppWindowGtk::Close() {
// To help catch bugs in any event handlers that might get fired during the // To help catch bugs in any event handlers that might get fired during the
// destruction, set window_ to NULL before any handlers will run. // destruction, set window_ to NULL before any handlers will run.
window_ = NULL; window_ = NULL;
gtk_widget_destroy(window);
// On other platforms, the native window doesn't get destroyed synchronously. // OnNativeClose does a delete this so no other members should
// We simulate that here so that ShellWindow can assume that it doesn't get // be accessed after. gtk_widget_destroy is safe (and must
// deleted immediately upon calling Close(). // be last).
MessageLoop::current()->PostTask( shell_window_->OnNativeClose();
FROM_HERE, gtk_widget_destroy(window);
base::Bind(&ShellWindow::OnNativeClose,
base::Unretained(shell_window_)));
} }
void NativeAppWindowGtk::Activate() { void NativeAppWindowGtk::Activate() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment