[Mac] Create CrTrackingArea and use it in TabStripController.

CrTrackingArea can prevent messages from being sent to the tracking area's
owner, which is the source of a significant number of zombie crashes. This hopes
to prevent that.

BUG=48709
TEST=Crash reports go down.

Review URL: http://codereview.chromium.org/6486002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@74940 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/ui/cocoa/tracking_area_unittest.mm b/chrome/browser/ui/cocoa/tracking_area_unittest.mm
new file mode 100644
index 0000000..151d033
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tracking_area_unittest.mm
@@ -0,0 +1,86 @@
+// Copyright (c) 2011 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 "base/scoped_nsobject.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/ui/cocoa/objc_zombie.h"
+#import "chrome/browser/ui/cocoa/tracking_area.h"
+
+// A test object that counts the number of times a message is sent to it.
+@interface TestTrackingAreaOwner : NSObject {
+ @private
+  NSUInteger messageCount_;
+}
+@property(nonatomic, assign) NSUInteger messageCount;
+- (void)performMessage;
+@end
+
+@implementation TestTrackingAreaOwner
+@synthesize messageCount = messageCount_;
+- (void)performMessage {
+  ++messageCount_;
+}
+@end
+
+class CrTrackingAreaTest : public CocoaTest {
+ public:
+  CrTrackingAreaTest()
+      : owner_([[TestTrackingAreaOwner alloc] init]),
+        trackingArea_([[CrTrackingArea alloc]
+            initWithRect:NSMakeRect(0, 0, 100, 100)
+                 options:NSTrackingMouseMoved | NSTrackingActiveInKeyWindow
+                   owner:owner_.get()
+                userInfo:nil]) {
+  }
+
+  scoped_nsobject<TestTrackingAreaOwner> owner_;
+  scoped_nsobject<CrTrackingArea> trackingArea_;
+};
+
+TEST_F(CrTrackingAreaTest, OwnerForwards) {
+  [[trackingArea_ owner] performMessage];
+  EXPECT_EQ(1U, [owner_ messageCount]);
+
+  [[trackingArea_ owner] performMessage];
+  EXPECT_EQ(2U, [owner_ messageCount]);
+}
+
+TEST_F(CrTrackingAreaTest, OwnerStopsForwarding) {
+  [[trackingArea_ owner] performMessage];
+  EXPECT_EQ(1U, [owner_ messageCount]);
+
+  [trackingArea_ clearOwner];
+
+  [[trackingArea_ owner] performMessage];
+  EXPECT_EQ(1U, [owner_ messageCount]);
+}
+
+TEST_F(CrTrackingAreaTest, OwnerAutomaticallyStopsForwardingOnClose) {
+  [test_window() orderFront:nil];
+  [trackingArea_ clearOwnerWhenWindowWillClose:test_window()];
+
+  [[trackingArea_ owner] performMessage];
+  EXPECT_EQ(1U, [owner_ messageCount]);
+
+  [test_window() close];
+
+  [[trackingArea_ owner] performMessage];
+  EXPECT_EQ(1U, [owner_ messageCount]);
+}
+
+TEST_F(CrTrackingAreaTest, ZombieOwner) {
+  EXPECT_TRUE(ObjcEvilDoers::ZombieEnable(NO, 20));
+
+  [[trackingArea_ owner] performMessage];
+  EXPECT_EQ(1U, [owner_ messageCount]);
+
+  [owner_ shouldBecomeCrZombie];
+  owner_.reset();
+  [trackingArea_ clearOwner];
+
+  [[trackingArea_ owner] performMessage];
+  // Don't crash!
+
+  ObjcEvilDoers::ZombieDisable();
+}