OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #import "chrome/browser/cocoa/content_exceptions_window_controller.h" | 5 #import "chrome/browser/cocoa/content_exceptions_window_controller.h" |
6 | 6 |
7 #include "app/l10n_util_mac.h" | 7 #include "app/l10n_util_mac.h" |
8 #include "app/table_model_observer.h" | 8 #include "app/table_model_observer.h" |
9 #import "base/mac_util.h" | 9 #import "base/mac_util.h" |
10 #import "base/scoped_nsobject.h" | 10 #import "base/scoped_nsobject.h" |
11 #include "base/sys_string_conversions.h" | 11 #include "base/sys_string_conversions.h" |
12 #include "chrome/browser/content_exceptions_table_model.h" | 12 #include "chrome/browser/content_exceptions_table_model.h" |
13 #include "chrome/common/notification_registrar.h" | 13 #include "chrome/common/notification_registrar.h" |
14 #include "chrome/common/notification_service.h" | 14 #include "chrome/common/notification_service.h" |
15 #include "grit/generated_resources.h" | 15 #include "grit/generated_resources.h" |
16 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" | 16 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" |
17 | 17 |
18 @interface ContentExceptionsWindowController (Private) | 18 @interface ContentExceptionsWindowController (Private) |
19 - (id)initWithType:(ContentSettingsType)settingsType | 19 - (id)initWithType:(ContentSettingsType)settingsType |
20 settingsMap:(HostContentSettingsMap*)settingsMap; | 20 settingsMap:(HostContentSettingsMap*)settingsMap |
| 21 otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap; |
21 - (void)updateRow:(NSInteger)row | 22 - (void)updateRow:(NSInteger)row |
22 withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry; | 23 withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry |
| 24 forOtr:(BOOL)isOtr; |
23 - (void)adjustEditingButtons; | 25 - (void)adjustEditingButtons; |
24 - (void)modelDidChange; | 26 - (void)modelDidChange; |
25 - (size_t)menuItemCount; | 27 - (size_t)menuItemCount; |
26 - (NSString*)titleForIndex:(size_t)index; | 28 - (NSString*)titleForIndex:(size_t)index; |
27 - (ContentSetting)settingForIndex:(size_t)index; | 29 - (ContentSetting)settingForIndex:(size_t)index; |
28 - (size_t)indexForSetting:(ContentSetting)setting; | 30 - (size_t)indexForSetting:(ContentSetting)setting; |
29 @end | 31 @end |
30 | 32 |
31 //////////////////////////////////////////////////////////////////////////////// | 33 //////////////////////////////////////////////////////////////////////////////// |
32 // PatternFormatter | 34 // PatternFormatter |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 | 136 |
135 //////////////////////////////////////////////////////////////////////////////// | 137 //////////////////////////////////////////////////////////////////////////////// |
136 // ContentExceptionsWindowController implementation | 138 // ContentExceptionsWindowController implementation |
137 | 139 |
138 static ContentExceptionsWindowController* | 140 static ContentExceptionsWindowController* |
139 g_exceptionWindows[CONTENT_SETTINGS_NUM_TYPES] = { nil }; | 141 g_exceptionWindows[CONTENT_SETTINGS_NUM_TYPES] = { nil }; |
140 | 142 |
141 @implementation ContentExceptionsWindowController | 143 @implementation ContentExceptionsWindowController |
142 | 144 |
143 + (id)controllerForType:(ContentSettingsType)settingsType | 145 + (id)controllerForType:(ContentSettingsType)settingsType |
144 settingsMap:(HostContentSettingsMap*)settingsMap { | 146 settingsMap:(HostContentSettingsMap*)settingsMap |
| 147 otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap { |
145 if (!g_exceptionWindows[settingsType]) { | 148 if (!g_exceptionWindows[settingsType]) { |
146 g_exceptionWindows[settingsType] = | 149 g_exceptionWindows[settingsType] = |
147 [[ContentExceptionsWindowController alloc] initWithType:settingsType | 150 [[ContentExceptionsWindowController alloc] |
148 settingsMap:settingsMap]; | 151 initWithType:settingsType |
| 152 settingsMap:settingsMap |
| 153 otrSettingsMap:otrSettingsMap]; |
149 } | 154 } |
150 return g_exceptionWindows[settingsType]; | 155 return g_exceptionWindows[settingsType]; |
151 } | 156 } |
152 | 157 |
153 - (id)initWithType:(ContentSettingsType)settingsType | 158 - (id)initWithType:(ContentSettingsType)settingsType |
154 settingsMap:(HostContentSettingsMap*)settingsMap { | 159 settingsMap:(HostContentSettingsMap*)settingsMap |
| 160 otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap { |
155 NSString* nibpath = | 161 NSString* nibpath = |
156 [mac_util::MainAppBundle() pathForResource:@"ContentExceptionsWindow" | 162 [mac_util::MainAppBundle() pathForResource:@"ContentExceptionsWindow" |
157 ofType:@"nib"]; | 163 ofType:@"nib"]; |
158 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { | 164 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { |
159 settingsType_ = settingsType; | 165 settingsType_ = settingsType; |
160 settingsMap_ = settingsMap; | 166 settingsMap_ = settingsMap; |
161 model_.reset(new ContentExceptionsTableModel(settingsMap_, settingsType_)); | 167 otrSettingsMap_ = otrSettingsMap; |
| 168 model_.reset(new ContentExceptionsTableModel( |
| 169 settingsMap_, otrSettingsMap_, settingsType_)); |
162 showAsk_ = settingsType_ == CONTENT_SETTINGS_TYPE_COOKIES; | 170 showAsk_ = settingsType_ == CONTENT_SETTINGS_TYPE_COOKIES; |
| 171 otrAllowed_ = otrSettingsMap != NULL; |
163 tableObserver_.reset(new UpdatingContentSettingsObserver(self)); | 172 tableObserver_.reset(new UpdatingContentSettingsObserver(self)); |
164 updatesEnabled_ = YES; | 173 updatesEnabled_ = YES; |
165 | 174 |
166 // TODO(thakis): autoremember window rect. | 175 // TODO(thakis): autoremember window rect. |
167 // TODO(thakis): sorting support. | 176 // TODO(thakis): sorting support. |
168 } | 177 } |
169 return self; | 178 return self; |
170 } | 179 } |
171 | 180 |
172 - (void)awakeFromNib { | 181 - (void)awakeFromNib { |
(...skipping 19 matching lines...) Expand all Loading... |
192 [allowItem.get() setTag:[self settingForIndex:i]]; | 201 [allowItem.get() setTag:[self settingForIndex:i]]; |
193 [menu.get() addItem:allowItem.get()]; | 202 [menu.get() addItem:allowItem.get()]; |
194 } | 203 } |
195 NSCell* menuCell = | 204 NSCell* menuCell = |
196 [[tableView_ tableColumnWithIdentifier:@"action"] dataCell]; | 205 [[tableView_ tableColumnWithIdentifier:@"action"] dataCell]; |
197 [menuCell setMenu:menu.get()]; | 206 [menuCell setMenu:menu.get()]; |
198 | 207 |
199 NSCell* patternCell = | 208 NSCell* patternCell = |
200 [[tableView_ tableColumnWithIdentifier:@"pattern"] dataCell]; | 209 [[tableView_ tableColumnWithIdentifier:@"pattern"] dataCell]; |
201 [patternCell setFormatter:[[[PatternFormatter alloc] init] autorelease]]; | 210 [patternCell setFormatter:[[[PatternFormatter alloc] init] autorelease]]; |
| 211 |
| 212 if (!otrAllowed_) { |
| 213 [tableView_ |
| 214 removeTableColumn:[tableView_ tableColumnWithIdentifier:@"otr"]]; |
| 215 } |
202 } | 216 } |
203 | 217 |
204 - (void)setMinWidth:(CGFloat)minWidth { | 218 - (void)setMinWidth:(CGFloat)minWidth { |
205 NSWindow* window = [self window]; | 219 NSWindow* window = [self window]; |
206 [window setMinSize:NSMakeSize(minWidth, [window minSize].height)]; | 220 [window setMinSize:NSMakeSize(minWidth, [window minSize].height)]; |
207 if ([window frame].size.width < minWidth) { | 221 if ([window frame].size.width < minWidth) { |
208 NSRect frame = [window frame]; | 222 NSRect frame = [window frame]; |
209 frame.size.width = minWidth; | 223 frame.size.width = minWidth; |
210 [window setFrame:frame display:NO]; | 224 [window setFrame:frame display:NO]; |
211 } | 225 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 // Table View Data Source ----------------------------------------------------- | 346 // Table View Data Source ----------------------------------------------------- |
333 | 347 |
334 - (NSInteger)numberOfRowsInTableView:(NSTableView*)table { | 348 - (NSInteger)numberOfRowsInTableView:(NSTableView*)table { |
335 return model_->RowCount() + (newException_.get() ? 1 : 0); | 349 return model_->RowCount() + (newException_.get() ? 1 : 0); |
336 } | 350 } |
337 | 351 |
338 - (id)tableView:(NSTableView*)tv | 352 - (id)tableView:(NSTableView*)tv |
339 objectValueForTableColumn:(NSTableColumn*)tableColumn | 353 objectValueForTableColumn:(NSTableColumn*)tableColumn |
340 row:(NSInteger)row { | 354 row:(NSInteger)row { |
341 const HostContentSettingsMap::PatternSettingPair* entry; | 355 const HostContentSettingsMap::PatternSettingPair* entry; |
342 if (newException_.get() && row >= model_->RowCount()) | 356 int isOtr; |
| 357 if (newException_.get() && row >= model_->RowCount()) { |
343 entry = newException_.get(); | 358 entry = newException_.get(); |
344 else | 359 isOtr = 0; |
| 360 } else { |
345 entry = &model_->entry_at(row); | 361 entry = &model_->entry_at(row); |
| 362 isOtr = model_->entry_is_off_the_record(row) ? 1 : 0; |
| 363 } |
346 | 364 |
347 NSObject* result = nil; | 365 NSObject* result = nil; |
348 NSString* identifier = [tableColumn identifier]; | 366 NSString* identifier = [tableColumn identifier]; |
349 if ([identifier isEqualToString:@"pattern"]) { | 367 if ([identifier isEqualToString:@"pattern"]) { |
350 result = base::SysUTF8ToNSString(entry->first.AsString()); | 368 result = base::SysUTF8ToNSString(entry->first.AsString()); |
351 } else if ([identifier isEqualToString:@"action"]) { | 369 } else if ([identifier isEqualToString:@"action"]) { |
352 result = [NSNumber numberWithInt:[self indexForSetting:entry->second]]; | 370 result = [NSNumber numberWithInt:[self indexForSetting:entry->second]]; |
| 371 } else if ([identifier isEqualToString:@"otr"]) { |
| 372 result = [NSNumber numberWithInt:isOtr]; |
353 } else { | 373 } else { |
354 NOTREACHED(); | 374 NOTREACHED(); |
355 } | 375 } |
356 return result; | 376 return result; |
357 } | 377 } |
358 | 378 |
359 // Updates exception at |row| to contain the data in |entry|. | 379 // Updates exception at |row| to contain the data in |entry|. |
360 - (void)updateRow:(NSInteger)row | 380 - (void)updateRow:(NSInteger)row |
361 withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry { | 381 withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry |
| 382 forOtr:(BOOL)isOtr { |
362 // TODO(thakis): This apparently moves an edited row to the back of the list. | 383 // TODO(thakis): This apparently moves an edited row to the back of the list. |
363 // It's what windows and linux do, but it's kinda sucky. Fix. | 384 // It's what windows and linux do, but it's kinda sucky. Fix. |
364 // http://crbug.com/36904 | 385 // http://crbug.com/36904 |
365 updatesEnabled_ = NO; | 386 updatesEnabled_ = NO; |
366 if (row < model_->RowCount()) | 387 if (row < model_->RowCount()) |
367 model_->RemoveException(row); | 388 model_->RemoveException(row); |
368 model_->AddException(entry.first, entry.second); | 389 model_->AddException(entry.first, entry.second, isOtr); |
369 updatesEnabled_ = YES; | 390 updatesEnabled_ = YES; |
370 [self modelDidChange]; | 391 [self modelDidChange]; |
371 | 392 |
372 // For now, at least re-select the edited element. | 393 // For now, at least re-select the edited element. |
373 int newIndex = model_->IndexOfExceptionByPattern(entry.first); | 394 int newIndex = model_->IndexOfExceptionByPattern(entry.first, isOtr); |
374 DCHECK(newIndex != -1); | 395 DCHECK(newIndex != -1); |
375 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex] | 396 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex] |
376 byExtendingSelection:NO]; | 397 byExtendingSelection:NO]; |
377 } | 398 } |
378 | 399 |
379 - (void) tableView:(NSTableView*)tv | 400 - (void) tableView:(NSTableView*)tv |
380 setObjectValue:(id)object | 401 setObjectValue:(id)object |
381 forTableColumn:(NSTableColumn*)tableColumn | 402 forTableColumn:(NSTableColumn*)tableColumn |
382 row:(NSInteger)row { | 403 row:(NSInteger)row { |
383 // -remove: and -removeAll: both call |tableView_|'s -deselectAll:, which | 404 // -remove: and -removeAll: both call |tableView_|'s -deselectAll:, which |
384 // calls this method if a cell is currently being edited. Do not commit edits | 405 // calls this method if a cell is currently being edited. Do not commit edits |
385 // of rows that are about to be deleted. | 406 // of rows that are about to be deleted. |
386 if (!updatesEnabled_) { | 407 if (!updatesEnabled_) { |
387 // If this method gets called, the pattern filed of the new exception can no | 408 // If this method gets called, the pattern filed of the new exception can no |
388 // longer be being edited. Reset |newException_| to keep the invariant true. | 409 // longer be being edited. Reset |newException_| to keep the invariant true. |
389 newException_.reset(); | 410 newException_.reset(); |
390 return; | 411 return; |
391 } | 412 } |
392 | 413 |
393 // Get model object. | 414 // Get model object. |
394 bool isNewRow = newException_.get() && row >= model_->RowCount(); | 415 bool isNewRow = newException_.get() && row >= model_->RowCount(); |
395 HostContentSettingsMap::PatternSettingPair originalEntry = | 416 HostContentSettingsMap::PatternSettingPair originalEntry = |
396 isNewRow ? *newException_ : model_->entry_at(row); | 417 isNewRow ? *newException_ : model_->entry_at(row); |
397 HostContentSettingsMap::PatternSettingPair entry = originalEntry; | 418 HostContentSettingsMap::PatternSettingPair entry = originalEntry; |
| 419 bool isOtr = |
| 420 isNewRow ? 0 : model_->entry_is_off_the_record(row); |
| 421 bool wasOtr = isOtr; |
398 | 422 |
399 // Modify it. | 423 // Modify it. |
400 NSString* identifier = [tableColumn identifier]; | 424 NSString* identifier = [tableColumn identifier]; |
401 if ([identifier isEqualToString:@"pattern"]) { | 425 if ([identifier isEqualToString:@"pattern"]) { |
402 entry.first = HostContentSettingsMap::Pattern( | 426 entry.first = HostContentSettingsMap::Pattern( |
403 base::SysNSStringToUTF8(object)); | 427 base::SysNSStringToUTF8(object)); |
404 } | 428 } |
405 if ([identifier isEqualToString:@"action"]) { | 429 if ([identifier isEqualToString:@"action"]) { |
406 int index = [object intValue]; | 430 int index = [object intValue]; |
407 entry.second = [self settingForIndex:index]; | 431 entry.second = [self settingForIndex:index]; |
408 } | 432 } |
| 433 if ([identifier isEqualToString:@"otr"]) { |
| 434 isOtr = [object intValue] != 0; |
| 435 } |
409 | 436 |
410 // Commit modification, if any. | 437 // Commit modification, if any. |
411 if (isNewRow) { | 438 if (isNewRow) { |
412 newException_.reset(); | 439 newException_.reset(); |
413 if (![identifier isEqualToString:@"pattern"]) { | 440 if (![identifier isEqualToString:@"pattern"]) { |
414 [tableView_ reloadData]; | 441 [tableView_ reloadData]; |
415 [self adjustEditingButtons]; | 442 [self adjustEditingButtons]; |
416 return; // Commit new rows only when the pattern has been set. | 443 return; // Commit new rows only when the pattern has been set. |
417 } | 444 } |
418 int newIndex = model_->IndexOfExceptionByPattern(entry.first); | 445 int newIndex = model_->IndexOfExceptionByPattern(entry.first, false); |
419 if (newIndex != -1) { | 446 if (newIndex != -1) { |
420 // The new pattern was already in the table. Focus existing row instead of | 447 // The new pattern was already in the table. Focus existing row instead of |
421 // overwriting it with a new one. | 448 // overwriting it with a new one. |
422 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex] | 449 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex] |
423 byExtendingSelection:NO]; | 450 byExtendingSelection:NO]; |
424 [tableView_ reloadData]; | 451 [tableView_ reloadData]; |
425 [self adjustEditingButtons]; | 452 [self adjustEditingButtons]; |
426 return; | 453 return; |
427 } | 454 } |
428 } | 455 } |
429 if (entry != originalEntry || isNewRow) | 456 if (entry != originalEntry || wasOtr != isOtr || isNewRow) |
430 [self updateRow:row withEntry:entry]; | 457 [self updateRow:row withEntry:entry forOtr:isOtr]; |
431 } | 458 } |
432 | 459 |
433 | 460 |
434 // Table View Delegate -------------------------------------------------------- | 461 // Table View Delegate -------------------------------------------------------- |
435 | 462 |
436 // When the selection in the table view changes, we need to adjust buttons. | 463 // When the selection in the table view changes, we need to adjust buttons. |
437 - (void)tableViewSelectionDidChange:(NSNotification*)notification { | 464 - (void)tableViewSelectionDidChange:(NSNotification*)notification { |
438 [self adjustEditingButtons]; | 465 [self adjustEditingButtons]; |
439 } | 466 } |
440 | 467 |
(...skipping 10 matching lines...) Expand all Loading... |
451 - (void)modelDidChange { | 478 - (void)modelDidChange { |
452 // Some calls on |model_|, e.g. RemoveException(), change something on the | 479 // Some calls on |model_|, e.g. RemoveException(), change something on the |
453 // backing content settings map object (which sends a notification) and then | 480 // backing content settings map object (which sends a notification) and then |
454 // change more stuff in |model_|. If |model_| is deleted when the notification | 481 // change more stuff in |model_|. If |model_| is deleted when the notification |
455 // is sent, this second access causes a segmentation violation. Hence, disable | 482 // is sent, this second access causes a segmentation violation. Hence, disable |
456 // resetting |model_| while updates can be in progress. | 483 // resetting |model_| while updates can be in progress. |
457 if (!updatesEnabled_) | 484 if (!updatesEnabled_) |
458 return; | 485 return; |
459 | 486 |
460 // The model caches its data, meaning we need to recreate it on every change. | 487 // The model caches its data, meaning we need to recreate it on every change. |
461 model_.reset(new ContentExceptionsTableModel(settingsMap_, settingsType_)); | 488 model_.reset(new ContentExceptionsTableModel( |
| 489 settingsMap_, otrSettingsMap_, settingsType_)); |
462 | 490 |
463 [tableView_ reloadData]; | 491 [tableView_ reloadData]; |
464 [self adjustEditingButtons]; | 492 [self adjustEditingButtons]; |
465 } | 493 } |
466 | 494 |
467 - (size_t)menuItemCount { | 495 - (size_t)menuItemCount { |
468 return showAsk_ ? arraysize(kAskSettings) : arraysize(kNoAskSettings); | 496 return showAsk_ ? arraysize(kAskSettings) : arraysize(kNoAskSettings); |
469 } | 497 } |
470 | 498 |
471 - (NSString*)titleForIndex:(size_t)index { | 499 - (NSString*)titleForIndex:(size_t)index { |
(...skipping 17 matching lines...) Expand all Loading... |
489 - (size_t)indexForSetting:(ContentSetting)setting { | 517 - (size_t)indexForSetting:(ContentSetting)setting { |
490 for (size_t i = 0; i < [self menuItemCount]; ++i) { | 518 for (size_t i = 0; i < [self menuItemCount]; ++i) { |
491 if ([self settingForIndex:i] == setting) | 519 if ([self settingForIndex:i] == setting) |
492 return i; | 520 return i; |
493 } | 521 } |
494 NOTREACHED(); | 522 NOTREACHED(); |
495 return 0; | 523 return 0; |
496 } | 524 } |
497 | 525 |
498 @end | 526 @end |
OLD | NEW |