Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: chrome/browser/resources/ntp_search/apps_page.js

Issue 12207138: Remove unused ntp_search. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 cr.define('ntp', function() {
6 'use strict';
7
8 var Tile = ntp.Tile;
9 var TilePage = ntp.TilePage;
10 var APP_LAUNCH = ntp.APP_LAUNCH;
11
12 // Histogram buckets for UMA tracking of where a DnD drop came from.
13 var DRAG_SOURCE = {
14 SAME_APPS_PANE: 0,
15 OTHER_APPS_PANE: 1,
16 MOST_VISITED_PANE: 2,
17 BOOKMARKS_PANE: 3,
18 OUTSIDE_NTP: 4
19 };
20 var DRAG_SOURCE_LIMIT = DRAG_SOURCE.OUTSIDE_NTP + 1;
21
22 /**
23 * App context menu. The class is designed to be used as a singleton with
24 * the app that is currently showing a context menu stored in this.app_.
25 * @constructor
26 */
27 function AppContextMenu() {
28 this.__proto__ = AppContextMenu.prototype;
29 this.initialize();
30 }
31 cr.addSingletonGetter(AppContextMenu);
32
33 AppContextMenu.prototype = {
34 initialize: function() {
35 var menu = new cr.ui.Menu;
36 cr.ui.decorate(menu, cr.ui.Menu);
37 menu.classList.add('app-context-menu');
38 this.menu = menu;
39
40 this.launch_ = this.appendMenuItem_();
41 this.launch_.addEventListener('activate', this.onLaunch_.bind(this));
42
43 menu.appendChild(cr.ui.MenuItem.createSeparator());
44 this.launchRegularTab_ = this.appendMenuItem_('applaunchtyperegular');
45 this.launchPinnedTab_ = this.appendMenuItem_('applaunchtypepinned');
46 if (!cr.isMac)
47 this.launchNewWindow_ = this.appendMenuItem_('applaunchtypewindow');
48 this.launchFullscreen_ = this.appendMenuItem_('applaunchtypefullscreen');
49
50 var self = this;
51 this.forAllLaunchTypes_(function(launchTypeButton, id) {
52 launchTypeButton.addEventListener('activate',
53 self.onLaunchTypeChanged_.bind(self));
54 });
55
56 menu.appendChild(cr.ui.MenuItem.createSeparator());
57 this.options_ = this.appendMenuItem_('appoptions');
58 this.details_ = this.appendMenuItem_('appdetails');
59 this.disableNotifications_ =
60 this.appendMenuItem_('appdisablenotifications');
61 this.uninstall_ = this.appendMenuItem_('appuninstall');
62 this.options_.addEventListener('activate',
63 this.onShowOptions_.bind(this));
64 this.details_.addEventListener('activate',
65 this.onShowDetails_.bind(this));
66 this.disableNotifications_.addEventListener(
67 'activate', this.onDisableNotifications_.bind(this));
68 this.uninstall_.addEventListener('activate',
69 this.onUninstall_.bind(this));
70
71 if (!cr.isMac && !cr.isChromeOS) {
72 menu.appendChild(cr.ui.MenuItem.createSeparator());
73 this.createShortcut_ = this.appendMenuItem_('appcreateshortcut');
74 this.createShortcut_.addEventListener(
75 'activate', this.onCreateShortcut_.bind(this));
76 }
77
78 document.body.appendChild(menu);
79 },
80
81 /**
82 * Appends a menu item to |this.menu|.
83 * @param {?string} textId If non-null, the ID for the localized string
84 * that acts as the item's label.
85 */
86 appendMenuItem_: function(textId) {
87 var button = cr.doc.createElement('button');
88 this.menu.appendChild(button);
89 cr.ui.decorate(button, cr.ui.MenuItem);
90 if (textId)
91 button.textContent = loadTimeData.getString(textId);
92 return button;
93 },
94
95 /**
96 * Iterates over all the launch type menu items.
97 * @param {function(cr.ui.MenuItem, number)} f The function to call for each
98 * menu item. The parameters to the function include the menu item and
99 * the associated launch ID.
100 */
101 forAllLaunchTypes_: function(f) {
102 // Order matters: index matches launchType id.
103 var launchTypes = [this.launchPinnedTab_,
104 this.launchRegularTab_,
105 this.launchFullscreen_,
106 this.launchNewWindow_];
107
108 for (var i = 0; i < launchTypes.length; ++i) {
109 if (!launchTypes[i])
110 continue;
111
112 f(launchTypes[i], i);
113 }
114 },
115
116 /**
117 * Does all the necessary setup to show the menu for the given app.
118 * @param {App} app The App object that will be showing a context menu.
119 */
120 setupForApp: function(app) {
121 this.app_ = app;
122
123 this.launch_.textContent = app.data.title;
124
125 this.forAllLaunchTypes_(function(launchTypeButton, id) {
126 launchTypeButton.disabled = false;
127 launchTypeButton.checked = app.data.launch_type == id;
128 });
129
130 this.options_.disabled = !app.data.optionsUrl || !app.data.enabled;
131 this.details_.disabled = !app.data.detailsUrl;
132 this.uninstall_.disabled = !app.data.mayDisable;
133
134 this.disableNotifications_.hidden = true;
135 var notificationsDisabled = app.data.notifications_disabled;
136 if (typeof notificationsDisabled != 'undefined') {
137 this.disableNotifications_.hidden = false;
138 this.disableNotifications_.checked = notificationsDisabled;
139 }
140 },
141
142 /**
143 * Handlers for menu item activation.
144 * @param {Event} e The activation event.
145 * @private
146 */
147 onLaunch_: function(e) {
148 chrome.send('launchApp', [this.app_.appId, APP_LAUNCH.NTP_APPS_MENU]);
149 },
150 onLaunchTypeChanged_: function(e) {
151 var pressed = e.currentTarget;
152 var app = this.app_;
153 this.forAllLaunchTypes_(function(launchTypeButton, id) {
154 if (launchTypeButton == pressed) {
155 chrome.send('setLaunchType', [app.appId, id]);
156 // Manually update the launch type. We will only get
157 // appsPrefChangeCallback calls after changes to other NTP instances.
158 app.data.launch_type = id;
159 }
160 });
161 },
162 onShowOptions_: function(e) {
163 window.location = this.app_.data.optionsUrl;
164 },
165 onShowDetails_: function(e) {
166 var url = this.app_.data.detailsUrl;
167 url = appendParam(url, 'utm_source', 'chrome-ntp-launcher');
168 window.location = url;
169 },
170 onDisableNotifications_: function(e) {
171 var app = this.app_;
172 app.removeBubble();
173 // Toggle the current disable setting.
174 var newSetting = !this.disableNotifications_.checked;
175 app.data.notifications_disabled = newSetting;
176 chrome.send('setNotificationsDisabled', [app.data.id, newSetting]);
177 },
178 onUninstall_: function(e) {
179 chrome.send('uninstallApp', [this.app_.data.id]);
180 },
181 onCreateShortcut_: function(e) {
182 chrome.send('createAppShortcut', [this.app_.data.id]);
183 },
184 };
185
186 /**
187 * Creates a new App object.
188 * @param {Object=} opt_data The data representing the app.
189 * @constructor
190 * @extends {HTMLDivElement}
191 */
192 function App(opt_data) {
193 var el = cr.doc.createElement('div');
194 el.__proto__ = App.prototype;
195 el.initialize_();
196
197 if (opt_data)
198 el.data = opt_data;
199
200 return el;
201 }
202
203 App.prototype = Tile.subclass({
204 __proto__: HTMLDivElement.prototype,
205
206 /**
207 * Initialize the app object.
208 * @private
209 */
210 initialize_: function() {
211 Tile.prototype.initialize.apply(this, arguments);
212
213 this.classList.add('app');
214 this.classList.add('focusable');
215 },
216
217 /**
218 * Formats this app according to |data|.
219 * @param {Object} data The data object that describes the app.
220 * @private
221 */
222 formatApp_: function(data) {
223 assert(this.data_.id, 'Got an app without an ID');
224 this.id = this.data_.id;
225 this.setAttribute('role', 'menuitem');
226
227 if (!this.data_.icon_big_exists && this.data_.icon_small_exists)
228 this.useSmallIcon_ = true;
229
230 // TODO(pedrosimonetti): Fix crbug.com/165612
231 if (!this.appContents_) {
232 this.appContents_ = this.useSmallIcon_ ?
233 $('app-small-icon-template').cloneNode(true) :
234 $('app-large-icon-template').cloneNode(true);
235 this.appContents_.id = '';
236 this.appendChild(this.appContents_);
237 }
238
239 this.appImgContainer_ = this.querySelector('.app-img-container');
240 this.appImg_ = this.appImgContainer_.querySelector('img');
241 this.setIcon();
242
243 var appTitle;
244 if (this.useSmallIcon_) {
245 this.classList.add('small-icon');
246 this.imgDiv_ = this.querySelector('.app-icon-div');
247 this.addLaunchClickTarget_(this.imgDiv_);
248 this.imgDiv_.title = this.data_.title;
249 appTitle = formatTitle(this.data_.title);
250 chrome.send('getAppIconDominantColor', [this.id]);
251 } else {
252 this.classList.remove('small-icon');
253 this.addLaunchClickTarget_(this.appImgContainer_);
254 this.appImgContainer_.title = this.data_.title;
255 appTitle = this.data_.title;
256 }
257
258 var appSpan = this.appContents_.querySelector('.title');
259 appSpan.textContent = appTitle;
260 appSpan.title = this.data_.title;
261 this.addLaunchClickTarget_(appSpan);
262
263 var notification = this.data_.notification;
264 var hasNotification = typeof notification != 'undefined' &&
265 typeof notification['title'] != 'undefined' &&
266 typeof notification['body'] != 'undefined' &&
267 !this.data_.notifications_disabled;
268 if (hasNotification)
269 this.setupNotification_(notification);
270
271 this.addEventListener('keydown', cr.ui.contextMenuHandler);
272 this.addEventListener('keyup', cr.ui.contextMenuHandler);
273
274 // This hack is here so that appContents.contextMenu will be the same as
275 // this.contextMenu.
276 var self = this;
277 this.appContents_.__defineGetter__('contextMenu', function() {
278 return self.contextMenu;
279 });
280 this.appContents_.addEventListener('contextmenu',
281 cr.ui.contextMenuHandler);
282
283 this.addEventListener('mousedown', this.onMousedown_, true);
284 this.addEventListener('keydown', this.onKeydown_);
285 this.addEventListener('keyup', this.onKeyup_);
286 },
287
288 /**
289 * Sets the color of the favicon dominant color bar.
290 * @param {string} color The css-parsable value for the color.
291 */
292 set stripeColor(color) {
293 this.querySelector('.color-stripe').style.backgroundColor = color;
294 },
295
296 /**
297 * Removes the app tile from the page. Should be called after the app has
298 * been uninstalled.
299 */
300 remove: function(opt_animate) {
301 // Unset the ID immediately, because the app is already gone. But leave
302 // the tile on the page as it animates out.
303 this.id = '';
304
305 if (opt_animate) {
306 var cell = this.tileCell;
307 var tilePage = cell.tilePage;
308 tilePage.dataList_.splice(cell.index, 1);
309 tilePage.animateTileRemoval(cell.index, tilePage.dataList_);
310 } else {
311 this.tileCell.doRemove(opt_animate);
312 }
313 },
314
315 /**
316 * Set the URL of the icon from |this.data_|. This won't actually show the
317 * icon until loadIcon() is called (for performance reasons; we don't want
318 * to load icons until we have to).
319 */
320 setIcon: function() {
321 var src = this.useSmallIcon_ ? this.data_.icon_small :
322 this.data_.icon_big;
323 if (!this.data_.enabled ||
324 (!this.data_.offlineEnabled && !navigator.onLine)) {
325 src += '?grayscale=true';
326 }
327
328 this.appImgSrc_ = src;
329 this.classList.add('icon-loading');
330 },
331
332 /**
333 * Shows the icon for the app. That is, it causes chrome to load the app
334 * icon resource.
335 */
336 loadIcon: function() {
337 if (this.appImgSrc_) {
338 this.appImg_.src = this.appImgSrc_;
339 this.appImg_.classList.remove('invisible');
340 this.appImgSrc_ = null;
341 }
342
343 this.classList.remove('icon-loading');
344 },
345
346 /**
347 * Creates a bubble node.
348 * @param {Object} notification The notification to show in the bubble.
349 * @param {boolean} full Whether we want the headline or just the content.
350 * @private
351 */
352 createBubbleNode_: function(notification, full) {
353 if (!full) {
354 var titleItem = this.ownerDocument.createElement('span');
355 titleItem.textContent = notification['title'];
356 return titleItem;
357 } else {
358 var container = this.ownerDocument.createElement('div');
359
360 var messageItem = this.ownerDocument.createElement('div');
361 messageItem.textContent = notification['body'];
362 container.appendChild(messageItem);
363
364 if (notification['linkUrl'] && notification['linkText']) {
365 var anchor = this.ownerDocument.createElement('a');
366 anchor.href = notification['linkUrl'];
367 anchor.textContent = notification['linkText'];
368 container.appendChild(anchor);
369 }
370
371 return container;
372 }
373 },
374
375 /**
376 * Sets up a notification for the app icon.
377 * @param {Object} notification The notification to show in the bubble.
378 * @private
379 */
380 setupNotification_: function(notification) {
381 if (notification) {
382 var infoBubble;
383 if (!this.currentBubbleShowing_) {
384 // Create a new bubble.
385 infoBubble = new cr.ui.ExpandableBubble;
386 infoBubble.anchorNode = this;
387 infoBubble.appId = this.data_.id;
388 infoBubble.handleCloseEvent = function() {
389 chrome.send('closeNotification', [this.appId]);
390 infoBubble.hide();
391 };
392 } else {
393 // Reuse the old bubble instead of popping up a new bubble over
394 // the old one.
395 infoBubble = this.currentBubbleShowing_;
396 infoBubble.collapseBubble_();
397 }
398 infoBubble.contentTitle = this.createBubbleNode_(notification, false);
399 infoBubble.content = this.createBubbleNode_(notification, true);
400 infoBubble.show();
401 infoBubble.resizeAndReposition();
402
403 this.currentBubbleShowing_ = infoBubble;
404 }
405 },
406
407 /**
408 * Removes the info bubble if there is one.
409 */
410 removeBubble: function() {
411 if (this.currentBubbleShowing_) {
412 this.currentBubbleShowing_.hide();
413 this.currentBubbleShowing_ = null;
414 }
415 },
416
417 /**
418 * Invoked when an app is clicked.
419 * @param {Event} e The click event.
420 * @private
421 */
422 onClick_: function(e) {
423 var url = !this.data_.is_webstore ? '' :
424 appendParam(this.data_.url,
425 'utm_source',
426 'chrome-ntp-icon');
427
428 chrome.send('launchApp',
429 [this.appId, APP_LAUNCH.NTP_APPS_MAXIMIZED, url,
430 e.button, e.altKey, e.ctrlKey, e.metaKey, e.shiftKey]);
431
432 // Don't allow the click to trigger a link or anything
433 e.preventDefault();
434 },
435
436 /**
437 * Invoked when the user presses a key while the app is focused.
438 * @param {Event} e The key event.
439 * @private
440 */
441 onKeydown_: function(e) {
442 if (e.keyIdentifier == 'Enter') {
443 chrome.send('launchApp',
444 [this.appId, APP_LAUNCH.NTP_APPS_MAXIMIZED, '',
445 0, e.altKey, e.ctrlKey, e.metaKey, e.shiftKey]);
446 e.preventDefault();
447 e.stopPropagation();
448 }
449 this.onKeyboardUsed_(e.keyCode);
450 },
451
452 /**
453 * Invoked when the user releases a key while the app is focused.
454 * @param {Event} e The key event.
455 * @private
456 */
457 onKeyup_: function(e) {
458 this.onKeyboardUsed_(e.keyCode);
459 },
460
461 /**
462 * Called when the keyboard has been used (key down or up). The .click-focus
463 * hack is removed if the user presses a key that can change focus.
464 * @param {number} keyCode The key code of the keyboard event.
465 * @private
466 */
467 onKeyboardUsed_: function(keyCode) {
468 switch (keyCode) {
469 case 9: // Tab.
470 case 37: // Left arrow.
471 case 38: // Up arrow.
472 case 39: // Right arrow.
473 case 40: // Down arrow.
474 this.classList.remove('click-focus');
475 }
476 },
477
478 /**
479 * Adds a node to the list of targets that will launch the app. This list
480 * is also used in onMousedown to determine whether the app contents should
481 * be shown as active (if we don't do this, then clicking anywhere in
482 * appContents, even a part that is outside the ideally clickable region,
483 * will cause the app icon to look active).
484 * @param {HTMLElement} node The node that should be clickable.
485 */
486 addLaunchClickTarget_: function(node) {
487 node.classList.add('launch-click-target');
488 node.addEventListener('click', this.onClick_.bind(this));
489 },
490
491 /**
492 * Handler for mousedown on the App. Adds a class that allows us to
493 * not display as :active for right clicks and clicks on app notifications
494 * (specifically, don't pulse on these occasions). Also, we don't pulse
495 * for clicks that aren't within the clickable regions.
496 * @param {Event} e The mousedown event.
497 */
498 onMousedown_: function(e) {
499 if (e.button == 2 ||
500 !findAncestorByClass(e.target, 'launch-click-target')) {
501 this.appContents_.classList.add('suppress-active');
502 } else {
503 this.appContents_.classList.remove('suppress-active');
504 }
505
506 // This class is here so we don't show the focus state for apps that
507 // gain keyboard focus via mouse clicking.
508 this.classList.add('click-focus');
509 },
510
511 /**
512 * Change the data and update the appearance of the app.
513 * @param {Object} data The new data object that describes the app.
514 */
515 replaceAppData: function(data) {
516 assert(data);
517 this.data = data;
518 this.setIcon();
519 this.loadIcon();
520 },
521
522 /**
523 * The data and preferences for this app.
524 * @type {Object}
525 */
526 set data(data) {
527 Object.getOwnPropertyDescriptor(Tile.prototype, 'data').set.apply(this,
528 arguments);
529
530 this.formatApp_(data);
531 },
532 get data() {
533 return this.data_;
534 },
535
536 get appId() {
537 return this.data_.id;
538 },
539
540 /**
541 * Returns a pointer to the context menu for this app. All apps share the
542 * singleton AppContextMenu. This function is called by the
543 * ContextMenuHandler in response to the 'contextmenu' event.
544 * @type {cr.ui.Menu}
545 */
546 get contextMenu() {
547 var menu = AppContextMenu.getInstance();
548 menu.setupForApp(this);
549 return menu.menu;
550 },
551
552 /**
553 * Returns whether this element can be 'removed' from chrome (i.e. whether
554 * the user can drag it onto the trash and expect something to happen).
555 * @return {boolean} True if the app can be uninstalled.
556 */
557 canBeRemoved: function() {
558 return this.data_.mayDisable;
559 },
560
561 /**
562 * Uninstalls the app after it's been dropped on the trash.
563 */
564 removeFromChrome: function() {
565 chrome.send('uninstallApp', [this.data_.id, true]);
566 this.tile.tilePage.removeTile(this.tile, true);
567 if (this.currentBubbleShowing_)
568 this.currentBubbleShowing_.hide();
569 },
570 });
571
572 /**
573 * Creates a new AppsPage object.
574 * @constructor
575 * @extends {TilePage}
576 */
577 function AppsPage() {
578 var el = new TilePage();
579 el.__proto__ = AppsPage.prototype;
580 el.initialize();
581
582 return el;
583 }
584
585 AppsPage.prototype = {
586 __proto__: TilePage.prototype,
587
588 /**
589 * Reference to the Tile subclass that will be used to create the tiles.
590 * @constructor
591 * @extends {Tile}
592 */
593 TileClass: App,
594
595 // The config object should be defined by a TilePage subclass if it
596 // wants the non-default behavior.
597 config: {
598 // The width of a cell.
599 cellWidth: 70,
600 // The start margin of a cell (left or right according to text direction).
601 cellMarginStart: 20,
602 // The maximum number of Tiles to be displayed.
603 maxTileCount: 512,
604 // Whether the TilePage content will be scrollable.
605 scrollable: true,
606 },
607
608 initialize: function() {
609 TilePage.prototype.initialize.apply(this, arguments);
610
611 this.classList.add('apps-page');
612
613 this.addEventListener('cardselected', this.onCardSelected_);
614 // Add event listeners for two events, so we can temporarily suppress
615 // the app notification bubbles when the app card slides in and out of
616 // view.
617 this.addEventListener('carddeselected', this.onCardDeselected_);
618 this.addEventListener('cardSlider:card_change_ended',
619 this.onCardChangeEnded_);
620
621 this.addEventListener('tilePage:tile_added', this.onTileAdded_);
622 },
623
624 /**
625 * Highlight a newly installed app as it's added to the NTP.
626 * @param {Object} data The data object that describes the app.
627 */
628 insertAndHighlightApp: function(data) {
629 ntp.getCardSlider().selectCardByValue(this);
630 this.insertApp(data, true);
631 },
632
633 /**
634 * Inserts an App into the TilePage, preserving the alphabetical order.
635 * @param {Object} data The data that describes the app.
636 * @param {boolean} animate Whether to animate the insertion.
637 */
638 insertApp: function(data, animate) {
639 var index = this.tiles_.length;
640 for (var i = 0; i < this.tiles_.length; i++) {
641 if (data.title.toLocaleLowerCase() <
642 this.tiles_[i].data.title.toLocaleLowerCase()) {
643 index = i;
644 break;
645 }
646 }
647
648 if (animate) {
649 this.dataList_.splice(index, 0, data);
650 this.animateTileRestoration(index, this.dataList_);
651 } else {
652 var app = new App(data);
653 this.addTileAt(app, index);
654 }
655 },
656
657 /**
658 * Handler for 'cardselected' event, fired when |this| is selected. The
659 * first time this is called, we load all the app icons.
660 * @private
661 */
662 onCardSelected_: function(e) {
663 var apps = this.querySelectorAll('.app.icon-loading');
664 for (var i = 0; i < apps.length; i++) {
665 apps[i].loadIcon();
666 if (apps[i].currentBubbleShowing_)
667 apps[i].currentBubbleShowing_.suppressed = false;
668 }
669 },
670
671 /**
672 * Handler for tile additions to this page.
673 * @param {Event} e The tilePage:tile_added event.
674 */
675 onTileAdded_: function(e) {
676 assert(e.currentTarget == this);
677 assert(e.addedTile instanceof App);
678 if (this.classList.contains('selected-card'))
679 e.addedTile.loadIcon();
680 },
681
682 /**
683 * Handler for the when this.cardSlider ends change its card. If animated,
684 * this happens when the -webkit-transition is done, otherwise happens
685 * immediately (but after cardSlider:card_changed).
686 * @private
687 */
688 onCardChangeEnded_: function(e) {
689 for (var i = 0; i < this.tiles_.length; i++) {
690 var app = this.tiles_[i];
691 assert(app instanceof App);
692 if (app.currentBubbleShowing_)
693 app.currentBubbleShowing_.suppressed = false;
694 }
695 },
696
697 /**
698 * Handler for the 'carddeselected' event, fired when the user switches
699 * to another 'card' than the App 'card' on the NTP (|this| gets
700 * deselected).
701 * @private
702 */
703 onCardDeselected_: function(e) {
704 for (var i = 0; i < this.tiles_.length; i++) {
705 var app = this.tiles_[i];
706 assert(app instanceof App);
707 if (app.currentBubbleShowing_)
708 app.currentBubbleShowing_.suppressed = true;
709 }
710 },
711
712 /** @override */
713 onScroll: function() {
714 TilePage.prototype.onScroll.apply(this, arguments);
715
716 for (var i = 0; i < this.tiles_.length; i++) {
717 var app = this.tiles_[i];
718 assert(app instanceof App);
719 if (app.currentBubbleShowing_)
720 app.currentBubbleShowing_.resizeAndReposition();
721 }
722 },
723
724 /**
725 * Creates a new crx-less app manifest and installs it.
726 * @param {Object} data The data object describing the link. Must have |url|
727 * and |title| members.
728 */
729 generateAppForLink: function(data) {
730 assert(data.url != undefined);
731 assert(data.title != undefined);
732 chrome.send('generateAppForLink', [data.url, data.title, 0]);
733 },
734 };
735
736 /**
737 * Launches the specified app using the APP_LAUNCH_NTP_APP_RE_ENABLE
738 * histogram. This should only be invoked from the AppLauncherHandler.
739 * @param {string} appID The ID of the app.
740 */
741 function launchAppAfterEnable(appId) {
742 chrome.send('launchApp', [appId, APP_LAUNCH.NTP_APP_RE_ENABLE]);
743 }
744
745 function appNotificationChanged(id, notification) {
746 var app = $(id);
747 // The app might have been uninstalled, or notifications might be disabled.
748 if (app && !app.data.notifications_disabled)
749 app.setupNotification_(notification);
750 }
751
752 /**
753 * Formats titles by removing the leading 'http://www.' part of the URL,
754 * and the last slash, so 'http://www.test.com/' becomes 'test.com'.
755 * @param {string} title Page's title.
756 * @return {string} The formatted title.
757 */
758 function formatTitle(title) {
759 return title.replace(/^(https?\:\/\/)?(www\.)?|\/$/gi, '');
760 }
761
762 return {
763 appNotificationChanged: appNotificationChanged,
764 AppsPage: AppsPage,
765 launchAppAfterEnable: launchAppAfterEnable,
766 };
767 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/ntp_search/apps_page.css ('k') | chrome/browser/resources/ntp_search/dot_list.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698