Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: d72d6fe5cb
Fetching contributors…

Cannot retrieve contributors at this time

file 460 lines (364 sloc) 14.031 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
#import "CTBrowser.h"
#import "CTTabStripModel.h"
#import "CTTabStripController.h"
#import "CTPageTransition.h"
#import "CTBrowserWindowController.h"
#import "CTTabContentsController.h"
#import "CTToolbarController.h"
#import "CTUtil.h"

@implementation CTBrowser

@synthesize windowController = windowController_;
@synthesize tabStripModel = tabStripModel_;


/*- (id)retain {
self = [super retain];
NSLog(@"%@ did retain (retainCount: %u)", self, [self retainCount]);
NSLog(@"%@", [NSThread callStackSymbols]);
return self;
}

- (void)release {
NSLog(@"%@ will release (retainCount: %u)", self, [self retainCount]);
NSLog(@"%@", [NSThread callStackSymbols]);
[super release];
}*/


+ (CTBrowser*)browser {
  return [[[self alloc] init] autorelease];
}


- (id)init {
  if ((self = [super init])) {
    tabStripModel_ = new CTTabStripModel(self);
  }
  return self;
}


-(void)dealloc {
  DLOG("[ChromiumTabs] deallocing browser %@", self);
  delete tabStripModel_;
  [super dealloc];
}


-(void)finalize {
  delete tabStripModel_;
  [super finalize];
}


-(CTToolbarController *)createToolbarController {
  // subclasses could override this -- returning nil means no toolbar
  NSBundle *bundle = [CTUtil bundleForResource:@"Toolbar" ofType:@"nib"];
  return [[[CTToolbarController alloc] initWithNibName:@"Toolbar"
                                                   bundle:bundle
                                                  browser:self] autorelease];
}

-(CTTabContentsController*)createTabContentsControllerWithContents:
    (CTTabContents*)contents {
  // subclasses could override this
  return [[[CTTabContentsController alloc]
      initWithContents:contents] autorelease];
}


#pragma mark -
#pragma mark Accessors

-(NSWindow*)window {
  return [windowController_ window];
}

// TabStripModel convenience helpers

-(int)tabCount {
  return tabStripModel_->count();
}

-(int)selectedTabIndex {
  return tabStripModel_->selected_index();
}

-(CTTabContents*)selectedTabContents {
  return tabStripModel_->GetSelectedTabContents();
}

-(CTTabContents*)tabContentsAtIndex:(int)index {
  return tabStripModel_->GetTabContentsAt(index);
}

- (NSArray*)allTabContents {
  NSUInteger i = 0, count = tabStripModel_->count();
  NSMutableArray *array = [NSMutableArray arrayWithCapacity:count];
  for (; i<count; ++i) {
    [array insertObject:tabStripModel_->GetTabContentsAt(i) atIndex:i];
  }
  return array;
}

-(int)indexOfTabContents:(CTTabContents*)contents {
  return tabStripModel_->GetIndexOfTabContents(contents);
}

-(void)selectTabContentsAtIndex:(int)index userGesture:(BOOL)userGesture {
  tabStripModel_->SelectTabContentsAt(index, userGesture);
}

-(void)updateTabStateAtIndex:(int)index {
  tabStripModel_->UpdateTabContentsStateAt(index, CTTabChangeTypeAll);
}

-(void)updateTabStateForContent:(CTTabContents*)contents {
  int index = tabStripModel_->GetIndexOfTabContents(contents);
  if (index != -1) {
    tabStripModel_->UpdateTabContentsStateAt(index, CTTabChangeTypeAll);
  }
}

-(void)replaceTabContentsAtIndex:(int)index
                 withTabContents:(CTTabContents*)contents {
  tabStripModel_->ReplaceTabContentsAt(index, contents, (CTTabReplaceType)0);
}

-(void)closeTabAtIndex:(int)index makeHistory:(BOOL)makeHistory {
  tabStripModel_->CloseTabContentsAt(index,
      makeHistory ? CTTabStripModel::CLOSE_CREATE_HISTORICAL_TAB : 0);
}

-(void)closeAllTabs {
  tabStripModel_->CloseAllTabs();
}

#pragma mark -
#pragma mark Callbacks

-(void)loadingStateDidChange:(CTTabContents*)contents {
  // TODO: Make sure the loading state is updated correctly
}

-(void)windowDidBeginToClose {
  tabStripModel_->CloseAllTabs();
}


#pragma mark -
#pragma mark UI state


/*-(NSRect)savedWindowBounds {
gfx::Rect restored_bounds = override_bounds_;
bool maximized;
WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, NULL,
&restored_bounds, &maximized);
return restored_bounds;
}*/


#pragma mark -
#pragma mark Commands

-(void)newWindow {
  // Create a new browser & window when we start
  Class cls = self.windowController ? [self.windowController class] :
                                      [CTBrowserWindowController class];
  CTBrowser *browser = [isa browser];
  CTBrowserWindowController* windowController =
      [[cls alloc] initWithBrowser:browser];
  [browser addBlankTabInForeground:YES];
  [windowController showWindow:self];
  [windowController autorelease];
}

-(void)closeWindow {
  [self.windowController close];
}

-(CTTabContents*)addTabContents:(CTTabContents*)contents
                        atIndex:(int)index
                   inForeground:(BOOL)foreground {
  int addTypes = foreground ? (CTTabStripModel::ADD_SELECTED |
                               CTTabStripModel::ADD_INHERIT_GROUP)
                            : CTTabStripModel::ADD_NONE;
  index = tabStripModel_->AddTabContents(contents, index, CTPageTransitionTyped,
                                         addTypes);
  if ((addTypes & CTTabStripModel::ADD_SELECTED) == 0) {
    // TabStripModel::AddTabContents invokes HideContents if not foreground.
    contents.isVisible = NO;
  }
  return contents;
}


-(CTTabContents*)addTabContents:(CTTabContents*)contents
                   inForeground:(BOOL)foreground {
  return [self addTabContents:contents atIndex:-1 inForeground:foreground];
}


-(CTTabContents*)addTabContents:(CTTabContents*)contents {
  return [self addTabContents:contents atIndex:-1 inForeground:YES];
}


-(CTTabContents*)createBlankTabBasedOn:(CTTabContents*)baseContents {
  // subclasses should override this to provide a custom CTTabContents type
  // and/or initialization
  return [[[CTTabContents alloc]
      initWithBaseTabContents:baseContents] autorelease];
}

// implementation conforms to CTTabStripModelDelegate
-(CTTabContents*)addBlankTabAtIndex:(int)index inForeground:(BOOL)foreground {
  CTTabContents* baseContents = tabStripModel_->GetSelectedTabContents();
  CTTabContents* contents = [self createBlankTabBasedOn:baseContents];
  return [self addTabContents:contents atIndex:index inForeground:foreground];
}

// implementation conforms to CTTabStripModelDelegate
-(CTTabContents*)addBlankTabInForeground:(BOOL)foreground {
  return [self addBlankTabAtIndex:-1 inForeground:foreground];
}

-(CTTabContents*)addBlankTab {
  return [self addBlankTabInForeground:YES];
}

-(void)closeTab {
  if ([self canCloseTab]) {
    tabStripModel_->CloseTabContentsAt(
        tabStripModel_->selected_index(),
        CTTabStripModel::CLOSE_USER_GESTURE |
        CTTabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
  }
}

-(void)selectNextTab {
  tabStripModel_->SelectNextTab();
}

-(void)selectPreviousTab {
  tabStripModel_->SelectPreviousTab();
}

-(void)moveTabNext {
  tabStripModel_->MoveTabNext();
}

-(void)moveTabPrevious {
  tabStripModel_->MoveTabPrevious();
}

-(void)selectTabAtIndex:(int)index {
  if (index < tabStripModel_->count()) {
    tabStripModel_->SelectTabContentsAt(index, true);
  }
}

-(void)selectLastTab {
  tabStripModel_->SelectLastTab();
}

-(void)duplicateTab {
  //[self duplicateContentsAt:tabStripModel_->selected_index()];
  // can't do this currently
}


-(void)executeCommand:(int)cmd
      withDisposition:(CTWindowOpenDisposition)disposition {
  //DLOG_EXPR(cmd); //< useful to debug incoming |cmd| values
  // No commands are enabled if there is not yet any selected tab.
  // TODO(pkasting): It seems like we should not need this, because either
  // most/all commands should not have been enabled yet anyway or the ones that
  // are enabled should be global, or safe themselves against having no selected
  // tab. However, Ben says he tried removing this before and got lots of
  // crashes, e.g. from Windows sending WM_COMMANDs at random times during
  // window construction. This probably could use closer examination someday.
  if (![self selectedTabContents])
    return;

  // If command execution is blocked then just record the command and return.
  /*if (block_command_execution_) {
// We actually only allow no more than one blocked command, otherwise some
// commands maybe lost.
DCHECK_EQ(last_blocked_command_id_, -1);
last_blocked_command_id_ = id;
last_blocked_command_disposition_ = disposition;
return;
}*/

  // The order of commands in this switch statement must match the function
  // declaration order in BrowserCommands.h
  switch (cmd) {
    // Window management commands
    case CTBrowserCommandNewWindow: [self newWindow]; break;
    //case CTBrowserCommandNewIncognitoWindow: break;
    case CTBrowserCommandCloseWindow: [self closeWindow]; break;
    //case CTBrowserCommandAlwaysOnTop: break;
    case CTBrowserCommandNewTab: [self addBlankTab]; break;
    case CTBrowserCommandCloseTab: [self closeTab]; break;
    case CTBrowserCommandSelectNextTab: [self selectNextTab]; break;
    case CTBrowserCommandSelectPreviousTab: [self selectPreviousTab]; break;
    case CTBrowserCommandSelectTab0:
    case CTBrowserCommandSelectTab1:
    case CTBrowserCommandSelectTab2:
    case CTBrowserCommandSelectTab3:
    case CTBrowserCommandSelectTab4:
    case CTBrowserCommandSelectTab5:
    case CTBrowserCommandSelectTab6:
    case CTBrowserCommandSelectTab7: {
      [self selectTabAtIndex:cmd - CTBrowserCommandSelectTab0];
      break;
    }
    case CTBrowserCommandSelectLastTab: [self selectLastTab]; break;
    case CTBrowserCommandDuplicateTab: [self duplicateTab]; break;
    //case CTBrowserCommandRestoreTab: break;
    //case CTBrowserCommandShowAsTab: break;
    //case CTBrowserCommandFullscreen: DLOG("TODO ToggleFullscreenMode();"); break;
    case CTBrowserCommandExit: [NSApp terminate:self]; break;
    case CTBrowserCommandMoveTabNext: [self moveTabNext]; break;
    case CTBrowserCommandMoveTabPrevious: [self moveTabPrevious]; break;
  }
}

-(void)executeCommand:(int)cmd {
  [self executeCommand:cmd withDisposition:CTWindowOpenDispositionCurrentTab];
}

+(void)executeCommand:(int)cmd {
  switch (cmd) {
    case CTBrowserCommandExit: [NSApp terminate:self]; break;
  }
}


#pragma mark -
#pragma mark CTTabStripModelDelegate protocol implementation


-(CTBrowser*)createNewStripWithContents:(CTTabContents*)contents {
  //assert(CanSupportWindowFeature(FEATURE_TABSTRIP));

  //gfx::Rect new_window_bounds = window_bounds;
  //if (dock_info.GetNewWindowBounds(&new_window_bounds, &maximize))
  // dock_info.AdjustOtherWindowBounds();

  // Create an empty new browser window the same size as the old one.
  CTBrowser* browser = [isa browser];
  browser.tabStripModel->AppendTabContents(contents, true);
  [browser loadingStateDidChange:contents];

  // Orig impl:
  //browser->set_override_bounds(new_window_bounds);
  //browser->set_maximized_state(
  // maximize ? MAXIMIZED_STATE_MAXIMIZED : MAXIMIZED_STATE_UNMAXIMIZED);
  //browser->CreateBrowserWindow();
  //browser->tabstrip_model()->AppendTabContents(contents, true);

  // Make sure the loading state is updated correctly, otherwise the throbber
  // won't start if the page is loading.
  //browser->LoadingStateChanged(contents);

  return browser;
}

// Creates a new CTBrowser object and window containing the specified
// |contents|, and continues a drag operation that began within the source
// window's tab strip. |window_bounds| are the bounds of the source window in
// screen coordinates, used to place the new window, and |tab_bounds| are the
// bounds of the dragged Tab view in the source window, in screen coordinates,
// used to place the new Tab in the new window.
-(void)continueDraggingDetachedTab:(CTTabContents*)contents
                      windowBounds:(const NSRect)windowBounds
                         tabBounds:(const NSRect)tabBounds {
  NOTIMPLEMENTED();
}


// Returns whether some contents can be duplicated.
-(BOOL)canDuplicateContentsAt:(int)index {
  return NO;
}

// Duplicates the contents at the provided index and places it into its own
// window.
-(void)duplicateContentsAt:(int)index {
  NOTIMPLEMENTED();
}

// Called when a drag session has completed and the frame that initiated the
// the session should be closed.
-(void)closeFrameAfterDragSession {
  DLOG("[ChromiumTabs] closeFrameAfterDragSession");
}

// Creates an entry in the historical tab database for the specified
// CTTabContents.
-(void)createHistoricalTab:(CTTabContents*)contents {
  DLOG("[ChromiumTabs] TODO createHistoricalTab %@", contents);
}

// Runs any unload listeners associated with the specified CTTabContents before
// it is closed. If there are unload listeners that need to be run, this
// function returns true and the TabStripModel will wait before closing the
// CTTabContents. If it returns false, there are no unload listeners and the
// TabStripModel can close the CTTabContents immediately.
-(BOOL)runUnloadListenerBeforeClosing:(CTTabContents*)contents {
  return NO;
}

// Returns true if a tab can be restored.
-(BOOL)canRestoreTab {
  return NO;
}

// Restores the last closed tab if CanRestoreTab would return true.
-(void)restoreTab {
}

// Returns whether some contents can be closed.
-(BOOL)canCloseContentsAt:(int)index {
  return YES;
}

// Returns true if any of the tabs can be closed.
-(BOOL)canCloseTab {
  return YES;
}


#pragma mark -
#pragma mark NSFastEnumeration


- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
                                  objects:(id *)stackbuf
                                    count:(NSUInteger)fetchCount {
  NSUInteger totalCount = tabStripModel_->count();
  NSUInteger fetchIndex = 0;

  while (state->state+fetchIndex < totalCount && fetchIndex < fetchCount) {
    stackbuf[fetchIndex++] =
        tabStripModel_->GetTabContentsAt(state->state + fetchIndex);
  }

  state->state += fetchIndex;
  state->itemsPtr = stackbuf;
  state->mutationsPtr = (unsigned long *)self; // TODO

  return fetchIndex;
}


@end
Something went wrong with that request. Please try again.