Merge f-t to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 20 Dec 2014 12:18:28 -0800
changeset 220744 7b33ee7fd162d784f382250d3fa811e86a1b7348
parent 220731 ba0dc109a8f86ca831866a5933cf863d379434cd (current diff)
parent 220743 9acd85c8081c8933e6d179bd0c68ac3b90eb0f01 (diff)
child 220745 b915a50bc6be1b25ee86874b8dd7137549b23e67
child 220747 b76d6ff5eec502e66e9ab544c6d12c9550dc3442
child 220774 6dcfe614583a493e3bffeaa40307b051b0f1f4d0
child 220846 4dbb2ddd009361e3df9c6c4fe31227fd4499398a
push id27997
push userphilringnalda@gmail.com
push dateSat, 20 Dec 2014 20:18:46 +0000
treeherdermozilla-central@7b33ee7fd162 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone37.0a1
first release with
nightly linux32
7b33ee7fd162 / 37.0a1 / 20141221030204 / files
nightly linux64
7b33ee7fd162 / 37.0a1 / 20141221030204 / files
nightly mac
7b33ee7fd162 / 37.0a1 / 20141221030204 / files
nightly win32
7b33ee7fd162 / 37.0a1 / 20141221030204 / files
nightly win64
7b33ee7fd162 / 37.0a1 / 20141221030204 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge f-t to m-c, a=merge
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -350,18 +350,17 @@ toolbarbutton.bookmark-item > menupopup 
 .bookmark-item:not(#home-button) > .toolbarbutton-icon,
 #personal-bookmarks[cui-areatype="toolbar"] > #bookmarks-toolbar-placeholder > .toolbarbutton-icon {
   width: 16px;
   min-height: 16px;
   max-height: 16px;
 }
 
 .bookmark-item > .toolbarbutton-icon[label]:not([label=""]),
-.bookmark-item > .toolbarbutton-icon[type="menu"],
-#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder > .toolbarbutton-icon[label]:not([label=""]) {
+.bookmark-item > .toolbarbutton-icon[type="menu"] {
   -moz-margin-end: 5px;
 }
 
 .bookmark-item[container] {
   list-style-image: url("chrome://global/skin/tree/folder.png");
 }
 
 .bookmark-item[container][livemark] {
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -270,16 +270,20 @@ toolbarpaletteitem[place="toolbar"] {
   display: none;
 }
 
 #wrapper-personal-bookmarks:not([place="toolbar"]) > #personal-bookmarks {
   -moz-box-pack: center;
   min-height: 48px;
 }
 
+#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder > .toolbarbutton-icon {
+  -moz-margin-end: 5px;
+}
+
 #customization-palette > toolbarpaletteitem > label {
   text-align: center;
   margin-left: 0;
   margin-right: 0;
 }
 
 #customization-lwtheme-menu > .panel-arrowcontainer > .panel-arrowcontent {
   -moz-box-orient: vertical;
--- a/mobile/android/base/FindInPageBar.java
+++ b/mobile/android/base/FindInPageBar.java
@@ -219,17 +219,18 @@ public class FindInPageBar extends Linea
         GeckoAppShell.sendRequestToGecko(new GeckoRequest(request, json) {
             @Override
             public void onResponse(NativeJSObject nativeJSObject) {
                 final int total = nativeJSObject.optInt("total", 0);
                 final int current = nativeJSObject.optInt("current", 0);
                 updateResult(total, current);
             }
 
-            public void onError() {
+            @Override
+            public void onError(NativeJSObject error) {
                 // Gecko didn't respond due to state change, javascript error, etc.
                 updateResult(0, 0);
                 Log.d(LOGTAG, "No response from Gecko on request to match string: [" +
                     searchString + "]");
             }
 
             private void updateResult(int total, int current) {
                 final Boolean statusVisibility = (total > 0);
--- a/mobile/android/base/ReadingListHelper.java
+++ b/mobile/android/base/ReadingListHelper.java
@@ -91,16 +91,17 @@ public final class ReadingListHelper imp
                     showToast(R.string.reading_list_duplicate, Toast.LENGTH_SHORT);
 
                 } else {
                     final ContentValues values = new ContentValues();
                     values.put(ReadingListItems.URL, url);
                     values.put(ReadingListItems.TITLE, message.optString("title"));
                     values.put(ReadingListItems.LENGTH, message.optInt("length"));
                     values.put(ReadingListItems.EXCERPT, message.optString("excerpt"));
+                    values.put(ReadingListItems.CONTENT_STATUS, message.optInt("status"));
                     BrowserDB.addReadingListItem(cr, values);
 
                     showToast(R.string.reading_list_added, Toast.LENGTH_SHORT);
                 }
             }
         });
 
         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Reader:Added", url));
--- a/mobile/android/base/db/BrowserContract.java
+++ b/mobile/android/base/db/BrowserContract.java
@@ -347,16 +347,26 @@ public class BrowserContract {
         public static final Uri CONTENT_URI = Uri.withAppendedPath(READING_LIST_AUTHORITY_URI, "items");
 
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/readinglistitem";
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/readinglistitem";
 
         public static final String EXCERPT = "excerpt";
         public static final String READ = "read";
         public static final String LENGTH = "length";
+
+        public static final String CONTENT_STATUS = "content_status";
+
+        // CONTENT_STATUS represents the result of an attempt to fetch content for the reading list item.
+        public static final int STATUS_UNFETCHED = 0;
+        public static final int STATUS_FETCH_FAILED_TEMPORARY = 1;
+        public static final int STATUS_FETCH_FAILED_PERMANENT = 2;
+        public static final int STATUS_FETCH_FAILED_UNSUPPORTED_FORMAT = 3;
+        public static final int STATUS_FETCHED_ARTICLE = 4;
+
         public static final String DEFAULT_SORT_ORDER = DATE_MODIFIED + " DESC";
         public static final String[] DEFAULT_PROJECTION = new String[] { _ID, URL, TITLE, EXCERPT, LENGTH };
 
         // Minimum fields required to create a reading list item.
         public static final String[] REQUIRED_FIELDS = { Bookmarks.URL, Bookmarks.TITLE };
 
         public static final String TABLE_NAME = "reading_list";
     }
--- a/mobile/android/base/db/BrowserDatabaseHelper.java
+++ b/mobile/android/base/db/BrowserDatabaseHelper.java
@@ -28,17 +28,17 @@ import android.database.sqlite.SQLiteOpe
 import android.net.Uri;
 import android.os.Build;
 import android.util.Log;
 
 
 final class BrowserDatabaseHelper extends SQLiteOpenHelper {
 
     private static final String LOGTAG = "GeckoBrowserDBHelper";
-    public static final int DATABASE_VERSION = 21;
+    public static final int DATABASE_VERSION = 22;
     public static final String DATABASE_NAME = "browser.db";
 
     final protected Context mContext;
 
     static final String TABLE_BOOKMARKS = Bookmarks.TABLE_NAME;
     static final String TABLE_HISTORY = History.TABLE_NAME;
     static final String TABLE_FAVICONS = Favicons.TABLE_NAME;
     static final String TABLE_THUMBNAILS = Thumbnails.TABLE_NAME;
@@ -319,22 +319,25 @@ final class BrowserDatabaseHelper extend
                     ReadingListItems.URL + " TEXT NOT NULL, " +
                     ReadingListItems.TITLE + " TEXT, " +
                     ReadingListItems.EXCERPT + " TEXT, " +
                     ReadingListItems.READ + " TINYINT DEFAULT 0, " +
                     ReadingListItems.IS_DELETED + " TINYINT DEFAULT 0, " +
                     ReadingListItems.GUID + " TEXT UNIQUE NOT NULL, " +
                     ReadingListItems.DATE_MODIFIED + " INTEGER NOT NULL, " +
                     ReadingListItems.DATE_CREATED + " INTEGER NOT NULL, " +
-                    ReadingListItems.LENGTH + " INTEGER DEFAULT 0 ); ");
+                    ReadingListItems.LENGTH + " INTEGER DEFAULT 0, " +
+                    ReadingListItems.CONTENT_STATUS + " TINYINT DEFAULT " + ReadingListItems.STATUS_UNFETCHED + "); ");
 
         db.execSQL("CREATE INDEX reading_list_url ON " + TABLE_READING_LIST + "("
                 + ReadingListItems.URL + ")");
         db.execSQL("CREATE UNIQUE INDEX reading_list_guid ON " + TABLE_READING_LIST + "("
                 + ReadingListItems.GUID + ")");
+        db.execSQL("CREATE INDEX reading_list_content_status ON " + TABLE_READING_LIST + "("
+                + ReadingListItems.CONTENT_STATUS + ")");
     }
 
     private void createOrUpdateAllSpecialFolders(SQLiteDatabase db) {
         createOrUpdateSpecialFolder(db, Bookmarks.MOBILE_FOLDER_GUID,
             R.string.bookmarks_folder_mobile, 0);
         createOrUpdateSpecialFolder(db, Bookmarks.TOOLBAR_FOLDER_GUID,
             R.string.bookmarks_folder_toolbar, 1);
         createOrUpdateSpecialFolder(db, Bookmarks.MENU_FOLDER_GUID,
@@ -756,16 +759,27 @@ final class BrowserDatabaseHelper extend
                    Bookmarks.TYPE + " = " + Bookmarks.TYPE_BOOKMARK +
                    " WHERE " + Bookmarks.TYPE + " IS NULL");
     }
 
     private void upgradeDatabaseFrom19to20(SQLiteDatabase db) {
         createSearchHistoryTable(db);
     }
 
+    private void upgradeDatabaseFrom21to22(SQLiteDatabase db) {
+        debug("Adding CONTENT_STATUS column to reading list table.");
+
+        db.execSQL("ALTER TABLE " + TABLE_READING_LIST +
+                   " ADD COLUMN " + ReadingListItems.CONTENT_STATUS +
+                   " TINYINT DEFAULT " + ReadingListItems.STATUS_UNFETCHED);
+
+        db.execSQL("CREATE INDEX reading_list_content_status ON " + TABLE_READING_LIST + "("
+                + ReadingListItems.CONTENT_STATUS + ")");
+    }
+
     private void createV19CombinedView(SQLiteDatabase db) {
         db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED);
         db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED_WITH_FAVICONS);
 
         createCombinedViewOn19(db);
     }
 
     @Override
@@ -819,16 +833,20 @@ final class BrowserDatabaseHelper extend
 
                 case 19:
                     upgradeDatabaseFrom18to19(db);
                     break;
 
                 case 20:
                     upgradeDatabaseFrom19to20(db);
                     break;
+
+                case 22:
+                    upgradeDatabaseFrom21to22(db);
+                    break;
             }
         }
 
         for (Table table : BrowserProvider.sTables) {
             table.onUpgrade(db, oldVersion, newVersion);
         }
 
         // Delete the obsolete favicon database after all other upgrades complete.
--- a/mobile/android/base/resources/layout/find_in_page_content.xml
+++ b/mobile/android/base/resources/layout/find_in_page_content.xml
@@ -27,17 +27,17 @@
               android:layout_marginRight="@dimen/find_in_page_status_margin_right"
               android:textColor="@color/find_status_default"
               android:visibility="gone"/>
 
     <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
                      android:id="@+id/find_matchcase"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:layout_marginRight="@dimen/find_in_page_matchcase_margin_right"
+                     android:padding="@dimen/find_in_page_matchcase_padding"
                      android:checked="false"
                      android:text="@string/find_matchcase"
                      android:textColor="@drawable/find_matchcase_selector"/>
 
     <ImageButton android:id="@+id/find_prev"
                  style="@style/FindBar.ImageButton"
                  android:contentDescription="@string/find_prev"
                  android:layout_marginTop="@dimen/find_in_page_control_margin_top"
--- a/mobile/android/base/resources/values/dimens.xml
+++ b/mobile/android/base/resources/values/dimens.xml
@@ -190,13 +190,13 @@
 
     <dimen name="horizontal_drag_area">256dp</dimen>
 
     <!-- Find-In-Page dialog dimensions. -->
     <dimen name="find_in_page_text_margin_left">5dip</dimen>
     <dimen name="find_in_page_text_margin_right">12dip</dimen>
     <dimen name="find_in_page_text_padding_left">10dip</dimen>
     <dimen name="find_in_page_text_padding_right">10dip</dimen>
-    <dimen name="find_in_page_status_margin_right">15dip</dimen>
-    <dimen name="find_in_page_matchcase_margin_right">10dip</dimen>
+    <dimen name="find_in_page_status_margin_right">10dip</dimen>
+    <dimen name="find_in_page_matchcase_padding">10dip</dimen>
     <dimen name="find_in_page_control_margin_top">2dip</dimen>
 
 </resources>
--- a/mobile/android/base/tests/testReadingListProvider.java
+++ b/mobile/android/base/tests/testReadingListProvider.java
@@ -86,16 +86,20 @@ public class testReadingListProvider ext
         public void test() throws Exception {
             ContentValues b = createFillerReadingListItem();
             long id = ContentUris.parseId(mProvider.insert(ReadingListItems.CONTENT_URI, b));
             Cursor c = getItemById(id);
 
             try {
                 mAsserter.ok(c.moveToFirst(), "Inserted item found", "");
                 assertRowEqualsContentValues(c, b);
+
+                mAsserter.is(c.getInt(c.getColumnIndex(ReadingListItems.CONTENT_STATUS)),
+                             ReadingListItems.STATUS_UNFETCHED,
+                             "Inserted item has correct default content status");
             } finally {
                 c.close();
             }
 
             testInsertWithNullCol(ReadingListItems.GUID);
             mContentProviderInsertTested = true;
         }
 
--- a/mobile/android/chrome/content/FindHelper.js
+++ b/mobile/android/chrome/content/FindHelper.js
@@ -50,17 +50,23 @@ var FindHelper = {
 
   _init: function() {
     // If there's no find in progress, start one.
     if (this._finder) {
       return;
     }
 
     this._targetTab = BrowserApp.selectedTab;
-    this._finder = this._targetTab.browser.finder;
+    try {
+      this._finder = this._targetTab.browser.finder;
+    } catch (e) {
+      throw new Error("FindHelper: " + e + "\n" +
+        "JS stack: \n" + (e.stack || Components.stack.formattedStack));
+    }
+
     this._finder.addResultListener(this);
     this._initialViewport = JSON.stringify(this._targetTab.getViewport());
     this._viewportChanged = false;
   },
 
   _uninit: function() {
     // If there's no find in progress, there's nothing to clean up.
     if (!this._finder) {
--- a/mobile/android/chrome/content/Reader.js
+++ b/mobile/android/chrome/content/Reader.js
@@ -1,15 +1,27 @@
 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
+const { utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/ReaderMode.jsm");
+
 let Reader = {
+  // These values should match those defined in BrowserContract.java.
+  STATUS_UNFETCHED: 0,
+  STATUS_FETCH_FAILED_TEMPORARY: 1,
+  STATUS_FETCH_FAILED_PERMANENT: 2,
+  STATUS_FETCH_FAILED_UNSUPPORTED_FORMAT: 3,
+  STATUS_FETCHED_ARTICLE: 4,
+
   get isEnabledForParseOnLoad() {
     delete this.isEnabledForParseOnLoad;
 
     // Listen for future pref changes.
     Services.prefs.addObserver("reader.parse-on-load.", this, false);
 
     return this.isEnabledForParseOnLoad = this._getStateForParseOnLoad();
   },
@@ -87,17 +99,23 @@ let Reader = {
 
     let article = yield this.getArticle(urlWithoutRef, tabID).catch(e => {
       Cu.reportError("Error getting article for tab: " + e);
       return null;
     });
     if (!article) {
       // If there was a problem getting the article, just store the
       // URL and title from the tab.
-      article = { url: urlWithoutRef, title: tab.browser.contentDocument.title };
+      article = {
+        url: urlWithoutRef,
+        title: tab.browser.contentDocument.title,
+        status: this.STATUS_FETCH_FAILED_UNSUPPORTED_FORMAT,
+      };
+    } else {
+      article.status = this.STATUS_FETCHED_ARTICLE;
     }
 
     this.addArticleToReadingList(article);
   }),
 
   addArticleToReadingList: function(article) {
     if (!article || !article.url) {
       Cu.reportError("addArticleToReadingList requires article with valid URL");
@@ -105,16 +123,17 @@ let Reader = {
     }
 
     Messaging.sendRequest({
       type: "Reader:AddToList",
       url: truncate(article.url, MAX_URI_LENGTH),
       title: truncate(article.title || "", MAX_TITLE_LENGTH),
       length: article.length || 0,
       excerpt: article.excerpt || "",
+      status: article.status,
     });
 
     ReaderMode.storeArticleInCache(article).catch(e => Cu.reportError("Error storing article in cache: " + e));
   },
 
   _getStateForParseOnLoad: function () {
     let isEnabled = Services.prefs.getBoolPref("reader.parse-on-load.enabled");
     let isForceEnabled = Services.prefs.getBoolPref("reader.parse-on-load.force-enabled");
--- a/toolkit/components/reader/content/aboutReader.js
+++ b/toolkit/components/reader/content/aboutReader.js
@@ -304,16 +304,18 @@ AboutReader.prototype = {
     });
   },
 
   _onReaderToggle: function Reader_onToggle() {
     if (!this._article)
       return;
 
     if (this._isReadingListItem == 0) {
+      // If we're in reader mode, we must have fetched the article.
+      this._article.status = gChromeWin.Reader.STATUS_FETCHED_ARTICLE;
       gChromeWin.Reader.addArticleToReadingList(this._article);
 
       UITelemetry.addEvent("save.1", "button", null, "reader");
     } else {
       Messaging.sendRequest({
         type: "Reader:RemoveFromList",
         url: this._article.url
       });